]> git.mxchange.org Git - friendica.git/blob - util/composer.phar
Merge pull request #4096 from annando/fix-pr-4095
[friendica.git] / util / 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\0a\!Z\ 5b\0\0¼cí߶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Autoload/ClassMapGenerator.php«\11\0\0a\!Z«\11\0\0\10ëÊ\9a\ 1\0\0\0\0\0\0\16\0\0\0src/Composer/Cache.phpt\13\0\0a\!Zt\13\0\0\0\11&#¶\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Command/AboutCommand.phpË\ 2\0\0a\!ZË\ 2\0\0º¡Ãh¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/ArchiveCommand.phpL\14\0\0a\!ZL\14\0\0\85\r;V¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/BaseCommand.phpÉ        \0\0a\!ZÉ \0\0\97P!£¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Command/BaseDependencyCommand.phpÉ\18\0\0a\!ZÉ\18\0\0D{²Ð¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Command/ClearCacheCommand.php]\ 5\0\0a\!Z]\ 5\0\0\1f\82ß´¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/ConfigCommand.php\aH\0\0a\!Z\aH\0\0\ fÃæ\ 5\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Command/CreateProjectCommand.php 5\0\0a\!Z 5\0\0\14\82Z\16\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/DependsCommand.php·\ 2\0\0a\!Z·\ 2\0\0o±¹ú¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/DiagnoseCommand.phpÍF\0\0a\!ZÍF\0\0²E>F¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Command/DumpAutoloadCommand.php¨       \0\0a\!Z¨ \0\0g/\94\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/ExecCommand.phpi\a\0\0a\!Zi\a\0\0\ 4\80\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/GlobalCommand.phpü\a\0\0a\!Zü\a\0\0ÝH\8f\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/HomeCommand.php\1f\ e\0\0a\!Z\1f\ e\0\0\16±¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/InitCommand.php¬A\0\0a\!Z¬A\0\0\ 3k&\89\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/InstallCommand.phpý\13\0\0a\!Zý\13\0\00ö:\89\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/LicensesCommand.php&\ e\0\0a\!Z&\ e\0\0Óv\83\1e\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/OutdatedCommand.php°
28 \0\0a\!Z°
29 \0\07àzk¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Command/ProhibitsCommand.phpË\ 2\0\0a\!ZË\ 2\0\0\1ag\8fð¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/RemoveCommand.php\91\15\0\0a\!Z\91\15\0\0\97ë\93\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/RequireCommand.php-\1f\0\0a\!Z-\1f\0\0ë\95\9f\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Command/RunScriptCommand.php \f\0\0a\!Z \f\0\0\ 3G\92\7f\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Command/ScriptAliasCommand.php\ 3\ 5\0\0a\!Z\ 3\ 5\0\0ÃJJü¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/SearchCommand.phpã\b\0\0a\!Zã\b\0\0ñ\v¼w¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Command/SelfUpdateCommand.phpï0\0\0a\!Zï0\0\0û­\ 3\f\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/ShowCommand.phpsf\0\0a\!Zsf\0\0bÄý^¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/StatusCommand.php/\15\0\0a\!Z/\15\0\0ôE\12\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/SuggestsCommand.php©\r\0\0a\!Z©\r\0\0\96º×U¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/UpdateCommand.php{"\0\0a\!Z{"\0\0e\8d­¸¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/ValidateCommand.php\18\14\0\0a\!Z\18\14\0\0lp\9c\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Composer.phpù  \0\0a\!Zù \0\0è\9f®(¶\ 1\0\0\0\0\0\0\17\0\0\0src/Composer/Config.phpÅ"\0\0a\!ZÅ"\0\0\9d¡¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Config/ConfigSourceInterface.php\ e\ 2\0\0a\!Z\ e\ 2\0\0³\f[/¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Config/JsonConfigSource.php!\13\0\0a\!Z!\13\0\0¾S\r\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Console/Application.phpä2\0\0a\!Zä2\0\0 ª5=¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Console/HtmlOutputFormatter.php3\ 6\0\0a\!Z3\ 6\0\0Ú\81Eu¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/DependencyResolver/Decisions.phpQ\ f\0\0a\!ZQ\ f\0\0?\98¬$¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/DefaultPolicy.php\ 2\17\0\0a\!Z\ 2\17\0\0õÝv\7f\ 1\0\0\0\0\0\0/\0\0\0src/Composer/DependencyResolver/GenericRule.php·\ 3\0\0a\!Z·\ 3\0\0Ì~¯³¶\ 1\0\0\0\0\0\0>\0\0\0src/Composer/DependencyResolver/Operation/InstallOperation.phpC\ 2\0\0a\!ZC\ 2\0\0´\õ*¶\ 1\0\0\0\0\0\0I\0\0\0src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php÷\ 2\0\0a\!Z÷\ 2\0\0ïÎà÷¶\ 1\0\0\0\0\0\0K\0\0\0src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.phpý\ 2\0\0a\!Zý\ 2\0\0\193#\86\ 1\0\0\0\0\0\0@\0\0\0src/Composer/DependencyResolver/Operation/OperationInterface.phpÓ\0\0\0a\!ZÓ\0\0\0Ùâ&ä¶\ 1\0\0\0\0\0\0=\0\0\0src/Composer/DependencyResolver/Operation/SolverOperation.php¹\ 1\0\0a\!Z¹\ 1\0\0&¢e
30\ 1\0\0\0\0\0\0@\0\0\0src/Composer/DependencyResolver/Operation/UninstallOperation.phpI\ 2\0\0a\!ZI\ 2\0\0FûÂɶ\ 1\0\0\0\0\0\0=\0\0\0src/Composer/DependencyResolver/Operation/UpdateOperation.phph\ 3\0\0a\!Zh\ 3\0\0öSÕ]¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/DependencyResolver/PolicyInterface.php­\ 1\0\0a\!Z­\ 1\0\0\18\9f\8b\ 1\0\0\0\0\0\0(\0\0\0src/Composer/DependencyResolver/Pool.php°"\0\0a\!Z°"\0\0\1d   \8e\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/Problem.php\99\16\0\0a\!Z\99\16\0\0\ 3´\87Ķ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/Request.php\83\ 4\0\0a\!Z\83\ 4\0\0åVP\84\ 1\0\0\0\0\0\0(\0\0\0src/Composer/DependencyResolver/Rule.php¶\18\0\0a\!Z¶\18\0\0Ú{\8d\8d\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/Rule2Literals.php§\ 4\0\0a\!Z§\ 4\0\0~Ð'ò¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/RuleSet.phpª
31 \0\0a\!Zª
32 \0\0\82\e\ 1\0\0\0\0\0\04\0\0\0src/Composer/DependencyResolver/RuleSetGenerator.phpO\e\0\0a\!ZO\e\0\0³Q[â¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/DependencyResolver/RuleSetIterator.php\14\ 6\0\0a\!Z\14\ 6\0\0}õÇù¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/DependencyResolver/RuleWatchChain.phpi\ 1\0\0a\!Zi\ 1\0\0\9a\ 1\0\0\0\0\0\02\0\0\0src/Composer/DependencyResolver/RuleWatchGraph.phpá\ 6\0\0a\!Zá\ 6\0\0\89rôv¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/RuleWatchNode.phpñ\ 3\0\0a\!Zñ\ 3\0\0ë\95\e\93\ 1\0\0\0\0\0\0*\0\0\0src/Composer/DependencyResolver/Solver.php\9f8\0\0a\!Z\9f8\0\0\1epöb¶\ 1\0\0\0\0\0\06\0\0\0src/Composer/DependencyResolver/SolverBugException.php\98\ 1\0\0a\!Z\98\ 1\0\0\7f"qN¶\ 1\0\0\0\0\0\0;\0\0\0src/Composer/DependencyResolver/SolverProblemsException.phpô\a\0\0a\!Zô\a\0\0×|Ŧ¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/DependencyResolver/Transaction.phpô\13\0\0a\!Zô\13\0\0cïTܶ\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Downloader/ArchiveDownloader.php¸\ e\0\0a\!Z¸\ e\0\0±°Y\b\ 1\0\0\0\0\0\01\0\0\0src/Composer/Downloader/ChangeReportInterface.phpÌ\0\0\0a\!ZÌ\0\0\0¯à¨¿¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Downloader/DownloadManager.phpG\15\0\0a\!ZG\15\0\0\8a(í»¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Downloader/DownloaderInterface.phpÊ\ 1\0\0a\!ZÊ\ 1\0\0gs!l¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Downloader/DvcsDownloaderInterface.phpÑ\0\0\0a\!ZÑ\0\0\0\9c¿¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/FileDownloader.phpì\17\0\0a\!Zì\17\0\04\1eø\ 1\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Downloader/FilesystemException.php
33 \ 1\0\0a\!Z
34 \ 1\0\0.-\1e\8b\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Downloader/FossilDownloader.php`\v\0\0a\!Z`\v\0\0ÿI©u¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/GitDownloader.php\9d3\0\0a\!Z\9d3\0\01mU¥¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/GzipDownloader.phpó\ 6\0\0a\!Zó\ 6\0\0}Úo¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Downloader/HgDownloader.php8 \0\0a\!Z8 \0\0ëyàn¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/PathDownloader.phpK\11\0\0a\!ZK\11\0\09\95&c¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/Downloader/PearPackageExtractor.phpu\e\0\0a\!Zu\e\0\0z\84\15\87\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Downloader/PerforceDownloader.phpÃ\a\0\0a\!ZÃ\a\0\0\1c\91Èý¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/PharDownloader.phpå\0\0\0a\!Zå\0\0\0ÞÉ\1fç¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/RarDownloader.php\9e\a\0\0a\!Z\9e\a\0\06      3U¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/SvnDownloader.phpG\11\0\0a\!ZG\11\0\0\86íV\96\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/TarDownloader.phpã\0\0\0a\!Zã\0\0\0Í\92X?¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Downloader/TransportException.php=\ 2\0\0a\!Z=\ 2\0\0ZÎÈÞ¶\ 1\0\0\0\0\0\09\0\0\0src/Composer/Downloader/VcsCapableDownloaderInterface.phpÔ\0\0\0a\!ZÔ\0\0\0`§ôö¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/VcsDownloader.php"\16\0\0a\!Z"\16\0\0\9c\1a\9f\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Downloader/XzDownloader.php§\ 4\0\0a\!Z§\ 4\0\0W$;á¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/ZipDownloader.php\98\13\0\0a\!Z\98\13\0\0\9b@\ 2ü¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/EventDispatcher/Event.php \ 2\0\0a\!Z \ 2\0\0±\99jï¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/EventDispatcher/EventDispatcher.phpß0\0\0a\!Zß0\0\0}f\18\a\ 1\0\0\0\0\0\09\0\0\0src/Composer/EventDispatcher/EventSubscriberInterface.php©\0\0\0a\!Z©\0\0\0\ 1\ 1\0\0\0\0\0\09\0\0\0src/Composer/EventDispatcher/ScriptExecutionException.phpv\0\0\0a\!Zv\0\0\0wZ8S¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Exception/NoSslException.phpf\0\0\0a\!Zf\0\0\0ËíM\9d\ 1\0\0\0\0\0\0\18\0\0\0src/Composer/Factory.phpS=\0\0a\!ZS=\0\0Fíж\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/IO/BaseIO.php\8c\10\0\0a\!Z\8c\10\0\0(\82l\91\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/IO/BufferIO.php*\ 4\0\0a\!Z*\ 4\0\0¢®hT¶\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/IO/ConsoleIO.php;\15\0\0a\!Z;\15\0\0Ê\17\9b\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/IO/IOInterface.phpì\ 5\0\0a\!Zì\ 5\0\0\0Õ\9d\ e\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/IO/NullIO.phpÀ\ 4\0\0a\!ZÀ\ 4\0\0F`sʶ\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/Installer.php}\9a\0\0a\!Z}\9a\0\0\ f¼)A¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/BinaryInstaller.php\10\13\0\0a\!Z\10\13\0\0\8dv÷j¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Installer/BinaryPresenceInterface.phpË\0\0\0a\!ZË\0\0\0À5\9a¨¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Installer/InstallationManager.php-\17\0\0a\!Z-\17\0\0¾}\8c\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Installer/InstallerEvent.php\ e\ 6\0\0a\!Z\ e\ 6\0\0lÔzi¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/InstallerEvents.phpÞ\0\0\0a\!ZÞ\0\0\0ì\9f@G¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Installer/InstallerInterface.phpã\ 2\0\0a\!Zã\ 2\0\0^\83\93ʶ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Installer/LibraryInstaller.php^\13\0\0a\!Z^\13\0\0\10\1aÍr¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Installer/MetapackageInstaller.php\9c\ 4\0\0a\!Z\9c\ 4\0\0Æ\12Å!¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/NoopInstaller.php+\ 5\0\0a\!Z+\ 5\0\0À·M}¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Installer/PackageEvent.phpe\ 3\0\0a\!Ze\ 3\0\0;° \1a\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/PackageEvents.php¸\ 1\0\0a\!Z¸\ 1\0\0dbØs¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Installer/PearBinaryInstaller.phpâ\f\0\0a\!Zâ\f\0\0;øiU¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/PearInstaller.php¢\a\0\0a\!Z¢\a\0\0È\82¶Ñ¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/PluginInstaller.php\9f\ 6\0\0a\!Z\9f\ 6\0\0<tú,¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Installer/ProjectInstaller.php\1d\ 6\0\0a\!Z\1d\ 6\0\0*0@P¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Installer/SuggestedPackagesReporter.php\10\a\0\0a\!Z\10\a\0\0+±]Ķ\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Json/JsonFile.php\ 3\14\0\0a\!Z\ 3\14\0\0VVN\15\ 1\0\0\0\0\0\0#\0\0\0src/Composer/Json/JsonFormatter.php\ 6\ 6\0\0a\!Z\ 6\ 6\0\0\1eÐqu¶\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Json/JsonManipulator.php¥2\0\0a\!Z¥2\0\0\96\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Json/JsonValidationException.php\\ 1\0\0a\!Z\\ 1\0\0.Xóܶ\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Package/AliasPackage.php\ 5\17\0\0a\!Z\ 5\17\0\0¹\97~\9a\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ArchivableFilesFilter.php       \ 2\0\0a\!Z \ 2\0\0yY+¦¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ArchivableFilesFinder.phpÞ\ 5\0\0a\!ZÞ\ 5\0\0\f²²¹¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/Package/Archiver/ArchiveManager.php°\f\0\0a\!Z°\f\0\0gþÒ)¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Package/Archiver/ArchiverInterface.php\a\ 1\0\0a\!Z\a\ 1\0\0ñ´>\v\ 1\0\0\0\0\0\03\0\0\0src/Composer/Package/Archiver/BaseExcludeFilter.php\96\ 6\0\0a\!Z\96\ 6\0\0y¶=ƶ\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ComposerExcludeFilter.php\1f\ 1\0\0a\!Z\1f\ 1\0\0\8bSZ0¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Package/Archiver/GitExcludeFilter.phpq\ 3\0\0a\!Zq\ 3\0\05¾i&¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/Archiver/HgExcludeFilter.php\13\ 5\0\0a\!Z\13\ 5\0\0~\94\ e¸¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Package/Archiver/PharArchiver.php>\ 6\0\0a\!Z>\ 6\0\0 5\89í¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Package/Archiver/ZipArchiver.php¼\ 4\0\0a\!Z¼\ 4\0\0\91XÝë¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Package/BasePackage.php&\r\0\0a\!Z&\r\0\0\e'\1fݶ\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Package/CompletePackage.phpü\ 6\0\0a\!Zü\ 6\0\0þM˶¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/CompletePackageInterface.phpõ\ 1\0\0a\!Zõ\ 1\0\0¦Ê\81ò¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Package/Dumper/ArrayDumper.phpë\v\0\0a\!Zë\v\0\0Ó8WE¶\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/Package/Link.php\88\ 5\0\0a\!Z\88\ 5\0\0å¶Y«¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/LinkConstraint/EmptyConstraint.php\82\ 1\0\0a\!Z\82\ 1\0\0\ eé~\8b\ 1\0\0\0\0\0\0?\0\0\0src/Composer/Package/LinkConstraint/LinkConstraintInterface.phpd\ 1\0\0a\!Zd\ 1\0\0¤ôLn¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/LinkConstraint/MultiConstraint.php\82\ 1\0\0a\!Z\82\ 1\0\0ób`ý¶\ 1\0\0\0\0\0\0:\0\0\0src/Composer/Package/LinkConstraint/SpecificConstraint.phpi\ 1\0\0a\!Zi\ 1\0\0Þ\94\9a\ 1\0\0\0\0\0\09\0\0\0src/Composer/Package/LinkConstraint/VersionConstraint.phpX\ 1\0\0a\!ZX\ 1\0\0\ 2}`y¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Package/Loader/ArrayLoader.php¸\1e\0\0a\!Z¸\1e\0\06\r¤\1d\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Loader/InvalidPackageException.phpE\ 2\0\0a\!ZE\ 2\0\0xb\13¾¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Package/Loader/JsonLoader.phpù\ 1\0\0a\!Zù\ 1\0\0!~\88\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Package/Loader/LoaderInterface.php²\0\0\0a\!Z²\0\0\0¦}úζ\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/Loader/RootPackageLoader.php$\17\0\0a\!Z$\17\0\0Ârü°¶\ 1\0\0\0\0\0\05\0\0\0src/Composer/Package/Loader/ValidatingArrayLoader.phpõ2\0\0a\!Zõ2\0\0ÞEY7¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Package/Locker.php©!\0\0a\!Z©!\0\0A\8aõë¶\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Package/Package.phpÉ\1a\0\0a\!ZÉ\1a\0\0\8f\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Package/PackageInterface.php \a\0\0a\!Z \a\0\0ûÇ^ƶ\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Package/RootAliasPackage.php\1f   \0\0a\!Z\1f \0\0      _\80ø¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Package/RootPackage.php\11\ 5\0\0a\!Z\11\ 5\0\0\ 2\8eÎ_¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Package/RootPackageInterface.php¹\ 3\0\0a\!Z¹\ 3\0\0"maV¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Package/Version/VersionGuesser.php_\1e\0\0a\!Z_\1e\0\0\12Ó¾\9e\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Package/Version/VersionParser.phpo\ 4\0\0a\!Zo\ 4\0\0ôÜ;Ô¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/Package/Version/VersionSelector.phpK\f\0\0a\!ZK\f\0\0²<\ fȶ\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Plugin/Capability/Capability.phpW\0\0\0a\!ZW\0\0\0æ_¨1¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Plugin/Capability/CommandProvider.php\97\0\0\0a\!Z\97\0\0\0ûOâ>¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Plugin/Capable.php\7f\0\0\0a\!Z\7f\0\0\0Æq\15\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Plugin/CommandEvent.phpâ\ 2\0\0a\!Zâ\ 2\0\0³ÆÇW¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Plugin/PluginEvents.phpÂ\0\0\0a\!ZÂ\0\0\0^Íþ\ 6\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Plugin/PluginInterface.phpô\0\0\0a\!Zô\0\0\0)'*ض\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Plugin/PluginManager.php\1f$\0\0a\!Z\1f$\0\0ë\8e"»¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Plugin/PreFileDownloadEvent.php`\ 2\0\0a\!Z`\ 2\0\0\09-ζ\ 1\0\0\0\0\0\04\0\0\0src/Composer/Question/StrictConfirmationQuestion.php\1e\ 5\0\0a\!Z\1e\ 5\0\0'.³è¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Repository/ArrayRepository.php\13\ e\0\0a\!Z\13\ e\0\0éÌt\0\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/ArtifactRepository.php»\f\0\0a\!Z»\f\0\0\88Ý÷<¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/BaseRepository.php_\r\0\0a\!Z_\r\0\0\96ûß\ e\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/ComposerRepository.php[T\0\0a\!Z[T\0\0¤uV1¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/CompositeRepository.php;\b\0\0a\!Z;\b\0\0¤¯S\1f\ 1\0\0\0\0\0\0;\0\0\0src/Composer/Repository/ConfigurableRepositoryInterface.php\85\0\0\0a\!Z\85\0\0\0±\9f_\1c\ 1\0\0\0\0\0\00\0\0\0src/Composer/Repository/FilesystemRepository.php×\ 4\0\0a\!Z×\ 4\0\0I\9cª\13\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/InstalledArrayRepository.php£\0\0\0a\!Z£\0\0\0/ö~>¶\ 1\0\0\0\0\0\09\0\0\0src/Composer/Repository/InstalledFilesystemRepository.php£\0\0\0a\!Z£\0\0\0V
35 \95\ 1\0\0\0\0\0\08\0\0\0src/Composer/Repository/InstalledRepositoryInterface.php\87\0\0\0a\!Z\87\0\0\0\18£9p¶\ 1\0\0\0\0\0\06\0\0\0src/Composer/Repository/InvalidRepositoryException.phpn\0\0\0a\!Zn\0\0\0à\93ë\98\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/PackageRepository.phpj\ 3\0\0a\!Zj\ 3\0\0¥ôò̶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/PathRepository.phpw
36 \0\0a\!Zw
37 \0\0\0~õ³¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Pear/BaseChannelReader.phpI\ 5\0\0a\!ZI\ 5\0\0c\b6³¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/ChannelInfo.phpÄ\ 1\0\0a\!ZÄ\ 1\0\0:T*ɶ\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/Pear/ChannelReader.phpí\ 6\0\0a\!Zí\ 6\0\0?ÈYT¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/Pear/ChannelRest10Reader.phpÁ \0\0a\!ZÁ \0\0\ 4O\80ë¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/Pear/ChannelRest11Reader.php& \0\0a\!Z& \0\0òUb\b\ 1\0\0\0\0\0\05\0\0\0src/Composer/Repository/Pear/DependencyConstraint.phpq\ 2\0\0a\!Zq\ 2\0\09\ e\17\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/Pear/DependencyInfo.phpq\ 1\0\0a\!Zq\ 1\0\0fºTò¶\ 1\0\0\0\0\0\08\0\0\0src/Composer/Repository/Pear/PackageDependencyParser.php\85\16\0\0a\!Z\85\16\0\0÷$Li¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/PackageInfo.php°\ 3\0\0a\!Z°\ 3\0\0\9f\r¸\f\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/ReleaseInfo.php\92\ 1\0\0a\!Z\92\ 1\0\0o\93\8aö\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/PearRepository.phpª\16\0\0a\!Zª\16\0\0)\9f\83\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/PlatformRepository.php\ 1\e\0\0a\!Z\ 1\e\0\0\ 3_Mì¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/RepositoryFactory.php\95\11\0\0a\!Z\95\11\0\0\80\83§\1d\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/RepositoryInterface.phpÛ\ 1\0\0a\!ZÛ\ 1\0\0\92\11âÁ¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/RepositoryManager.php,
38 \0\0a\!Z,
39 \0\0¾\85\\95\ 1\0\0\0\0\0\07\0\0\0src/Composer/Repository/RepositorySecurityException.phpo\0\0\0a\!Zo\0\0\0pÕ«ª¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/Vcs/BitbucketDriver.phpô\1e\0\0a\!Zô\1e\0\0\ 4x¤ü¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/FossilDriver.php \12\0\0a\!Z \12\0\0]\8bÉQ¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Vcs/GitBitbucketDriver.phpê\ 5\0\0a\!Zê\ 5\0\0Ã\8e»\14\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/GitDriver.phpØ\11\0\0a\!ZØ\11\0\0Ý"T̶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/GitHubDriver.phpz+\0\0a\!Zz+\0\0\13\1fÚb¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/GitLabDriver.php\9e"\0\0a\!Z\9e"\0\0Áé­û¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Repository/Vcs/HgBitbucketDriver.phpä\ 5\0\0a\!Zä\ 5\0\0i\9büà¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Repository/Vcs/HgDriver.phpe\12\0\0a\!Ze\12\0\0O!O\13\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/Vcs/PerforceDriver.phpO     \0\0a\!ZO \0\0@ËóN¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/SvnDriver.php\15\e\0\0a\!Z\15\e\0\0\1dÕzï¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/VcsDriver.phpæ
40 \0\0a\!Zæ
41 \0\0eׯ-¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Vcs/VcsDriverInterface.php÷\ 2\0\0a\!Z÷\ 2\0\0ÇX[\89\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/VcsRepository.php´\1e\0\0a\!Z´\1e\0\0\ 1ªÖG¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Repository/WritableArrayRepository.php\ f\ 3\0\0a\!Z\ f\ 3\0\0¾G\17\ 1\0\0\0\0\0\07\0\0\0src/Composer/Repository/WritableRepositoryInterface.php\89\ 1\0\0a\!Z\89\ 1\0\0\91/sï¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/CommandEvent.phpW\0\0\0a\!ZW\0\0\0£VZt¶\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/Script/Event.phpµ\ 2\0\0a\!Zµ\ 2\0\0lt¦M¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/PackageEvent.php\9c\0\0\0a\!Z\9c\0\0\0§ÿÉ\r\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/ScriptEvents.phpP\ 4\0\0a\!ZP\ 4\0\0\87\8f\ 4¶¶\ 1\0\0\0\0\0\0 \0\0\0src/Composer/SelfUpdate/Keys.php\9d\ 1\0\0a\!Z\9d\ 1\0\0\vîÊN¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/SelfUpdate/Versions.phpì\ 5\0\0a\!Zì\ 5\0\0͵\91\83\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Util/AuthHelper.phpË\ 3\0\0a\!ZË\ 3\0\0>zx\96\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/Bitbucket.php%\15\0\0a\!Z%\15\0\0n=gÓ¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Util/ComposerMirror.php±\ 4\0\0a\!Z±\ 4\0\0­½øض\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Util/ConfigValidator.phpu\12\0\0a\!Zu\12\0\0m\ 5áض\ 1\0\0\0\0\0\0"\0\0\0src/Composer/Util/ErrorHandler.php\87\ 4\0\0a\!Z\87\ 4\0\0He\1c\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Util/Filesystem.phps.\0\0a\!Zs.\0\0\9bÍ®à¶\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Git.phpn$\0\0a\!Zn$\0\05XÇ\ e\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/Util/GitHub.phpÏ
42 \0\0a\!ZÏ
43 \0\0ÁØ\å¶\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/Util/GitLab.php\99\f\0\0a\!Z\99\f\0\0\17BLF¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/IniHelper.php]\ 3\0\0a\!Z]\ 3\0\0®äéä¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Util/NoProxyPattern.php¾\ 6\0\0a\!Z¾\ 6\0\0Z+°m¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Perforce.php\1e2\0\0a\!Z\1e2\0\0­\ 65P¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Platform.phpü\ 4\0\0a\!Zü\ 4\0\0s­fç¶\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Util/ProcessExecutor.php\f\b\0\0a\!Z\f\b\0\0\88)sw¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Util/RemoteFilesystem.phpce\0\0a\!Zce\0\0°Qè;¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Silencer.phpò\ 2\0\0a\!Zò\ 2\0\0.\8e\7fܶ\ 1\0\0\0\0\0\0!\0\0\0src/Composer/Util/SpdxLicense.php\ 3\ 1\0\0a\!Z\ 3\ 1\0\0¾7
44 ñ¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Util/StreamContextFactory.phpÍ\ f\0\0a\!ZÍ\ f\0\0\8bK:8¶\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Svn.php¾\11\0\0a\!Z¾\11\0\0Ík\93ܶ\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/TlsHelper.phpp
45 \0\0a\!Zp
46 \0\0¤eÞæ¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/XdebugHandler.php\93\ f\0\0a\!Z\93\ f\0\0ÕWÖ>¶\ 1\0\0\0\0\0\0\11\0\0\0src/bootstrap.php¹\ 1\0\0a\!Z¹\ 1\0\0\15I}\9c\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Autoload/ClassLoader.php\8b4\0\0a\!Z\8b4\0\0Q\9f\94¼¶\ 1\0\0\0\0\0\0#\0\0\0res/composer-repository-schema.jsonð\ f\0\0a\!Zð\ f\0\0\81GÐà¶\ 1\0\0\0\0\0\0\18\0\0\0res/composer-schema.json_\93\0\0a\!Z_\93\0\0¤H\10õ¶\ 1\0\0\0\0\0\06\0\0\0vendor/composer/spdx-licenses/res/spdx-exceptions.jsoní\ 6\0\0a\!Zí\ 6\0\0ÆÅz±¶\ 1\0\0\0\0\0\04\0\0\0vendor/composer/spdx-licenses/res/spdx-licenses.jsonïf\0\0a\!Zïf\0\0"ï@\96\ 1\0\0\0\0\0\0*\0\0\0vendor/seld/cli-prompt/res/hiddeninput.exe\0$\0\0a\!Z\0$\0\0\95\8d¥v¶\ 1\0\0\0\0\0\0&\0\0\0vendor/symfony/console/Application.php¥V\0\0a\!Z¥V\0\0\15«8\88\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/console/Command/Command.php
47 #\0\0a\!Z
48 #\0\0\13¢\11Á¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Command/HelpCommand.phpÝ\a\0\0a\!ZÝ\a\0\0\99\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Command/ListCommand.phpZ\b\0\0a\!ZZ\b\0\0É£ \16\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/ConsoleEvents.phpï\0\0\0a\!Zï\0\0\0\rÕH¸¶\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/console/Descriptor/ApplicationDescription.phpß\b\0\0a\!Zß\b\0\0µ\8c°7¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Descriptor/Descriptor.php\9d\a\0\0a\!Z\9d\a\0\0\b;~Ķ\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/console/Descriptor/DescriptorInterface.phpü\0\0\0a\!Zü\0\0\0±Q\aµ¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Descriptor/JsonDescriptor.phpì\r\0\0a\!Zì\r\0\0á8-\8c\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Descriptor/MarkdownDescriptor.php¹\ e\0\0a\!Z¹\ e\0\0k\9f.a¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Descriptor/TextDescriptor.php\93\1e\0\0a\!Z\93\1e\0\0»]Ïø¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Descriptor/XmlDescriptor.php\ f\1c\0\0a\!Z\ f\1c\0\0\ 4\8bP$¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Event/ConsoleCommandEvent.php²\ 1\0\0a\!Z²\ 1\0\0Zk\89\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Event/ConsoleEvent.phpÅ\ 2\0\0a\!ZÅ\ 2\0\0ÒxÛ\¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Event/ConsoleExceptionEvent.php\12\ 3\0\0a\!Z\12\ 3\0\0á\162é¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Event/ConsoleTerminateEvent.phpz\ 2\0\0a\!Zz\ 2\0\0³,îL¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Exception/CommandNotFoundException.phpÔ\ 1\0\0a\!ZÔ\ 1\0\0È÷ L¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/console/Exception/ExceptionInterface.phpf\0\0\0a\!Zf\0\0\0¡ABª¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Exception/InvalidArgumentException.php¦\0\0\0a\!Z¦\0\0\0Ö̽Z¶\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/console/Exception/InvalidOptionException.php¦\0\0\0a\!Z¦\0\0\0\13Ë×H¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Exception/LogicException.php\92\0\0\0a\!Z\92\0\0\0ÍO\e¶\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/console/Exception/RuntimeException.php\96\0\0\0a\!Z\96\0\0\0Ùí,6¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Formatter/OutputFormatter.php\f\ e\0\0a\!Z\f\ e\0\0\83á&B¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Formatter/OutputFormatterInterface.php\8c\ 1\0\0a\!Z\8c\ 1\0\0òññÀ¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyle.phpL\10\0\0a\!ZL\10\0\0\8a\908<¶\ 1\0\0\0\0\0\0B\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php\86\ 1\0\0a\!Z\86\ 1\0\0ÝRÚ­¶\ 1\0\0\0\0\0\0>\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyleStack.phpL\ 5\0\0a\!ZL\ 5\0\0.=\16\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Helper/DebugFormatterHelper.phpx\b\0\0a\!Zx\b\0\0N©Ø¼¶\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Helper/DescriptorHelper.phpz\ 5\0\0a\!Zz\ 5\0\0fÉÚý¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Helper/DialogHelper.phpú\1e\0\0a\!Zú\1e\0\0hX\8fö\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Helper/FormatterHelper.phpc\ 4\0\0a\!Zc\ 4\0\0\93ý«N¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/Helper/Helper.php¬\a\0\0a\!Z¬\a\0\0OÜs¢¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Helper/HelperInterface.phpç\0\0\0a\!Zç\0\0\0 \18Çã¶\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Helper/HelperSet.phpÐ\a\0\0a\!ZÐ\a\0\0a\88~\r\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Helper/InputAwareHelper.phpc\ 1\0\0a\!Zc\ 1\0\0ñø\90\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Helper/ProcessHelper.phpÑ     \0\0a\!ZÑ \0\0@±ã\81\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Helper/ProgressBar.phps%\0\0a\!Zs%\0\0鯦\81\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/ProgressHelper.php\\e\0\0a\!Z\\e\0\0\12?\8bá¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Helper/ProgressIndicator.phpK\14\0\0a\!ZK\14\0\0í\1cÍ°¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/QuestionHelper.php\7f\e\0\0a\!Z\7f\e\0\0a4Íý¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/console/Helper/SymfonyQuestionHelper.phpl
49 \0\0a\!Zl
50 \0\0\1e÷ÞL¶\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/console/Helper/Table.php¢*\0\0a\!Z¢*\0\0\0\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Helper/TableCell.php\87\ 3\0\0a\!Z\87\ 3\0\0¨*æ\18\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Helper/TableHelper.php\13\f\0\0a\!Z\13\f\0\0¦pm\87\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/TableSeparator.phpÍ\0\0\0a\!ZÍ\0\0\0Qßa²¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Helper/TableStyle.php\1f
51 \0\0a\!Z\1f
52 \0\0PÞµ¦¶\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/console/Input/ArgvInput.php\14\15\0\0a\!Z\14\15\0\0¯Ü\10\9c\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Input/ArrayInput.php_
53 \0\0a\!Z_
54 \0\0[µðɶ\ 1\0\0\0\0\0\0&\0\0\0vendor/symfony/console/Input/Input.phpª\v\0\0a\!Zª\v\0\0\ 3\1a\1f¶¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Input/InputArgument.php\12\ 6\0\0a\!Z\12\ 6\0\0ÁÜ\17\90\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Input/InputAwareInterface.php\9a\0\0\0a\!Z\9a\0\0\0\87jT\9f\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Input/InputDefinition.php\96\19\0\0a\!Z\96\19\0\00Oly¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Input/InputInterface.php\9f\ 3\0\0a\!Z\9f\ 3\0\0¥R6Û¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Input/InputOption.php\1c\f\0\0a\!Z\1c\f\0\0\87¹§\7f\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Input/StringInput.php\98\ 6\0\0a\!Z\98\ 6\0\0 \1dÚ¤¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/console/LICENSE)\ 4\0\0a\!Z)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Logger/ConsoleLogger.php< \0\0a\!Z< \0\0:âÇl¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Output/BufferedOutput.phpb\ 1\0\0a\!Zb\ 1\0\0çA?¦¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Output/ConsoleOutput.phpµ\a\0\0a\!Zµ\a\0\0
55 ¢S\¶\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Output/ConsoleOutputInterface.phpå\0\0\0a\!Zå\0\0\0rNô\0\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Output/NullOutput.phpÏ\ 3\0\0a\!ZÏ\ 3\0\0®\98\8b\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/Output/Output.php\9a    \0\0a\!Z\9a \0\001 ý¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Output/OutputInterface.php\1c\ 3\0\0a\!Z\1c\ 3\0\0\1aÓÚ>¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Output/StreamOutput.phpÄ\ 5\0\0a\!ZÄ\ 5\0\0õ\1aí\95\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Question/ChoiceQuestion.phpy
56 \0\0a\!Zy
57 \0\0.\ f\Q¶\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Question/ConfirmationQuestion.phpé\ 2\0\0a\!Zé\ 2\0\0\83\17Q@¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Question/Question.php#
58 \0\0a\!Z#
59 \0\0e¯ \ e\ 1\0\0\0\0\0\0 \0\0\0vendor/symfony/console/Shell.phpé\ f\0\0a\!Zé\ f\0\0½fü\91\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Style/OutputStyle.php_\ 5\0\0a\!Z_\ 5\0\0\ 4û\ 5µ¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Style/StyleInterface.phpÔ\ 3\0\0a\!ZÔ\ 3\0\0 ßÊj¶\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Style/SymfonyStyle.php¼\1f\0\0a\!Z¼\1f\0\0öÅPg¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Tester/ApplicationTester.phpÔ\ 5\0\0a\!ZÔ\ 5\0\0¬ì¤d¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Tester/CommandTester.php¯\ 6\0\0a\!Z¯\ 6\0\0{8"÷¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/debug/BufferingLogger.phpt\ 1\0\0a\!Zt\ 1\0\0=\0hܶ\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/debug/Debug.phpé\ 2\0\0a\!Zé\ 2\0\0Àxa?¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/debug/DebugClassLoader.phpï\1d\0\0a\!Zï\1d\0\0ß<§ê¶\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/debug/ErrorHandler.php\80C\0\0a\!Z\80C\0\0¥æõ¾¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/debug/Exception/ClassNotFoundException.php\84\ 1\0\0a\!Z\84\ 1\0\0n\90¡\85\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/debug/Exception/ContextErrorException.php\98\ 1\0\0a\!Z\98\ 1\0\0-
60 d2¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/debug/Exception/DummyException.php\ 2\ 1\0\0a\!Z\ 2\ 1\0\0-"ûd¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/debug/Exception/FatalErrorException.phpï\ 6\0\0a\!Zï\ 6\0\0æ\ffz¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/debug/Exception/FatalThrowableError.phpD\ 2\0\0a\!ZD\ 2\0\0¡\fÂí¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/debug/Exception/FlattenException.php²\16\0\0a\!Z²\16\0\0HòÑ\ f\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/debug/Exception/OutOfMemoryException.php~\0\0\0a\!Z~\0\0\0ë¨oâ¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/debug/Exception/UndefinedFunctionException.php\88\ 1\0\0a\!Z\88\ 1\0\0¢G\82\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/debug/Exception/UndefinedMethodException.php\86\ 1\0\0a\!Z\86\ 1\0\0¨LÚ:¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/debug/ExceptionHandler.php\1f3\0\0a\!Z\1f3\0\0%\E\17\ 1\0\0\0\0\0\0I\0\0\0vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php7\12\0\0a\!Z7\12\0\0Ñj/=¶\ 1\0\0\0\0\0\0E\0\0\0vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php\ 3\ 1\0\0a\!Z\ 3\ 1\0\0ĹBV¶\ 1\0\0\0\0\0\0M\0\0\0vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.phpu\b\0\0a\!Zu\b\0\0éj\ 3\19\ 1\0\0\0\0\0\0K\0\0\0vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.phpN\ 5\0\0a\!ZN\ 5\0\0Ço-ç¶\ 1\0\0\0\0\0\0\1c\0\0\0vendor/symfony/debug/LICENSE)\ 4\0\0a\!Z)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/filesystem/Exception/ExceptionInterface.phpi\0\0\0a\!Zi\0\0\0$ ÿ\9b\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/filesystem/Exception/FileNotFoundException.php¼\ 1\0\0a\!Z¼\ 1\0\0pí\¶¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/filesystem/Exception/IOException.php\87\ 1\0\0a\!Z\87\ 1\0\0\80ü#Ѷ\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/filesystem/Exception/IOExceptionInterface.php¦\0\0\0a\!Z¦\0\0\0jÙwM¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/filesystem/Filesystem.php¦1\0\0a\!Z¦1\0\0\8dò\86\ 1\0\0\0\0\0\0!\0\0\0vendor/symfony/filesystem/LICENSE)\ 4\0\0a\!Z)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/filesystem/LockHandler.php¢\ 5\0\0a\!Z¢\ 5\0\0D\91;i¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/finder/Adapter/AbstractAdapter.php\\v\0\0a\!Z\\v\0\0Æ\93É\80\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Adapter/AbstractFindAdapter.php\91\19\0\0a\!Z\91\19\0\0ao¦È¶\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/finder/Adapter/AdapterInterface.php±\ 3\0\0a\!Z±\ 3\0\0ä»Ê&¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/finder/Adapter/BsdFindAdapter.php2\a\0\0a\!Z2\a\0\0Q/ÇC¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/finder/Adapter/GnuFindAdapter.php\15\a\0\0a\!Z\15\a\0\0\r\17¡¾¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/finder/Adapter/PhpAdapter.phpô\a\0\0a\!Zô\a\0\0\16\1d:?¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/finder/Comparator/Comparator.php\8c\ 3\0\0a\!Z\8c\ 3\0\0\16wþT¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Comparator/DateComparator.php%\ 3\0\0a\!Z%\ 3\0\0L¿EǶ\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Comparator/NumberComparator.php~\ 3\0\0a\!Z~\ 3\0\0\94\87 x¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Exception/AccessDeniedException.php\84\0\0\0a\!Z\84\0\0\0½¾s\9c\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/finder/Exception/AdapterFailureException.php¯\ 2\0\0a\!Z¯\ 2\0\0\9côÔÁ¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/finder/Exception/ExceptionInterface.php\84\0\0\0a\!Z\84\0\0\0\1cGz-¶\ 1\0\0\0\0\0\0A\0\0\0vendor/symfony/finder/Exception/OperationNotPermitedException.php)\ 1\0\0a\!Z)\ 1\0\0ìcj=¶\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/finder/Exception/ShellCommandFailureException.phpÂ\ 2\0\0a\!ZÂ\ 2\0\0\19v\82ȶ\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/finder/Expression/Expression.php\a\ 6\0\0a\!Z\a\ 6\0\0µoÔ\ 6\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/finder/Expression/Glob.phpi\ 4\0\0a\!Zi\ 4\0\0@\8a\eº¶\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/finder/Expression/Regex.php\ 6\ f\0\0a\!Z\ 6\ f\0\0p8\0\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Expression/ValueInterface.phpÍ\ 1\0\0a\!ZÍ\ 1\0\0²~øb¶\ 1\0\0\0\0\0\0 \0\0\0vendor/symfony/finder/Finder.phpÂ-\0\0a\!ZÂ-\0\0\1e\98f´¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/finder/Glob.phpK\ 5\0\0a\!ZK\ 5\0\0já±n¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/finder/Iterator/CustomFilterIterator.php]\ 2\0\0a\!Z]\ 2\0\0tà±µ¶\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/finder/Iterator/DateRangeFilterIterator.phpz\ 2\0\0a\!Zz\ 2\0\0ÂT-\ 5\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/finder/Iterator/DepthRangeFilterIterator.phpð\ 1\0\0a\!Zð\ 1\0\0ß0\99\ 4\ 1\0\0\0\0\0\0A\0\0\0vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.phpï\ 5\0\0a\!Zï\ 5\0\0¾\8dÒâ¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/finder/Iterator/FilePathsIterator.php \ 6\0\0a\!Z \ 6\0\0fQCe¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Iterator/FileTypeFilterIterator.php\\ 2\0\0a\!Z\\ 2\0\0p\91'\98\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/finder/Iterator/FilecontentFilterIterator.php5\ 2\0\0a\!Z5\ 2\0\0\9aí\1f\14\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Iterator/FilenameFilterIterator.phpr\ 1\0\0a\!Zr\ 1\0\0t\b\1a\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/finder/Iterator/FilterIterator.phpÃ\ 2\0\0a\!ZÃ\ 2\0\0\9a+µÞ¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php/\ 5\0\0a\!Z/\ 5\0\0»Ç\1f\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Iterator/PathFilterIterator.phpÏ\ 1\0\0a\!ZÏ\ 1\0\0º\1cªÇ¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php\15   \0\0a\!Z\15 \0\0ìt\90¶¶\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/finder/Iterator/SizeRangeFilterIterator.phpg\ 2\0\0a\!Zg\ 2\0\0\97é¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Iterator/SortableIterator.php,\ 6\0\0a\!Z,\ 6\0\0\96\1c\ 1\0\0\0\0\0\0\1d\0\0\0vendor/symfony/finder/LICENSE)\ 4\0\0a\!Z)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/finder/Shell/Command.phpS\v\0\0a\!ZS\v\0\0cC\85\99\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/finder/Shell/Shell.phpp\ 4\0\0a\!Zp\ 4\0\0\18Ó}g¶\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/finder/SplFileInfo.phpÿ\ 2\0\0a\!Zÿ\ 2\0\0Ë\rOÀ¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/polyfill-mbstring/LICENSE)\ 4\0\0a\!Z)\ 4\0\0î*L\14\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/polyfill-mbstring/Mbstring.phpÄ6\0\0a\!ZÄ6\0\0U.\17ݶ\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php2A\0\0a\!Z2A\0\0½\11=¨¶\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php¡A\0\0a\!Z¡A\0\0\ eÚ    Í¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/polyfill-mbstring/bootstrap.php±\ f\0\0a\!Z±\ f\0\0|\8a©Ò¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/process/Exception/ExceptionInterface.phpf\0\0\0a\!Zf\0\0\0]ö>T¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/process/Exception/InvalidArgumentException.php¨\0\0\0a\!Z¨\0\0\0ÐÀ+_¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/process/Exception/LogicException.php\94\0\0\0a\!Z\94\0\0\0 ³ãñ¶\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/process/Exception/ProcessFailedException.phpx\ 3\0\0a\!Zx\ 3\0\0¨Ìzy¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/process/Exception/ProcessTimedOutException.php\1f\ 4\0\0a\!Z\1f\ 4\0\0.     Ãá¶\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/process/Exception/RuntimeException.php\98\0\0\0a\!Z\98\0\0\0¢\eØ:¶\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/process/ExecutableFinder.php\9b\ 4\0\0a\!Z\9b\ 4\0\0ý\82m\9b\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/process/LICENSE)\ 4\0\0a\!Z)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/process/PhpExecutableFinder.phpg\ 4\0\0a\!Zg\ 4\0\0\8dçµ\ 6\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/process/PhpProcess.phpü\ 3\0\0a\!Zü\ 3\0\0_\17\97\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/process/Pipes/AbstractPipes.php^\a\0\0a\!Z^\a\0\0%s\85ï¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/process/Pipes/PipesInterface.phpD\ 1\0\0a\!ZD\ 1\0\0vØ\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/process/Pipes/UnixPipes.phpå\a\0\0a\!Zå\a\0\0\ 1È¥\ 4\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/process/Pipes/WindowsPipes.php\8d\v\0\0a\!Z\8d\v\0\0\85®\1e\ 1\0\0\0\0\0\0"\0\0\0vendor/symfony/process/Process.php§R\0\0a\!Z§R\0\0+Á¥\1f\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/process/ProcessBuilder.phpã
61 \0\0a\!Zã
62 \0\0ʧ°\88\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/process/ProcessUtils.phpK\ 6\0\0a\!ZK\ 6\0\0µ½~ò¶\ 1\0\0\0\0\0\0\1c\0\0\0vendor/seld/jsonlint/LICENSE"\ 4\0\0a\!Z"\ 4\0\0a\83sy¶\ 1\0\0\0\0\0\0@\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/DuplicateKeyException.php*\ 1\0\0a\!Z*\ 1\0\0\19\95pñ¶\ 1\0\0\0\0\0\05\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/JsonParser.php/2\0\0a\!Z/2\0\0­ß\98ö¶\ 1\0\0\0\0\0\00\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/Lexer.php\ 6\ f\0\0a\!Z\ 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\0a\!Z\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\0a\!Z>\0\0\0ÿq\9f\9f\ 1\0\0\0\0\0\0\1e\0\0\0vendor/seld/cli-prompt/LICENSE"\ 4\0\0a\!Z"\ 4\0\0\88ñ?e¶\ 1\0\0\0\0\0\0&\0\0\0vendor/seld/cli-prompt/res/example.php'\ 1\0\0a\!Z'\ 1\0\0I\1c\ 5£¶\ 1\0\0\0\0\0\0(\0\0\0vendor/seld/cli-prompt/src/CliPrompt.phpC\ 6\0\0a\!ZC\ 6\0\0Ð}\8d\ 1\0\0\0\0\0\0(\0\0\0vendor/justinrainbow/json-schema/LICENSE \ 4\0\0a\!Z \ 4\0\0ºç\ 6©¶\ 1\0\0\0\0\0\0.\0\0\0vendor/justinrainbow/json-schema/demo/demo.phpñ\ 1\0\0a\!Zñ\ 1\0\0f\e\12\ 1\0\0\0\0\0\0N\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/BaseConstraint.php¡      \0\0a\!Z¡ \0\0\86wÌl¶\ 1\0\0\0\0\0\0T\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php.\r\0\0a\!Z.\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\0a\!Z\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\0a\!Z¼\ 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\0a\!Z]\ 3\0\0V\8eU<¶\ 1\0\0\0\0\0\0G\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php;\r\0\0a\!Z;\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\0a\!Z\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
63 \0\0a\!Z\9a
64 \0\0\15\1ez&¶\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ObjectConstraint.phpÃ\11\0\0a\!ZÃ\11\0\0©Å¼x¶\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.phpN \0\0a\!ZN \0\0QÓmV¶\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php\7f\ 4\0\0a\!Z\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\0a\!Za\ 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\0a\!Zp\ 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\0a\!Z\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\0a\!Z&\ 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\0a\!Z\ 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\0a\!Zè\ 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\0a\!ZI\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\0a\!Z\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\0a\!Zl\0\0\0A!L׶\ 1\0\0\0\0\0\0T\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaException.phpl\0\0\0a\!Zl\0\0\0è2÷þ¶\ 1\0\0\0\0\0\0]\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.phpu\0\0\0a\!Zu\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\0a\!Zw\0\0\0N-ò[¶\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.phpÞ\ 2\0\0a\!ZÞ\ 2\0\0\r
65\ 1\0\0\0\0\0\0W\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ResourceNotFoundException.phpo\0\0\0a\!Zo\0\0\0píÛù¶\ 1\0\0\0\0\0\0N\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/RuntimeException.php\85\0\0\0a\!Z\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\0a\!Z\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\0a\!Zj\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\0a\!Zf\0\0\0¬¤\84þ¶\ 1\0\0\0\0\0\0K\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Iterator/ObjectIterator.phpþ\ 5\0\0a\!Zþ\ 5\0\0M\8f\84õ¶\ 1\0\0\0\0\0\0;\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Rfc3339.php \ 2\0\0a\!Z \ 2\0\0f4÷³¶\ 1\0\0\0\0\0\0A\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php\84\f\0\0a\!Z\84\f\0\0Nt³è¶\ 1\0\0\0\0\0\0J\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorageInterface.php\ 1\ 1\0\0a\!Z\ 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\0a\!Zá\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\0a\!Z¥\ 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\0a\!Z%\ 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\0a\!Z,\ 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\0a\!Z®\0\0\0ÿ\8bÁå¶\ 1\0\0\0\0\0\0C\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php\96  \0\0a\!Z\96 \0\0=&ßͶ\ 1\0\0\0\0\0\0D\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php&\13\0\0a\!Z&\13\0\0¼î\82¢¶\ 1\0\0\0\0\0\0H\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/UriResolverInterface.php\83\0\0\0a\!Z\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\0a\!Z\85\0\0\0íæ\e\ 1\0\0\0\0\0\0=\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Validator.phpn\ 5\0\0a\!Zn\ 5\0\0\90Ñ|§¶\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/spdx-licenses/LICENSE\1c\ 4\0\0a\!Z\1c\ 4\0\0\ 6Bhí¶\ 1\0\0\0\0\0\02\0\0\0vendor/composer/spdx-licenses/src/SpdxLicenses.phpç\11\0\0a\!Zç\11\0\0·\96U ¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/composer/semver/LICENSE\1c\ 4\0\0a\!Z\1c\ 4\0\0\ 6Bhí¶\ 1\0\0\0\0\0\0)\0\0\0vendor/composer/semver/src/Comparator.php\ 2\ 4\0\0a\!Z\ 2\ 4\0\0wl\83ï¶\ 1\0\0\0\0\0\0<\0\0\0vendor/composer/semver/src/Constraint/AbstractConstraint.php×\ 2\0\0a\!Z×\ 2\0\0õî>\8e\ 1\0\0\0\0\0\04\0\0\0vendor/composer/semver/src/Constraint/Constraint.phpª\f\0\0a\!Zª\f\0\0ÇO7²¶\ 1\0\0\0\0\0\0=\0\0\0vendor/composer/semver/src/Constraint/ConstraintInterface.phpß\0\0\0a\!Zß\0\0\00C,\87\ 1\0\0\0\0\0\09\0\0\0vendor/composer/semver/src/Constraint/EmptyConstraint.phpé\ 1\0\0a\!Zé\ 1\0\0!-Ø\99\ 1\0\0\0\0\0\09\0\0\0vendor/composer/semver/src/Constraint/MultiConstraint.php1\ 5\0\0a\!Z1\ 5\0\0í xU¶\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/semver/src/Semver.phpv\ 6\0\0a\!Zv\ 6\0\0\8b×È\9b\ 1\0\0\0\0\0\0,\0\0\0vendor/composer/semver/src/VersionParser.php¿*\0\0a\!Z¿*\0\0\13)mƶ\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/ca-bundle/LICENSE\1c\ 4\0\0a\!Z\1c\ 4\0\0*!^`¶\ 1\0\0\0\0\0\0*\0\0\0vendor/composer/ca-bundle/src/CaBundle.php½\e\0\0a\!Z½\e\0\0e\1c\e\1e\ 1\0\0\0\0\0\0\16\0\0\0vendor/psr/log/LICENSE=\ 4\0\0a\!Z=\ 4\0\0\8e\ 1\0\0\0\0\0\0)\0\0\0vendor/psr/log/Psr/Log/AbstractLogger.php;\ 4\0\0a\!Z;\ 4\0\0ñ>3[¶\ 1\0\0\0\0\0\03\0\0\0vendor/psr/log/Psr/Log/InvalidArgumentException.php`\0\0\0a\!Z`\0\0\0 \88X1¶\ 1\0\0\0\0\0\0#\0\0\0vendor/psr/log/Psr/Log/LogLevel.phpû\0\0\0a\!Zû\0\0\0jðñ8¶\ 1\0\0\0\0\0\0/\0\0\0vendor/psr/log/Psr/Log/LoggerAwareInterface.php|\0\0\0a\!Z|\0\0\0$\13£\88\ 1\0\0\0\0\0\0+\0\0\0vendor/psr/log/Psr/Log/LoggerAwareTrait.php§\0\0\0a\!Z§\0\0\0T½úB¶\ 1\0\0\0\0\0\0*\0\0\0vendor/psr/log/Psr/Log/LoggerInterface.phpÆ\ 2\0\0a\!ZÆ\ 2\0\0»\12sg¶\ 1\0\0\0\0\0\0&\0\0\0vendor/psr/log/Psr/Log/LoggerTrait.phpi\ 4\0\0a\!Zi\ 4\0\035§Þ¶\ 1\0\0\0\0\0\0%\0\0\0vendor/psr/log/Psr/Log/NullLogger.php\9e\0\0\0a\!Z\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\0a\!Zü\f\0\0iq0ض\ 1\0\0\0\0\0\0\13\0\0\0vendor/autoload.php\82\0\0\0a\!Z\82\0\0\0O4o\87\ 1\0\0\0\0\0\0'\0\0\0vendor/composer/autoload_namespaces.phpd\0\0\0a\!Zd\0\0\0Z¡¦H¶\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/autoload_psr4.php\98\ 4\0\0a\!Z\98\ 4\0\0\9e\1c{¢¶\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/autoload_classmap.phpd\0\0\0a\!Zd\0\0\0Z¡¦H¶\ 1\0\0\0\0\0\0"\0\0\0vendor/composer/autoload_files.phpÃ\0\0\0a\!ZÃ\0\0\0ÒÂür¶\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/autoload_real.phpI\a\0\0a\!ZI\a\0\0þ\13V'¶\ 1\0\0\0\0\0\0#\0\0\0vendor/composer/autoload_static.php¬ \0\0a\!Z¬ \0\0\10ó\18\ 1\0\0\0\0\0\0\1f\0\0\0vendor/composer/ClassLoader.php\9c\18\0\0a\!Z\9c\18\0\0¥ÂåN¶\ 1\0\0\0\0\0\0(\0\0\0vendor/composer/ca-bundle/res/cacert.pem\bè\ 3\0a\!Z\bè\ 3\0x85ú¶\ 1\0\0\0\0\0\0\f\0\0\0bin/composer\8b\ 5\0\0a\!Z\8b\ 5\0\0íeG\9a\ 1\0\0\0\0\0\0\a\0\0\0LICENSE.\ 4\0\0a\!Z.\ 4\0\0 Õ\b\ 3\ 1\0\0\0\0\0\0<?php
66
67
68
69
70
71
72
73
74
75
76
77 namespace Composer\Autoload;
78
79 use Composer\Config;
80 use Composer\EventDispatcher\EventDispatcher;
81 use Composer\Installer\InstallationManager;
82 use Composer\IO\IOInterface;
83 use Composer\Package\AliasPackage;
84 use Composer\Package\PackageInterface;
85 use Composer\Repository\InstalledRepositoryInterface;
86 use Composer\Util\Filesystem;
87 use Composer\Script\ScriptEvents;
88
89
90
91
92
93 class AutoloadGenerator
94 {
95
96
97
98 private $eventDispatcher;
99
100
101
102
103 private $io;
104
105
106
107
108 private $devMode = false;
109
110
111
112
113 private $classMapAuthoritative = false;
114
115
116
117
118 private $apcu = false;
119
120
121
122
123 private $runScripts = false;
124
125 public function __construct(EventDispatcher $eventDispatcher, IOInterface $io = null)
126 {
127 $this->eventDispatcher = $eventDispatcher;
128 $this->io = $io;
129 }
130
131 public function setDevMode($devMode = true)
132 {
133 $this->devMode = (bool) $devMode;
134 }
135
136
137
138
139
140
141
142 public function setClassMapAuthoritative($classMapAuthoritative)
143 {
144 $this->classMapAuthoritative = (bool) $classMapAuthoritative;
145 }
146
147
148
149
150
151
152 public function setApcu($apcu)
153 {
154 $this->apcu = (bool) $apcu;
155 }
156
157
158
159
160
161
162 public function setRunScripts($runScripts = true)
163 {
164 $this->runScripts = (bool) $runScripts;
165 }
166
167 public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsr0Packages = false, $suffix = '')
168 {
169 if ($this->classMapAuthoritative) {
170
171  $scanPsr0Packages = true;
172 }
173 if ($this->runScripts) {
174 $this->eventDispatcher->dispatchScript(ScriptEvents::PRE_AUTOLOAD_DUMP, $this->devMode, array(), array(
175 'optimize' => (bool) $scanPsr0Packages,
176 ));
177 }
178
179 $filesystem = new Filesystem();
180 $filesystem->ensureDirectoryExists($config->get('vendor-dir'));
181
182  
183  
184  $basePath = $filesystem->normalizePath(realpath(realpath(getcwd())));
185 $vendorPath = $filesystem->normalizePath(realpath(realpath($config->get('vendor-dir'))));
186 $useGlobalIncludePath = (bool) $config->get('use-include-path');
187 $prependAutoloader = $config->get('prepend-autoloader') === false ? 'false' : 'true';
188 $targetDir = $vendorPath.'/'.$targetDir;
189 $filesystem->ensureDirectoryExists($targetDir);
190
191 $vendorPathCode = $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true);
192 $vendorPathCode52 = str_replace('__DIR__', 'dirname(__FILE__)', $vendorPathCode);
193 $vendorPathToTargetDirCode = $filesystem->findShortestPathCode($vendorPath, realpath($targetDir), true);
194
195 $appBaseDirCode = $filesystem->findShortestPathCode($vendorPath, $basePath, true);
196 $appBaseDirCode = str_replace('__DIR__', '$vendorDir', $appBaseDirCode);
197
198 $namespacesFile = <<<EOF
199 <?php
200
201 // autoload_namespaces.php @generated by Composer
202
203 \$vendorDir = $vendorPathCode52;
204 \$baseDir = $appBaseDirCode;
205
206 return array(
207
208 EOF;
209
210 $psr4File = <<<EOF
211 <?php
212
213 // autoload_psr4.php @generated by Composer
214
215 \$vendorDir = $vendorPathCode52;
216 \$baseDir = $appBaseDirCode;
217
218 return array(
219
220 EOF;
221
222
223  $packageMap = $this->buildPackageMap($installationManager, $mainPackage, $localRepo->getCanonicalPackages());
224 $autoloads = $this->parseAutoloads($packageMap, $mainPackage);
225
226
227  foreach ($autoloads['psr-0'] as $namespace => $paths) {
228 $exportedPaths = array();
229 foreach ($paths as $path) {
230 $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
231 }
232 $exportedPrefix = var_export($namespace, true);
233 $namespacesFile .= "    $exportedPrefix => ";
234 $namespacesFile .= "array(".implode(', ', $exportedPaths)."),\n";
235 }
236 $namespacesFile .= ");\n";
237
238
239  foreach ($autoloads['psr-4'] as $namespace => $paths) {
240 $exportedPaths = array();
241 foreach ($paths as $path) {
242 $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
243 }
244 $exportedPrefix = var_export($namespace, true);
245 $psr4File .= "    $exportedPrefix => ";
246 $psr4File .= "array(".implode(', ', $exportedPaths)."),\n";
247 }
248 $psr4File .= ");\n";
249
250 $classmapFile = <<<EOF
251 <?php
252
253 // autoload_classmap.php @generated by Composer
254
255 \$vendorDir = $vendorPathCode52;
256 \$baseDir = $appBaseDirCode;
257
258 return array(
259
260 EOF;
261
262
263  $targetDirLoader = null;
264 $mainAutoload = $mainPackage->getAutoload();
265 if ($mainPackage->getTargetDir() && !empty($mainAutoload['psr-0'])) {
266 $levels = count(explode('/', $filesystem->normalizePath($mainPackage->getTargetDir())));
267 $prefixes = implode(', ', array_map(function ($prefix) {
268 return var_export($prefix, true);
269 }, array_keys($mainAutoload['psr-0'])));
270 $baseDirFromTargetDirCode = $filesystem->findShortestPathCode($targetDir, $basePath, true);
271
272 $targetDirLoader = <<<EOF
273
274     public static function autoload(\$class)
275     {
276         \$dir = $baseDirFromTargetDirCode . '/';
277         \$prefixes = array($prefixes);
278         foreach (\$prefixes as \$prefix) {
279             if (0 !== strpos(\$class, \$prefix)) {
280                 continue;
281             }
282             \$path = \$dir . implode('/', array_slice(explode('\\\\', \$class), $levels)).'.php';
283             if (!\$path = stream_resolve_include_path(\$path)) {
284                 return false;
285             }
286             require \$path;
287
288             return true;
289         }
290     }
291
292 EOF;
293 }
294
295 $blacklist = null;
296 if (!empty($autoloads['exclude-from-classmap'])) {
297 $blacklist = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
298 }
299
300
301  $classMap = array();
302 if ($scanPsr0Packages) {
303 $namespacesToScan = array();
304
305
306  foreach (array('psr-0', 'psr-4') as $psrType) {
307 foreach ($autoloads[$psrType] as $namespace => $paths) {
308 $namespacesToScan[$namespace][] = array('paths' => $paths, 'type' => $psrType);
309 }
310 }
311
312 krsort($namespacesToScan);
313
314 foreach ($namespacesToScan as $namespace => $groups) {
315 foreach ($groups as $group) {
316 foreach ($group['paths'] as $dir) {
317 $dir = $filesystem->normalizePath($filesystem->isAbsolutePath($dir) ? $dir : $basePath.'/'.$dir);
318 if (!is_dir($dir)) {
319 continue;
320 }
321
322 $namespaceFilter = $namespace === '' ? null : $namespace;
323 $classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, $namespaceFilter, $classMap);
324 }
325 }
326 }
327 }
328
329 foreach ($autoloads['classmap'] as $dir) {
330 $classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, null, $classMap);
331 }
332
333 ksort($classMap);
334 foreach ($classMap as $class => $code) {
335 $classmapFile .= '    '.var_export($class, true).' => '.$code;
336 }
337 $classmapFile .= ");\n";
338
339 if (!$suffix) {
340 if (!$config->get('autoloader-suffix') && is_readable($vendorPath.'/autoload.php')) {
341 $content = file_get_contents($vendorPath.'/autoload.php');
342 if (preg_match('{ComposerAutoloaderInit([^:\s]+)::}', $content, $match)) {
343 $suffix = $match[1];
344 }
345 }
346
347 if (!$suffix) {
348 $suffix = $config->get('autoloader-suffix') ?: md5(uniqid('', true));
349 }
350 }
351
352 file_put_contents($targetDir.'/autoload_namespaces.php', $namespacesFile);
353 file_put_contents($targetDir.'/autoload_psr4.php', $psr4File);
354 file_put_contents($targetDir.'/autoload_classmap.php', $classmapFile);
355 $includePathFilePath = $targetDir.'/include_paths.php';
356 if ($includePathFileContents = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
357 file_put_contents($includePathFilePath, $includePathFileContents);
358 } elseif (file_exists($includePathFilePath)) {
359 unlink($includePathFilePath);
360 }
361 $includeFilesFilePath = $targetDir.'/autoload_files.php';
362 if ($includeFilesFileContents = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
363 file_put_contents($includeFilesFilePath, $includeFilesFileContents);
364 } elseif (file_exists($includeFilesFilePath)) {
365 unlink($includeFilesFilePath);
366 }
367 file_put_contents($targetDir.'/autoload_static.php', $this->getStaticFile($suffix, $targetDir, $vendorPath, $basePath, $staticPhpVersion));
368 file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix));
369 file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFileContents, $targetDirLoader, (bool) $includeFilesFileContents, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion));
370
371 $this->safeCopy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php');
372 $this->safeCopy(__DIR__.'/../../../LICENSE', $targetDir.'/LICENSE');
373
374 if ($this->runScripts) {
375 $this->eventDispatcher->dispatchScript(ScriptEvents::POST_AUTOLOAD_DUMP, $this->devMode, array(), array(
376 'optimize' => (bool) $scanPsr0Packages,
377 ));
378 }
379 }
380
381 private function addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist = null, $namespaceFilter = null, array $classMap = array())
382 {
383 foreach ($this->generateClassMap($dir, $blacklist, $namespaceFilter) as $class => $path) {
384 $pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path).",\n";
385 if (!isset($classMap[$class])) {
386 $classMap[$class] = $pathCode;
387 } elseif ($this->io && $classMap[$class] !== $pathCode && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($classMap[$class].' '.$path, '\\', '/'))) {
388 $this->io->writeError(
389 '<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
390 ' was found in both "'.str_replace(array('$vendorDir . \'', "',\n"), array($vendorPath, ''), $classMap[$class]).'" and "'.$path.'", the first will be used.</warning>'
391 );
392 }
393 }
394
395 return $classMap;
396 }
397
398 private function generateClassMap($dir, $blacklist = null, $namespaceFilter = null, $showAmbiguousWarning = true)
399 {
400 return ClassMapGenerator::createMap($dir, $blacklist, $showAmbiguousWarning ? $this->io : null, $namespaceFilter);
401 }
402
403 public function buildPackageMap(InstallationManager $installationManager, PackageInterface $mainPackage, array $packages)
404 {
405
406  $packageMap = array(array($mainPackage, ''));
407
408 foreach ($packages as $package) {
409 if ($package instanceof AliasPackage) {
410 continue;
411 }
412 $this->validatePackage($package);
413
414 $packageMap[] = array(
415 $package,
416 $installationManager->getInstallPath($package),
417 );
418 }
419
420 return $packageMap;
421 }
422
423
424
425
426
427
428 protected function validatePackage(PackageInterface $package)
429 {
430 $autoload = $package->getAutoload();
431 if (!empty($autoload['psr-4']) && null !== $package->getTargetDir()) {
432 $name = $package->getName();
433 $package->getTargetDir();
434 throw new \InvalidArgumentException("PSR-4 autoloading is incompatible with the target-dir property, remove the target-dir in package '$name'.");
435 }
436 if (!empty($autoload['psr-4'])) {
437 foreach ($autoload['psr-4'] as $namespace => $dirs) {
438 if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
439 throw new \InvalidArgumentException("psr-4 namespaces must end with a namespace separator, '$namespace' does not, use '$namespace\\'.");
440 }
441 }
442 }
443 }
444
445
446
447
448
449
450
451
452 public function parseAutoloads(array $packageMap, PackageInterface $mainPackage)
453 {
454 $mainPackageMap = array_shift($packageMap);
455 $sortedPackageMap = $this->sortPackageMap($packageMap);
456 $sortedPackageMap[] = $mainPackageMap;
457 array_unshift($packageMap, $mainPackageMap);
458
459 $psr0 = $this->parseAutoloadsType($packageMap, 'psr-0', $mainPackage);
460 $psr4 = $this->parseAutoloadsType($packageMap, 'psr-4', $mainPackage);
461 $classmap = $this->parseAutoloadsType(array_reverse($sortedPackageMap), 'classmap', $mainPackage);
462 $files = $this->parseAutoloadsType($sortedPackageMap, 'files', $mainPackage);
463 $exclude = $this->parseAutoloadsType($sortedPackageMap, 'exclude-from-classmap', $mainPackage);
464
465 krsort($psr0);
466 krsort($psr4);
467
468 return array(
469 'psr-0' => $psr0,
470 'psr-4' => $psr4,
471 'classmap' => $classmap,
472 'files' => $files,
473 'exclude-from-classmap' => $exclude,
474 );
475 }
476
477
478
479
480
481
482
483 public function createLoader(array $autoloads)
484 {
485 $loader = new ClassLoader();
486
487 if (isset($autoloads['psr-0'])) {
488 foreach ($autoloads['psr-0'] as $namespace => $path) {
489 $loader->add($namespace, $path);
490 }
491 }
492
493 if (isset($autoloads['psr-4'])) {
494 foreach ($autoloads['psr-4'] as $namespace => $path) {
495 $loader->addPsr4($namespace, $path);
496 }
497 }
498
499 if (isset($autoloads['classmap'])) {
500 $blacklist = null;
501 if (!empty($autoloads['exclude-from-classmap'])) {
502 $blacklist = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
503 }
504
505 foreach ($autoloads['classmap'] as $dir) {
506 try {
507 $loader->addClassMap($this->generateClassMap($dir, $blacklist, null, false));
508 } catch (\RuntimeException $e) {
509 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
510 }
511 }
512 }
513
514 return $loader;
515 }
516
517 protected function getIncludePathsFile(array $packageMap, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
518 {
519 $includePaths = array();
520
521 foreach ($packageMap as $item) {
522 list($package, $installPath) = $item;
523
524 if (null !== $package->getTargetDir() && strlen($package->getTargetDir()) > 0) {
525 $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
526 }
527
528 foreach ($package->getIncludePaths() as $includePath) {
529 $includePath = trim($includePath, '/');
530 $includePaths[] = empty($installPath) ? $includePath : $installPath.'/'.$includePath;
531 }
532 }
533
534 if (!$includePaths) {
535 return;
536 }
537
538 $includePathsCode = '';
539 foreach ($includePaths as $path) {
540 $includePathsCode .= "    " . $this->getPathCode($filesystem, $basePath, $vendorPath, $path) . ",\n";
541 }
542
543 return <<<EOF
544 <?php
545
546 // include_paths.php @generated by Composer
547
548 \$vendorDir = $vendorPathCode;
549 \$baseDir = $appBaseDirCode;
550
551 return array(
552 $includePathsCode);
553
554 EOF;
555 }
556
557 protected function getIncludeFilesFile(array $files, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
558 {
559 $filesCode = '';
560 foreach ($files as $fileIdentifier => $functionFile) {
561 $filesCode .= '    ' . var_export($fileIdentifier, true) . ' => '
562 . $this->getPathCode($filesystem, $basePath, $vendorPath, $functionFile) . ",\n";
563 }
564
565 if (!$filesCode) {
566 return false;
567 }
568
569 return <<<EOF
570 <?php
571
572 // autoload_files.php @generated by Composer
573
574 \$vendorDir = $vendorPathCode;
575 \$baseDir = $appBaseDirCode;
576
577 return array(
578 $filesCode);
579
580 EOF;
581 }
582
583 protected function getPathCode(Filesystem $filesystem, $basePath, $vendorPath, $path)
584 {
585 if (!$filesystem->isAbsolutePath($path)) {
586 $path = $basePath . '/' . $path;
587 }
588 $path = $filesystem->normalizePath($path);
589
590 $baseDir = '';
591 if (strpos($path.'/', $vendorPath.'/') === 0) {
592 $path = substr($path, strlen($vendorPath));
593 $baseDir = '$vendorDir';
594
595 if ($path !== false) {
596 $baseDir .= " . ";
597 }
598 } else {
599 $path = $filesystem->normalizePath($filesystem->findShortestPath($basePath, $path, true));
600 if (!$filesystem->isAbsolutePath($path)) {
601 $baseDir = '$baseDir . ';
602 $path = '/' . $path;
603 }
604 }
605
606 if (preg_match('/\.phar.+$/', $path)) {
607 $baseDir = "'phar://' . " . $baseDir;
608 }
609
610 return $baseDir . (($path !== false) ? var_export($path, true) : "");
611 }
612
613 protected function getAutoloadFile($vendorPathToTargetDirCode, $suffix)
614 {
615 $lastChar = $vendorPathToTargetDirCode[strlen($vendorPathToTargetDirCode) - 1];
616 if ("'" === $lastChar || '"' === $lastChar) {
617 $vendorPathToTargetDirCode = substr($vendorPathToTargetDirCode, 0, -1).'/autoload_real.php'.$lastChar;
618 } else {
619 $vendorPathToTargetDirCode .= " . '/autoload_real.php'";
620 }
621
622 return <<<AUTOLOAD
623 <?php
624
625 // autoload.php @generated by Composer
626
627 require_once $vendorPathToTargetDirCode;
628
629 return ComposerAutoloaderInit$suffix::getLoader();
630
631 AUTOLOAD;
632 }
633
634 protected function getAutoloadRealFile($useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion = 70000)
635 {
636 $file = <<<HEADER
637 <?php
638
639 // autoload_real.php @generated by Composer
640
641 class ComposerAutoloaderInit$suffix
642 {
643     private static \$loader;
644
645     public static function loadClassLoader(\$class)
646     {
647         if ('Composer\\Autoload\\ClassLoader' === \$class) {
648             require __DIR__ . '/ClassLoader.php';
649         }
650     }
651
652     public static function getLoader()
653     {
654         if (null !== self::\$loader) {
655             return self::\$loader;
656         }
657
658         spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'), true, $prependAutoloader);
659         self::\$loader = \$loader = new \\Composer\\Autoload\\ClassLoader();
660         spl_autoload_unregister(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'));
661
662
663 HEADER;
664
665 if ($useIncludePath) {
666 $file .= <<<'INCLUDE_PATH'
667         $includePaths = require __DIR__ . '/include_paths.php';
668         array_push($includePaths, get_include_path());
669         set_include_path(implode(PATH_SEPARATOR, $includePaths));
670
671
672 INCLUDE_PATH;
673 }
674
675 $file .= <<<STATIC_INIT
676         \$useStaticLoader = PHP_VERSION_ID >= $staticPhpVersion && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
677         if (\$useStaticLoader) {
678             require_once __DIR__ . '/autoload_static.php';
679
680             call_user_func(\Composer\Autoload\ComposerStaticInit$suffix::getInitializer(\$loader));
681         } else {
682
683 STATIC_INIT;
684
685 if (!$this->classMapAuthoritative) {
686 $file .= <<<'PSR04'
687             $map = require __DIR__ . '/autoload_namespaces.php';
688             foreach ($map as $namespace => $path) {
689                 $loader->set($namespace, $path);
690             }
691
692             $map = require __DIR__ . '/autoload_psr4.php';
693             foreach ($map as $namespace => $path) {
694                 $loader->setPsr4($namespace, $path);
695             }
696
697
698 PSR04;
699 }
700
701 if ($useClassMap) {
702 $file .= <<<'CLASSMAP'
703             $classMap = require __DIR__ . '/autoload_classmap.php';
704             if ($classMap) {
705                 $loader->addClassMap($classMap);
706             }
707
708 CLASSMAP;
709 }
710
711 $file .= "        }\n\n";
712
713 if ($this->classMapAuthoritative) {
714 $file .= <<<'CLASSMAPAUTHORITATIVE'
715         $loader->setClassMapAuthoritative(true);
716
717 CLASSMAPAUTHORITATIVE;
718 }
719
720 if ($this->apcu) {
721 $apcuPrefix = substr(base64_encode(md5(uniqid('', true), true)), 0, -3);
722 $file .= <<<APCU
723         \$loader->setApcuPrefix('$apcuPrefix');
724
725 APCU;
726 }
727
728 if ($useGlobalIncludePath) {
729 $file .= <<<'INCLUDEPATH'
730         $loader->setUseIncludePath(true);
731
732 INCLUDEPATH;
733 }
734
735 if ($targetDirLoader) {
736 $file .= <<<REGISTER_TARGET_DIR_AUTOLOAD
737         spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'autoload'), true, true);
738
739
740 REGISTER_TARGET_DIR_AUTOLOAD;
741 }
742
743 $file .= <<<REGISTER_LOADER
744         \$loader->register($prependAutoloader);
745
746
747 REGISTER_LOADER;
748
749 if ($useIncludeFiles) {
750 $file .= <<<INCLUDE_FILES
751         if (\$useStaticLoader) {
752             \$includeFiles = Composer\Autoload\ComposerStaticInit$suffix::\$files;
753         } else {
754             \$includeFiles = require __DIR__ . '/autoload_files.php';
755         }
756         foreach (\$includeFiles as \$fileIdentifier => \$file) {
757             composerRequire$suffix(\$fileIdentifier, \$file);
758         }
759
760
761 INCLUDE_FILES;
762 }
763
764 $file .= <<<METHOD_FOOTER
765         return \$loader;
766     }
767
768 METHOD_FOOTER;
769
770 $file .= $targetDirLoader;
771
772 if ($useIncludeFiles) {
773 return $file . <<<FOOTER
774 }
775
776 function composerRequire$suffix(\$fileIdentifier, \$file)
777 {
778     if (empty(\$GLOBALS['__composer_autoload_files'][\$fileIdentifier])) {
779         require \$file;
780
781         \$GLOBALS['__composer_autoload_files'][\$fileIdentifier] = true;
782     }
783 }
784
785 FOOTER;
786 }
787
788 return $file . <<<FOOTER
789 }
790
791 FOOTER;
792 }
793
794 protected function getStaticFile($suffix, $targetDir, $vendorPath, $basePath, &$staticPhpVersion)
795 {
796 $staticPhpVersion = 50600;
797
798 $file = <<<HEADER
799 <?php
800
801 // autoload_static.php @generated by Composer
802
803 namespace Composer\Autoload;
804
805 class ComposerStaticInit$suffix
806 {
807
808 HEADER;
809
810 $loader = new ClassLoader();
811
812 $map = require $targetDir . '/autoload_namespaces.php';
813 foreach ($map as $namespace => $path) {
814 $loader->set($namespace, $path);
815 }
816
817 $map = require $targetDir . '/autoload_psr4.php';
818 foreach ($map as $namespace => $path) {
819 $loader->setPsr4($namespace, $path);
820 }
821
822 $classMap = require $targetDir . '/autoload_classmap.php';
823 if ($classMap) {
824 $loader->addClassMap($classMap);
825 }
826
827 $filesystem = new Filesystem();
828
829 $vendorPathCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true, true) . " . '/";
830 $appBaseDirCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, true, true) . " . '/";
831
832 $absoluteVendorPathCode = ' => ' . substr(var_export(rtrim($vendorDir, '\\/') . '/', true), 0, -1);
833 $absoluteAppBaseDirCode = ' => ' . substr(var_export(rtrim($baseDir, '\\/') . '/', true), 0, -1);
834
835 $initializer = '';
836 $prefix = "\0Composer\Autoload\ClassLoader\0";
837 $prefixLen = strlen($prefix);
838 if (file_exists($targetDir . '/autoload_files.php')) {
839 $maps = array('files' => require $targetDir . '/autoload_files.php');
840 } else {
841 $maps = array();
842 }
843
844 foreach ((array) $loader as $prop => $value) {
845 if ($value && 0 === strpos($prop, $prefix)) {
846 $maps[substr($prop, $prefixLen)] = $value;
847 }
848 }
849
850 foreach ($maps as $prop => $value) {
851 if (count($value) > 32767) {
852
853  
854  $staticPhpVersion = 70000;
855 }
856 $value = var_export($value, true);
857 $value = str_replace($absoluteVendorPathCode, $vendorPathCode, $value);
858 $value = str_replace($absoluteAppBaseDirCode, $appBaseDirCode, $value);
859 $value = ltrim(preg_replace('/^ */m', '    $0$0', $value));
860
861 $file .= sprintf("    public static $%s = %s;\n\n", $prop, $value);
862 if ('files' !== $prop) {
863 $initializer .= "            \$loader->$prop = ComposerStaticInit$suffix::\$$prop;\n";
864 }
865 }
866
867 return $file . <<<INITIALIZER
868     public static function getInitializer(ClassLoader \$loader)
869     {
870         return \Closure::bind(function () use (\$loader) {
871 $initializer
872         }, null, ClassLoader::class);
873     }
874 }
875
876 INITIALIZER;
877 }
878
879 protected function parseAutoloadsType(array $packageMap, $type, PackageInterface $mainPackage)
880 {
881 $autoloads = array();
882
883 foreach ($packageMap as $item) {
884 list($package, $installPath) = $item;
885
886 $autoload = $package->getAutoload();
887 if ($this->devMode && $package === $mainPackage) {
888 $autoload = array_merge_recursive($autoload, $package->getDevAutoload());
889 }
890
891
892  if (!isset($autoload[$type]) || !is_array($autoload[$type])) {
893 continue;
894 }
895 if (null !== $package->getTargetDir() && $package !== $mainPackage) {
896 $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
897 }
898
899 foreach ($autoload[$type] as $namespace => $paths) {
900 foreach ((array) $paths as $path) {
901 if (($type === 'files' || $type === 'classmap' || $type === 'exclude-from-classmap') && $package->getTargetDir() && !is_readable($installPath.'/'.$path)) {
902
903  if ($package === $mainPackage) {
904 $targetDir = str_replace('\\<dirsep\\>', '[\\\\/]', preg_quote(str_replace(array('/', '\\'), '<dirsep>', $package->getTargetDir())));
905 $path = ltrim(preg_replace('{^'.$targetDir.'}', '', ltrim($path, '\\/')), '\\/');
906 } else {
907
908  $path = $package->getTargetDir() . '/' . $path;
909 }
910 }
911
912 if ($type === 'exclude-from-classmap') {
913
914  $path = preg_replace('{/+}', '/', preg_quote(trim(strtr($path, '\\', '/'), '/')));
915
916
917  $path = str_replace('\\*\\*', '.+?', $path);
918 $path = str_replace('\\*', '[^/]+?', $path);
919
920
921  $updir = null;
922 $path = preg_replace_callback(
923 '{^((?:(?:\\\\\\.){1,2}+/)+)}',
924 function ($matches) use (&$updir) {
925 if (isset($matches[1])) {
926
927  $updir = str_replace('\\.', '.', $matches[1]);
928 }
929
930 return '';
931 },
932 $path
933 );
934 if (empty($installPath)) {
935 $installPath = strtr(getcwd(), '\\', '/');
936 }
937
938 $resolvedPath = realpath($installPath . '/' . $updir);
939 $autoloads[] = preg_quote(strtr($resolvedPath, '\\', '/')) . '/' . $path;
940 continue;
941 }
942
943 $relativePath = empty($installPath) ? (empty($path) ? '.' : $path) : $installPath.'/'.$path;
944
945 if ($type === 'files') {
946 $autoloads[$this->getFileIdentifier($package, $path)] = $relativePath;
947 continue;
948 } elseif ($type === 'classmap') {
949 $autoloads[] = $relativePath;
950 continue;
951 }
952
953 $autoloads[$namespace][] = $relativePath;
954 }
955 }
956 }
957
958 return $autoloads;
959 }
960
961 protected function getFileIdentifier(PackageInterface $package, $path)
962 {
963 return md5($package->getName() . ':' . $path);
964 }
965
966
967
968
969
970
971
972
973
974 protected function sortPackageMap(array $packageMap)
975 {
976 $packages = array();
977 $paths = array();
978 $usageList = array();
979
980 foreach ($packageMap as $item) {
981 list($package, $path) = $item;
982 $name = $package->getName();
983 $packages[$name] = $package;
984 $paths[$name] = $path;
985
986 foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) {
987 $target = $link->getTarget();
988 $usageList[$target][] = $name;
989 }
990 }
991
992 $computing = array();
993 $computed = array();
994 $computeImportance = function ($name) use (&$computeImportance, &$computing, &$computed, $usageList) {
995
996  if (isset($computed[$name])) {
997 return $computed[$name];
998 }
999
1000
1001  if (isset($computing[$name])) {
1002 return 0;
1003 }
1004
1005 $computing[$name] = true;
1006 $weight = 0;
1007
1008 if (isset($usageList[$name])) {
1009 foreach ($usageList[$name] as $user) {
1010 $weight -= 1 - $computeImportance($user);
1011 }
1012 }
1013
1014 unset($computing[$name]);
1015 $computed[$name] = $weight;
1016
1017 return $weight;
1018 };
1019
1020 $weightList = array();
1021
1022 foreach ($packages as $name => $package) {
1023 $weight = $computeImportance($name);
1024 $weightList[$name] = $weight;
1025 }
1026
1027 $stable_sort = function (&$array) {
1028 static $transform, $restore;
1029
1030 $i = 0;
1031
1032 if (!$transform) {
1033 $transform = function (&$v, $k) use (&$i) {
1034 $v = array($v, ++$i, $k, $v);
1035 };
1036
1037 $restore = function (&$v, $k) {
1038 $v = $v[3];
1039 };
1040 }
1041
1042 array_walk($array, $transform);
1043 asort($array);
1044 array_walk($array, $restore);
1045 };
1046
1047 $stable_sort($weightList);
1048
1049 $sortedPackageMap = array();
1050
1051 foreach (array_keys($weightList) as $name) {
1052 $sortedPackageMap[] = array($packages[$name], $paths[$name]);
1053 }
1054
1055 return $sortedPackageMap;
1056 }
1057
1058
1059
1060
1061
1062
1063
1064 protected function safeCopy($source, $target)
1065 {
1066 $source = fopen($source, 'r');
1067 $target = fopen($target, 'w+');
1068
1069 stream_copy_to_stream($source, $target);
1070 fclose($source);
1071 fclose($target);
1072 }
1073 }
1074 <?php
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092 namespace Composer\Autoload;
1093
1094 use Symfony\Component\Finder\Finder;
1095 use Composer\IO\IOInterface;
1096 use Composer\Util\Filesystem;
1097
1098
1099
1100
1101
1102
1103
1104 class ClassMapGenerator
1105 {
1106
1107
1108
1109
1110
1111
1112 public static function dump($dirs, $file)
1113 {
1114 $maps = array();
1115
1116 foreach ($dirs as $dir) {
1117 $maps = array_merge($maps, static::createMap($dir));
1118 }
1119
1120 file_put_contents($file, sprintf('<?php return %s;', var_export($maps, true)));
1121 }
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134 public static function createMap($path, $blacklist = null, IOInterface $io = null, $namespace = null)
1135 {
1136 if (is_string($path)) {
1137 if (is_file($path)) {
1138 $path = array(new \SplFileInfo($path));
1139 } elseif (is_dir($path)) {
1140 $path = Finder::create()->files()->followLinks()->name('/\.(php|inc|hh)$/')->in($path);
1141 } else {
1142 throw new \RuntimeException(
1143 'Could not scan for classes inside "'.$path.
1144 '" which does not appear to be a file nor a folder'
1145 );
1146 }
1147 }
1148
1149 $map = array();
1150 $filesystem = new Filesystem();
1151 $cwd = realpath(getcwd());
1152
1153 foreach ($path as $file) {
1154 $filePath = $file->getPathname();
1155 if (!in_array(pathinfo($filePath, PATHINFO_EXTENSION), array('php', 'inc', 'hh'))) {
1156 continue;
1157 }
1158
1159 if (!$filesystem->isAbsolutePath($filePath)) {
1160 $filePath = $cwd . '/' . $filePath;
1161 $filePath = $filesystem->normalizePath($filePath);
1162 } else {
1163 $filePath = preg_replace('{[\\\\/]{2,}}', '/', $filePath);
1164 }
1165
1166
1167  if ($blacklist && preg_match($blacklist, strtr(realpath($filePath), '\\', '/'))) {
1168 continue;
1169 }
1170
1171 $classes = self::findClasses($filePath);
1172
1173 foreach ($classes as $class) {
1174
1175  if (null !== $namespace && 0 !== strpos($class, $namespace)) {
1176 continue;
1177 }
1178
1179 if (!isset($map[$class])) {
1180 $map[$class] = $filePath;
1181 } elseif ($io && $map[$class] !== $filePath && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($map[$class].' '.$filePath, '\\', '/'))) {
1182 $io->writeError(
1183 '<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
1184 ' was found in both "'.$map[$class].'" and "'.$filePath.'", the first will be used.</warning>'
1185 );
1186 }
1187 }
1188 }
1189
1190 return $map;
1191 }
1192
1193
1194
1195
1196
1197
1198
1199
1200 private static function findClasses($path)
1201 {
1202 $extraTypes = PHP_VERSION_ID < 50400 ? '' : '|trait';
1203 if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>=')) {
1204 $extraTypes .= '|enum';
1205 }
1206
1207
1208  
1209  $contents = @php_strip_whitespace($path);
1210 if (!$contents) {
1211 if (!file_exists($path)) {
1212 $message = 'File at "%s" does not exist, check your classmap definitions';
1213 } elseif (!is_readable($path)) {
1214 $message = 'File at "%s" is not readable, check its permissions';
1215 } elseif ('' === trim(file_get_contents($path))) {
1216
1217  return array();
1218 } else {
1219 $message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted';
1220 }
1221 $error = error_get_last();
1222 if (isset($error['message'])) {
1223 $message .= PHP_EOL . 'The following message may be helpful:' . PHP_EOL . $error['message'];
1224 }
1225 throw new \RuntimeException(sprintf($message, $path));
1226 }
1227
1228
1229  if (!preg_match('{\b(?:class|interface'.$extraTypes.')\s}i', $contents)) {
1230 return array();
1231 }
1232
1233
1234  $contents = preg_replace('{<<<\s*(\'?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)\\2(?=\r\n|\n|\r|;)}s', 'null', $contents);
1235
1236  $contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
1237
1238  if (substr($contents, 0, 2) !== '<?') {
1239 $contents = preg_replace('{^.+?<\?}s', '<?', $contents, 1, $replacements);
1240 if ($replacements === 0) {
1241 return array();
1242 }
1243 }
1244
1245  $contents = preg_replace('{\?>.+<\?}s', '?><?', $contents);
1246
1247  $pos = strrpos($contents, '?>');
1248 if (false !== $pos && false === strpos(substr($contents, $pos), '<?')) {
1249 $contents = substr($contents, 0, $pos);
1250 }
1251
1252 preg_match_all('{
1253             (?:
1254                  \b(?<![\$:>])(?P<type>class|interface'.$extraTypes.') \s++ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
1255                | \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*+ [\{;]
1256             )
1257         }ix', $contents, $matches);
1258
1259 $classes = array();
1260 $namespace = '';
1261
1262 for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
1263 if (!empty($matches['ns'][$i])) {
1264 $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\';
1265 } else {
1266 $name = $matches['name'][$i];
1267
1268  if ($name === 'extends' || $name === 'implements') {
1269 continue;
1270 }
1271 if ($name[0] === ':') {
1272
1273  $name = 'xhp'.substr(str_replace(array('-', ':'), array('_', '__'), $name), 1);
1274 } elseif ($matches['type'][$i] === 'enum') {
1275
1276  
1277  
1278  
1279  $name = rtrim($name, ':');
1280 }
1281 $classes[] = ltrim($namespace . $name, '\\');
1282 }
1283 }
1284
1285 return $classes;
1286 }
1287 }
1288 <?php
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300 namespace Composer;
1301
1302 use Composer\IO\IOInterface;
1303 use Composer\Util\Filesystem;
1304 use Composer\Util\Silencer;
1305 use Symfony\Component\Finder\Finder;
1306
1307
1308
1309
1310
1311
1312 class Cache
1313 {
1314 private static $cacheCollected = false;
1315 private $io;
1316 private $root;
1317 private $enabled = true;
1318 private $whitelist;
1319 private $filesystem;
1320
1321
1322
1323
1324
1325
1326
1327 public function __construct(IOInterface $io, $cacheDir, $whitelist = 'a-z0-9.', Filesystem $filesystem = null)
1328 {
1329 $this->io = $io;
1330 $this->root = rtrim($cacheDir, '/\\') . '/';
1331 $this->whitelist = $whitelist;
1332 $this->filesystem = $filesystem ?: new Filesystem();
1333
1334 if (preg_match('{(^|[\\\\/])(\$null|NUL|/dev/null)([\\\\/]|$)}', $cacheDir)) {
1335 $this->enabled = false;
1336
1337 return;
1338 }
1339
1340 if (
1341 (!is_dir($this->root) && !Silencer::call('mkdir', $this->root, 0777, true))
1342 || !is_writable($this->root)
1343 ) {
1344 $this->io->writeError('<warning>Cannot create cache directory ' . $this->root . ', or directory is not writable. Proceeding without cache</warning>');
1345 $this->enabled = false;
1346 }
1347 }
1348
1349 public function isEnabled()
1350 {
1351 return $this->enabled;
1352 }
1353
1354 public function getRoot()
1355 {
1356 return $this->root;
1357 }
1358
1359 public function read($file)
1360 {
1361 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1362 if ($this->enabled && file_exists($this->root . $file)) {
1363 $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
1364
1365 return file_get_contents($this->root . $file);
1366 }
1367
1368 return false;
1369 }
1370
1371 public function write($file, $contents)
1372 {
1373 if ($this->enabled) {
1374 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1375
1376 $this->io->writeError('Writing '.$this->root . $file.' into cache', true, IOInterface::DEBUG);
1377
1378 try {
1379 return file_put_contents($this->root . $file, $contents);
1380 } catch (\ErrorException $e) {
1381 $this->io->writeError('<warning>Failed to write into cache: '.$e->getMessage().'</warning>', true, IOInterface::DEBUG);
1382 if (preg_match('{^file_put_contents\(\): Only ([0-9]+) of ([0-9]+) bytes written}', $e->getMessage(), $m)) {
1383
1384  unlink($this->root . $file);
1385
1386 $message = sprintf(
1387 '<warning>Writing %1$s into cache failed after %2$u of %3$u bytes written, only %4$u bytes of free space available</warning>',
1388 $this->root . $file,
1389 $m[1],
1390 $m[2],
1391 @disk_free_space($this->root . dirname($file))
1392 );
1393
1394 $this->io->writeError($message);
1395
1396 return false;
1397 }
1398
1399 throw $e;
1400 }
1401 }
1402
1403 return false;
1404 }
1405
1406
1407
1408
1409 public function copyFrom($file, $source)
1410 {
1411 if ($this->enabled) {
1412 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1413 $this->filesystem->ensureDirectoryExists(dirname($this->root . $file));
1414
1415 if (!file_exists($source)) {
1416 $this->io->writeError('<error>'.$source.' does not exist, can not write into cache</error>');
1417 } elseif ($this->io->isDebug()) {
1418 $this->io->writeError('Writing '.$this->root . $file.' into cache from '.$source);
1419 }
1420
1421 return copy($source, $this->root . $file);
1422 }
1423
1424 return false;
1425 }
1426
1427
1428
1429
1430 public function copyTo($file, $target)
1431 {
1432 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1433 if ($this->enabled && file_exists($this->root . $file)) {
1434 try {
1435 touch($this->root . $file, filemtime($this->root . $file), time());
1436 } catch (\ErrorException $e) {
1437
1438  
1439  Silencer::call('touch', $this->root . $file);
1440 }
1441
1442 $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
1443
1444 return copy($this->root . $file, $target);
1445 }
1446
1447 return false;
1448 }
1449
1450 public function gcIsNecessary()
1451 {
1452 return (!self::$cacheCollected && !mt_rand(0, 50));
1453 }
1454
1455 public function remove($file)
1456 {
1457 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1458 if ($this->enabled && file_exists($this->root . $file)) {
1459 return $this->filesystem->unlink($this->root . $file);
1460 }
1461
1462 return false;
1463 }
1464
1465 public function clear()
1466 {
1467 if ($this->enabled) {
1468 return $this->filesystem->removeDirectory($this->root);
1469 }
1470
1471 return false;
1472 }
1473
1474 public function gc($ttl, $maxSize)
1475 {
1476 if ($this->enabled) {
1477 $expire = new \DateTime();
1478 $expire->modify('-'.$ttl.' seconds');
1479
1480 $finder = $this->getFinder()->date('until '.$expire->format('Y-m-d H:i:s'));
1481 foreach ($finder as $file) {
1482 $this->filesystem->unlink($file->getPathname());
1483 }
1484
1485 $totalSize = $this->filesystem->size($this->root);
1486 if ($totalSize > $maxSize) {
1487 $iterator = $this->getFinder()->sortByAccessedTime()->getIterator();
1488 while ($totalSize > $maxSize && $iterator->valid()) {
1489 $filepath = $iterator->current()->getPathname();
1490 $totalSize -= $this->filesystem->size($filepath);
1491 $this->filesystem->unlink($filepath);
1492 $iterator->next();
1493 }
1494 }
1495
1496 self::$cacheCollected = true;
1497
1498 return true;
1499 }
1500
1501 return false;
1502 }
1503
1504 public function sha1($file)
1505 {
1506 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1507 if ($this->enabled && file_exists($this->root . $file)) {
1508 return sha1_file($this->root . $file);
1509 }
1510
1511 return false;
1512 }
1513
1514 public function sha256($file)
1515 {
1516 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1517 if ($this->enabled && file_exists($this->root . $file)) {
1518 return hash_file('sha256', $this->root . $file);
1519 }
1520
1521 return false;
1522 }
1523
1524 protected function getFinder()
1525 {
1526 return Finder::create()->in($this->root)->files();
1527 }
1528 }
1529 <?php
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541 namespace Composer\Command;
1542
1543 use Symfony\Component\Console\Input\InputInterface;
1544 use Symfony\Component\Console\Output\OutputInterface;
1545
1546
1547
1548
1549 class AboutCommand extends BaseCommand
1550 {
1551 protected function configure()
1552 {
1553 $this
1554 ->setName('about')
1555 ->setDescription('Shows the short information about Composer.')
1556 ->setHelp(<<<EOT
1557 <info>php composer.phar about</info>
1558 EOT
1559 )
1560 ;
1561 }
1562
1563 protected function execute(InputInterface $input, OutputInterface $output)
1564 {
1565 $this->getIO()->write(<<<EOT
1566 <info>Composer - Package Management for PHP</info>
1567 <comment>Composer is a dependency manager tracking local dependencies of your projects and libraries.
1568 See https://getcomposer.org/ for more information.</comment>
1569 EOT
1570 );
1571 }
1572 }
1573 <?php
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585 namespace Composer\Command;
1586
1587 use Composer\Factory;
1588 use Composer\IO\IOInterface;
1589 use Composer\Config;
1590 use Composer\Composer;
1591 use Composer\Repository\CompositeRepository;
1592 use Composer\Repository\RepositoryFactory;
1593 use Composer\Script\ScriptEvents;
1594 use Composer\Plugin\CommandEvent;
1595 use Composer\Plugin\PluginEvents;
1596 use Composer\Util\Filesystem;
1597 use Symfony\Component\Console\Input\InputArgument;
1598 use Symfony\Component\Console\Input\InputInterface;
1599 use Symfony\Component\Console\Input\InputOption;
1600 use Symfony\Component\Console\Output\OutputInterface;
1601
1602
1603
1604
1605
1606
1607 class ArchiveCommand extends BaseCommand
1608 {
1609 protected function configure()
1610 {
1611 $this
1612 ->setName('archive')
1613 ->setDescription('Creates an archive of this composer package.')
1614 ->setDefinition(array(
1615 new InputArgument('package', InputArgument::OPTIONAL, 'The package to archive instead of the current project'),
1616 new InputArgument('version', InputArgument::OPTIONAL, 'A version constraint to find the package to archive'),
1617 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the resulting archive: tar or zip'),
1618 new InputOption('dir', null, InputOption::VALUE_REQUIRED, 'Write the archive to this directory'),
1619 new InputOption('file', null, InputOption::VALUE_REQUIRED, 'Write the archive with the given file name.'
1620 .' Note that the format will be appended.'),
1621 new InputOption('ignore-filters', false, InputOption::VALUE_NONE, 'Ignore filters when saving package'),
1622 ))
1623 ->setHelp(<<<EOT
1624 The <info>archive</info> command creates an archive of the specified format
1625 containing the files and directories of the Composer project or the specified
1626 package in the specified version and writes it to the specified directory.
1627
1628 <info>php composer.phar archive [--format=zip] [--dir=/foo] [package [version]]</info>
1629
1630 EOT
1631 )
1632 ;
1633 }
1634
1635 protected function execute(InputInterface $input, OutputInterface $output)
1636 {
1637 $config = Factory::createConfig();
1638 $composer = $this->getComposer(false);
1639 if ($composer) {
1640 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'archive', $input, $output);
1641 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
1642 $composer->getEventDispatcher()->dispatchScript(ScriptEvents::PRE_ARCHIVE_CMD);
1643 }
1644
1645 if (null === $input->getOption('format')) {
1646 $input->setOption('format', $config->get('archive-format'));
1647 }
1648 if (null === $input->getOption('dir')) {
1649 $input->setOption('dir', $config->get('archive-dir'));
1650 }
1651
1652 $returnCode = $this->archive(
1653 $this->getIO(),
1654 $config,
1655 $input->getArgument('package'),
1656 $input->getArgument('version'),
1657 $input->getOption('format'),
1658 $input->getOption('dir'),
1659 $input->getOption('file'),
1660 $input->getOption('ignore-filters'),
1661 $composer
1662 );
1663
1664 if (0 === $returnCode && $composer) {
1665 $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ARCHIVE_CMD);
1666 }
1667
1668 return $returnCode;
1669 }
1670
1671 protected function archive(IOInterface $io, Config $config, $packageName = null, $version = null, $format = 'tar', $dest = '.', $fileName = null, $ignoreFilters = false, Composer $composer = null)
1672 {
1673 if ($composer) {
1674 $archiveManager = $composer->getArchiveManager();
1675 } else {
1676 $factory = new Factory;
1677 $downloadManager = $factory->createDownloadManager($io, $config);
1678 $archiveManager = $factory->createArchiveManager($config, $downloadManager);
1679 }
1680
1681 if ($packageName) {
1682 $package = $this->selectPackage($io, $packageName, $version);
1683
1684 if (!$package) {
1685 return 1;
1686 }
1687 } else {
1688 $package = $this->getComposer()->getPackage();
1689 }
1690
1691 $io->writeError('<info>Creating the archive into "'.$dest.'".</info>');
1692 $packagePath = $archiveManager->archive($package, $format, $dest, $fileName, $ignoreFilters);
1693 $fs = new Filesystem;
1694 $shortPath = $fs->findShortestPath(getcwd(), $packagePath, true);
1695
1696 $io->writeError('Created: ', false);
1697 $io->write(strlen($shortPath) < strlen($packagePath) ? $shortPath : $packagePath);
1698
1699 return 0;
1700 }
1701
1702 protected function selectPackage(IOInterface $io, $packageName, $version = null)
1703 {
1704 $io->writeError('<info>Searching for the specified package.</info>');
1705
1706 if ($composer = $this->getComposer(false)) {
1707 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
1708 $repo = new CompositeRepository(array_merge(array($localRepo), $composer->getRepositoryManager()->getRepositories()));
1709 } else {
1710 $defaultRepos = RepositoryFactory::defaultRepos($this->getIO());
1711 $io->writeError('No composer.json found in the current directory, searching packages from ' . implode(', ', array_keys($defaultRepos)));
1712 $repo = new CompositeRepository($defaultRepos);
1713 }
1714
1715 $packages = $repo->findPackages($packageName, $version);
1716
1717 if (count($packages) > 1) {
1718 $package = reset($packages);
1719 $io->writeError('<info>Found multiple matches, selected '.$package->getPrettyString().'.</info>');
1720 $io->writeError('Alternatives were '.implode(', ', array_map(function ($p) {
1721 return $p->getPrettyString();
1722 }, $packages)).'.');
1723 $io->writeError('<comment>Please use a more specific constraint to pick a different package.</comment>');
1724 } elseif ($packages) {
1725 $package = reset($packages);
1726 $io->writeError('<info>Found an exact match '.$package->getPrettyString().'.</info>');
1727 } else {
1728 $io->writeError('<error>Could not find a package matching '.$packageName.'.</error>');
1729
1730 return false;
1731 }
1732
1733 return $package;
1734 }
1735 }
1736 <?php
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748 namespace Composer\Command;
1749
1750 use Composer\Composer;
1751 use Composer\Config;
1752 use Composer\Console\Application;
1753 use Composer\IO\IOInterface;
1754 use Composer\IO\NullIO;
1755 use Symfony\Component\Console\Input\InputInterface;
1756 use Symfony\Component\Console\Output\OutputInterface;
1757 use Symfony\Component\Console\Command\Command;
1758
1759
1760
1761
1762
1763
1764
1765 abstract class BaseCommand extends Command
1766 {
1767
1768
1769
1770 private $composer;
1771
1772
1773
1774
1775 private $io;
1776
1777
1778
1779
1780
1781
1782
1783 public function getComposer($required = true, $disablePlugins = null)
1784 {
1785 if (null === $this->composer) {
1786 $application = $this->getApplication();
1787 if ($application instanceof Application) {
1788
1789 $this->composer = $application->getComposer($required, $disablePlugins);
1790 } elseif ($required) {
1791 throw new \RuntimeException(
1792 'Could not create a Composer\Composer instance, you must inject '.
1793 'one if this command is not used with a Composer\Console\Application instance'
1794 );
1795 }
1796 }
1797
1798 return $this->composer;
1799 }
1800
1801
1802
1803
1804 public function setComposer(Composer $composer)
1805 {
1806 $this->composer = $composer;
1807 }
1808
1809
1810
1811
1812 public function resetComposer()
1813 {
1814 $this->composer = null;
1815 $this->getApplication()->resetComposer();
1816 }
1817
1818
1819
1820
1821
1822
1823
1824
1825 public function isProxyCommand()
1826 {
1827 return false;
1828 }
1829
1830
1831
1832
1833 public function getIO()
1834 {
1835 if (null === $this->io) {
1836 $application = $this->getApplication();
1837 if ($application instanceof Application) {
1838
1839 $this->io = $application->getIO();
1840 } else {
1841 $this->io = new NullIO();
1842 }
1843 }
1844
1845 return $this->io;
1846 }
1847
1848
1849
1850
1851 public function setIO(IOInterface $io)
1852 {
1853 $this->io = $io;
1854 }
1855
1856
1857
1858
1859 protected function initialize(InputInterface $input, OutputInterface $output)
1860 {
1861 if (true === $input->hasParameterOption(array('--no-ansi')) && $input->hasOption('no-progress')) {
1862 $input->setOption('no-progress', true);
1863 }
1864
1865 parent::initialize($input, $output);
1866 }
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877 protected function getPreferredInstallOptions(Config $config, InputInterface $input, $keepVcsRequiresPreferSource = false)
1878 {
1879 $preferSource = false;
1880 $preferDist = false;
1881
1882 switch ($config->get('preferred-install')) {
1883 case 'source':
1884 $preferSource = true;
1885 break;
1886 case 'dist':
1887 $preferDist = true;
1888 break;
1889 case 'auto':
1890 default:
1891
1892  break;
1893 }
1894
1895 if ($input->getOption('prefer-source') || $input->getOption('prefer-dist') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'))) {
1896 $preferSource = $input->getOption('prefer-source') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'));
1897 $preferDist = $input->getOption('prefer-dist');
1898 }
1899
1900 return array($preferSource, $preferDist);
1901 }
1902 }
1903 <?php
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915 namespace Composer\Command;
1916
1917 use Composer\DependencyResolver\Pool;
1918 use Composer\Package\Link;
1919 use Composer\Package\PackageInterface;
1920 use Composer\Repository\ArrayRepository;
1921 use Composer\Repository\CompositeRepository;
1922 use Composer\Repository\PlatformRepository;
1923 use Composer\Repository\RepositoryFactory;
1924 use Composer\Plugin\CommandEvent;
1925 use Composer\Plugin\PluginEvents;
1926 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
1927 use Composer\Package\Version\VersionParser;
1928 use Symfony\Component\Console\Helper\Table;
1929 use Symfony\Component\Console\Input\InputArgument;
1930 use Symfony\Component\Console\Input\InputInterface;
1931 use Symfony\Component\Console\Input\InputOption;
1932 use Symfony\Component\Console\Output\OutputInterface;
1933
1934
1935
1936
1937
1938
1939 class BaseDependencyCommand extends BaseCommand
1940 {
1941 const ARGUMENT_PACKAGE = 'package';
1942 const ARGUMENT_CONSTRAINT = 'constraint';
1943 const OPTION_RECURSIVE = 'recursive';
1944 const OPTION_TREE = 'tree';
1945
1946 protected $colors;
1947
1948
1949
1950
1951 protected function configure()
1952 {
1953 $this->setDefinition(array(
1954 new InputArgument(self::ARGUMENT_PACKAGE, InputArgument::REQUIRED, 'Package to inspect'),
1955 new InputArgument(self::ARGUMENT_CONSTRAINT, InputArgument::OPTIONAL, 'Optional version constraint', '*'),
1956 new InputOption(self::OPTION_RECURSIVE, 'r', InputOption::VALUE_NONE, 'Recursively resolves up to the root package'),
1957 new InputOption(self::OPTION_TREE, 't', InputOption::VALUE_NONE, 'Prints the results as a nested tree'),
1958 ));
1959 }
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969 protected function doExecute(InputInterface $input, OutputInterface $output, $inverted = false)
1970 {
1971
1972  $composer = $this->getComposer();
1973 $commandEvent = new CommandEvent(PluginEvents::COMMAND, $this->getName(), $input, $output);
1974 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
1975
1976
1977  $platformOverrides = $composer->getConfig()->get('platform') ?: array();
1978 $repository = new CompositeRepository(array(
1979 new ArrayRepository(array($composer->getPackage())),
1980 $composer->getRepositoryManager()->getLocalRepository(),
1981 new PlatformRepository(array(), $platformOverrides),
1982 ));
1983 $pool = new Pool();
1984 $pool->addRepository($repository);
1985
1986
1987  list($needle, $textConstraint) = array_pad(
1988 explode(':', $input->getArgument(self::ARGUMENT_PACKAGE)),
1989 2,
1990 $input->getArgument(self::ARGUMENT_CONSTRAINT)
1991 );
1992
1993
1994  $packages = $pool->whatProvides($needle);
1995 if (empty($packages)) {
1996 throw new \InvalidArgumentException(sprintf('Could not find package "%s" in your project', $needle));
1997 }
1998
1999
2000  
2001  if (!$repository->findPackage($needle, $textConstraint)) {
2002 $defaultRepos = new CompositeRepository(RepositoryFactory::defaultRepos($this->getIO()));
2003 if ($match = $defaultRepos->findPackage($needle, $textConstraint)) {
2004 $repository->addRepository(new ArrayRepository(array(clone $match)));
2005 }
2006 }
2007
2008
2009  $needles = array($needle);
2010 if ($inverted) {
2011 foreach ($packages as $package) {
2012 $needles = array_merge($needles, array_map(function (Link $link) {
2013 return $link->getTarget();
2014 }, $package->getReplaces()));
2015 }
2016 }
2017
2018
2019  if ('*' !== $textConstraint) {
2020 $versionParser = new VersionParser();
2021 $constraint = $versionParser->parseConstraints($textConstraint);
2022 } else {
2023 $constraint = null;
2024 }
2025
2026
2027  $renderTree = $input->getOption(self::OPTION_TREE);
2028 $recursive = $renderTree || $input->getOption(self::OPTION_RECURSIVE);
2029
2030
2031  $results = $repository->getDependents($needles, $constraint, $inverted, $recursive);
2032 if (empty($results)) {
2033 $extra = (null !== $constraint) ? sprintf(' in versions %smatching %s', $inverted ? 'not ' : '', $textConstraint) : '';
2034 $this->getIO()->writeError(sprintf('<info>There is no installed package depending on "%s"%s</info>',
2035 $needle, $extra));
2036 } elseif ($renderTree) {
2037 $this->initStyles($output);
2038 $root = $packages[0];
2039 $this->getIO()->write(sprintf('<info>%s</info> %s %s', $root->getPrettyName(), $root->getPrettyVersion(), $root->getDescription()));
2040 $this->printTree($results);
2041 } else {
2042 $this->printTable($output, $results);
2043 }
2044
2045 return 0;
2046 }
2047
2048
2049
2050
2051
2052
2053
2054 protected function printTable(OutputInterface $output, $results)
2055 {
2056 $table = array();
2057 $doubles = array();
2058 do {
2059 $queue = array();
2060 $rows = array();
2061 foreach ($results as $result) {
2062
2063
2064
2065
2066 list($package, $link, $children) = $result;
2067 $unique = (string) $link;
2068 if (isset($doubles[$unique])) {
2069 continue;
2070 }
2071 $doubles[$unique] = true;
2072 $version = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '-' : $package->getPrettyVersion();
2073 $rows[] = array($package->getPrettyName(), $version, $link->getDescription(), sprintf('%s (%s)', $link->getTarget(), $link->getPrettyConstraint()));
2074 if ($children) {
2075 $queue = array_merge($queue, $children);
2076 }
2077 }
2078 $results = $queue;
2079 $table = array_merge($rows, $table);
2080 } while (!empty($results));
2081
2082
2083  $renderer = new Table($output);
2084 $renderer->setStyle('compact');
2085 $renderer->getStyle()->setVerticalBorderChar('');
2086 $renderer->getStyle()->setCellRowContentFormat('%s  ');
2087 $renderer->setRows($table)->render();
2088 }
2089
2090
2091
2092
2093
2094
2095 protected function initStyles(OutputInterface $output)
2096 {
2097 $this->colors = array(
2098 'green',
2099 'yellow',
2100 'cyan',
2101 'magenta',
2102 'blue',
2103 );
2104
2105 foreach ($this->colors as $color) {
2106 $style = new OutputFormatterStyle($color);
2107 $output->getFormatter()->setStyle($color, $style);
2108 }
2109 }
2110
2111
2112
2113
2114
2115
2116
2117
2118 protected function printTree($results, $prefix = '', $level = 1)
2119 {
2120 $count = count($results);
2121 $idx = 0;
2122 foreach ($results as $result) {
2123
2124
2125
2126
2127
2128 list($package, $link, $children) = $result;
2129
2130 $color = $this->colors[$level % count($this->colors)];
2131 $prevColor = $this->colors[($level - 1) % count($this->colors)];
2132 $isLast = (++$idx == $count);
2133 $versionText = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '' : $package->getPrettyVersion();
2134 $packageText = rtrim(sprintf('<%s>%s</%1$s> %s', $color, $package->getPrettyName(), $versionText));
2135 $linkText = sprintf('%s <%s>%s</%2$s> %s', $link->getDescription(), $prevColor, $link->getTarget(), $link->getPrettyConstraint());
2136 $circularWarn = $children === false ? '(circular dependency aborted here)' : '';
2137 $this->writeTreeLine(rtrim(sprintf("%s%s%s (%s) %s", $prefix, $isLast ? '└──' : '├──', $packageText, $linkText, $circularWarn)));
2138 if ($children) {
2139 $this->printTree($children, $prefix . ($isLast ? '   ' : '│  '), $level + 1);
2140 }
2141 }
2142 }
2143
2144 private function writeTreeLine($line)
2145 {
2146 $io = $this->getIO();
2147 if (!$io->isDecorated()) {
2148 $line = str_replace(array('└', '├', '──', '│'), array('`-', '|-', '-', '|'), $line);
2149 }
2150
2151 $io->write($line);
2152 }
2153 }
2154 <?php
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166 namespace Composer\Command;
2167
2168 use Composer\Cache;
2169 use Composer\Factory;
2170 use Symfony\Component\Console\Input\InputInterface;
2171 use Symfony\Component\Console\Output\OutputInterface;
2172
2173
2174
2175
2176 class ClearCacheCommand extends BaseCommand
2177 {
2178 protected function configure()
2179 {
2180 $this
2181 ->setName('clear-cache')
2182 ->setAliases(array('clearcache'))
2183 ->setDescription('Clears composer\'s internal package cache.')
2184 ->setHelp(<<<EOT
2185 The <info>clear-cache</info> deletes all cached packages from composer's
2186 cache directory.
2187 EOT
2188 )
2189 ;
2190 }
2191
2192 protected function execute(InputInterface $input, OutputInterface $output)
2193 {
2194 $config = Factory::createConfig();
2195 $io = $this->getIO();
2196
2197 $cachePaths = array(
2198 'cache-vcs-dir' => $config->get('cache-vcs-dir'),
2199 'cache-repo-dir' => $config->get('cache-repo-dir'),
2200 'cache-files-dir' => $config->get('cache-files-dir'),
2201 'cache-dir' => $config->get('cache-dir'),
2202 );
2203
2204 foreach ($cachePaths as $key => $cachePath) {
2205 $cachePath = realpath($cachePath);
2206 if (!$cachePath) {
2207 $io->writeError("<info>Cache directory does not exist ($key): $cachePath</info>");
2208
2209 continue;
2210 }
2211 $cache = new Cache($io, $cachePath);
2212 if (!$cache->isEnabled()) {
2213 $io->writeError("<info>Cache is not enabled ($key): $cachePath</info>");
2214
2215 continue;
2216 }
2217
2218 $io->writeError("<info>Clearing cache ($key): $cachePath</info>");
2219 $cache->clear();
2220 }
2221
2222 $io->writeError('<info>All caches cleared.</info>');
2223 }
2224 }
2225 <?php
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237 namespace Composer\Command;
2238
2239 use Composer\Util\Platform;
2240 use Composer\Util\Silencer;
2241 use Symfony\Component\Console\Input\InputInterface;
2242 use Symfony\Component\Console\Input\InputArgument;
2243 use Symfony\Component\Console\Input\InputOption;
2244 use Symfony\Component\Console\Output\OutputInterface;
2245 use Composer\Config;
2246 use Composer\Config\JsonConfigSource;
2247 use Composer\Factory;
2248 use Composer\Json\JsonFile;
2249 use Composer\Semver\VersionParser;
2250 use Composer\Package\BasePackage;
2251
2252
2253
2254
2255
2256 class ConfigCommand extends BaseCommand
2257 {
2258
2259
2260
2261 protected $config;
2262
2263
2264
2265
2266 protected $configFile;
2267
2268
2269
2270
2271 protected $configSource;
2272
2273
2274
2275
2276 protected $authConfigFile;
2277
2278
2279
2280
2281 protected $authConfigSource;
2282
2283
2284
2285
2286 protected function configure()
2287 {
2288 $this
2289 ->setName('config')
2290 ->setDescription('Sets config options.')
2291 ->setDefinition(array(
2292 new InputOption('global', 'g', InputOption::VALUE_NONE, 'Apply command to the global config file'),
2293 new InputOption('editor', 'e', InputOption::VALUE_NONE, 'Open editor'),
2294 new InputOption('auth', 'a', InputOption::VALUE_NONE, 'Affect auth config file (only used for --editor)'),
2295 new InputOption('unset', null, InputOption::VALUE_NONE, 'Unset the given setting-key'),
2296 new InputOption('list', 'l', InputOption::VALUE_NONE, 'List configuration settings'),
2297 new InputOption('file', 'f', InputOption::VALUE_REQUIRED, 'If you want to choose a different composer.json or config.json'),
2298 new InputOption('absolute', null, InputOption::VALUE_NONE, 'Returns absolute paths when fetching *-dir config values instead of relative'),
2299 new InputArgument('setting-key', null, 'Setting key'),
2300 new InputArgument('setting-value', InputArgument::IS_ARRAY, 'Setting value'),
2301 ))
2302 ->setHelp(<<<EOT
2303 This command allows you to edit composer config settings and repositories
2304 in either the local composer.json file or the global config.json file.
2305
2306 Additionally it lets you edit most properties in the local composer.json.
2307
2308 To set a config setting:
2309
2310     <comment>%command.full_name% bin-dir bin/</comment>
2311
2312 To read a config setting:
2313
2314     <comment>%command.full_name% bin-dir</comment>
2315     Outputs: <info>bin</info>
2316
2317 To edit the global config.json file:
2318
2319     <comment>%command.full_name% --global</comment>
2320
2321 To add a repository:
2322
2323     <comment>%command.full_name% repositories.foo vcs https://bar.com</comment>
2324
2325 To remove a repository (repo is a short alias for repositories):
2326
2327     <comment>%command.full_name% --unset repo.foo</comment>
2328
2329 To disable packagist:
2330
2331     <comment>%command.full_name% repo.packagist false</comment>
2332
2333 You can alter repositories in the global config.json file by passing in the
2334 <info>--global</info> option.
2335
2336 To edit the file in an external editor:
2337
2338     <comment>%command.full_name% --editor</comment>
2339
2340 To choose your editor you can set the "EDITOR" env variable.
2341
2342 To get a list of configuration values in the file:
2343
2344     <comment>%command.full_name% --list</comment>
2345
2346 You can always pass more than one option. As an example, if you want to edit the
2347 global config.json file.
2348
2349     <comment>%command.full_name% --editor --global</comment>
2350 EOT
2351 )
2352 ;
2353 }
2354
2355
2356
2357
2358 protected function initialize(InputInterface $input, OutputInterface $output)
2359 {
2360 parent::initialize($input, $output);
2361
2362 if ($input->getOption('global') && null !== $input->getOption('file')) {
2363 throw new \RuntimeException('--file and --global can not be combined');
2364 }
2365
2366 $io = $this->getIO();
2367 $this->config = Factory::createConfig($io);
2368
2369
2370  
2371  $configFile = $input->getOption('global')
2372 ? ($this->config->get('home') . '/config.json')
2373 : ($input->getOption('file') ?: Factory::getComposerFile());
2374
2375
2376  if (
2377 ($configFile === 'composer.json' || $configFile === './composer.json')
2378 && !file_exists($configFile)
2379 && realpath(getcwd()) === realpath($this->config->get('home'))
2380 ) {
2381 file_put_contents($configFile, "{\n}\n");
2382 }
2383
2384 $this->configFile = new JsonFile($configFile, null, $io);
2385 $this->configSource = new JsonConfigSource($this->configFile);
2386
2387 $authConfigFile = $input->getOption('global')
2388 ? ($this->config->get('home') . '/auth.json')
2389 : dirname(realpath($configFile)) . '/auth.json';
2390
2391 $this->authConfigFile = new JsonFile($authConfigFile, null, $io);
2392 $this->authConfigSource = new JsonConfigSource($this->authConfigFile, true);
2393
2394
2395  if ($input->getOption('global') && !$this->configFile->exists()) {
2396 touch($this->configFile->getPath());
2397 $this->configFile->write(array('config' => new \ArrayObject));
2398 Silencer::call('chmod', $this->configFile->getPath(), 0600);
2399 }
2400 if ($input->getOption('global') && !$this->authConfigFile->exists()) {
2401 touch($this->authConfigFile->getPath());
2402 $this->authConfigFile->write(array('bitbucket-oauth' => new \ArrayObject, 'github-oauth' => new \ArrayObject, 'gitlab-oauth' => new \ArrayObject, 'gitlab-token' => new \ArrayObject, 'http-basic' => new \ArrayObject));
2403 Silencer::call('chmod', $this->authConfigFile->getPath(), 0600);
2404 }
2405
2406 if (!$this->configFile->exists()) {
2407 throw new \RuntimeException(sprintf('File "%s" cannot be found in the current directory', $configFile));
2408 }
2409 }
2410
2411
2412
2413
2414 protected function execute(InputInterface $input, OutputInterface $output)
2415 {
2416
2417  if ($input->getOption('editor')) {
2418 $editor = escapeshellcmd(getenv('EDITOR'));
2419 if (!$editor) {
2420 if (Platform::isWindows()) {
2421 $editor = 'notepad';
2422 } else {
2423 foreach (array('editor', 'vim', 'vi', 'nano', 'pico', 'ed') as $candidate) {
2424 if (exec('which '.$candidate)) {
2425 $editor = $candidate;
2426 break;
2427 }
2428 }
2429 }
2430 }
2431
2432 $file = $input->getOption('auth') ? $this->authConfigFile->getPath() : $this->configFile->getPath();
2433 system($editor . ' ' . $file . (Platform::isWindows() ? '' : ' > `tty`'));
2434
2435 return 0;
2436 }
2437
2438 if (!$input->getOption('global')) {
2439 $this->config->merge($this->configFile->read());
2440 $this->config->merge(array('config' => $this->authConfigFile->exists() ? $this->authConfigFile->read() : array()));
2441 }
2442
2443
2444  if ($input->getOption('list')) {
2445 $this->listConfiguration($this->config->all(), $this->config->raw(), $output);
2446
2447 return 0;
2448 }
2449
2450 $settingKey = $input->getArgument('setting-key');
2451 if (!$settingKey) {
2452 return 0;
2453 }
2454
2455
2456  if (array() !== $input->getArgument('setting-value') && $input->getOption('unset')) {
2457 throw new \RuntimeException('You can not combine a setting value with --unset');
2458 }
2459
2460
2461  if (array() === $input->getArgument('setting-value') && !$input->getOption('unset')) {
2462 $properties = array('name', 'type', 'description', 'homepage', 'version', 'minimum-stability', 'prefer-stable', 'keywords', 'license', 'extra');
2463 $rawData = $this->configFile->read();
2464 $data = $this->config->all();
2465 if (preg_match('/^repos?(?:itories)?(?:\.(.+))?/', $settingKey, $matches)) {
2466 if (!isset($matches[1]) || $matches[1] === '') {
2467 $value = isset($data['repositories']) ? $data['repositories'] : array();
2468 } else {
2469 if (!isset($data['repositories'][$matches[1]])) {
2470 throw new \InvalidArgumentException('There is no '.$matches[1].' repository defined');
2471 }
2472
2473 $value = $data['repositories'][$matches[1]];
2474 }
2475 } elseif (strpos($settingKey, '.')) {
2476 $bits = explode('.', $settingKey);
2477 if ($bits[0] === 'extra') {
2478 $data = $rawData;
2479 } else {
2480 $data = $data['config'];
2481 }
2482 $match = false;
2483 foreach ($bits as $bit) {
2484 $key = isset($key) ? $key.'.'.$bit : $bit;
2485 $match = false;
2486 if (isset($data[$key])) {
2487 $match = true;
2488 $data = $data[$key];
2489 unset($key);
2490 }
2491 }
2492
2493 if (!$match) {
2494 throw new \RuntimeException($settingKey.' is not defined.');
2495 }
2496
2497 $value = $data;
2498 } elseif (isset($data['config'][$settingKey])) {
2499 $value = $this->config->get($settingKey, $input->getOption('absolute') ? 0 : Config::RELATIVE_PATHS);
2500 } elseif (in_array($settingKey, $properties, true) && isset($rawData[$settingKey])) {
2501 $value = $rawData[$settingKey];
2502 } else {
2503 throw new \RuntimeException($settingKey.' is not defined');
2504 }
2505
2506 if (is_array($value)) {
2507 $value = json_encode($value);
2508 }
2509
2510 $this->getIO()->write($value);
2511
2512 return 0;
2513 }
2514
2515 $values = $input->getArgument('setting-value'); 
2516
2517 $booleanValidator = function ($val) {
2518 return in_array($val, array('true', 'false', '1', '0'), true);
2519 };
2520 $booleanNormalizer = function ($val) {
2521 return $val !== 'false' && (bool) $val;
2522 };
2523
2524
2525  $uniqueConfigValues = array(
2526 'process-timeout' => array('is_numeric', 'intval'),
2527 'use-include-path' => array($booleanValidator, $booleanNormalizer),
2528 'preferred-install' => array(
2529 function ($val) {
2530 return in_array($val, array('auto', 'source', 'dist'), true);
2531 },
2532 function ($val) {
2533 return $val;
2534 },
2535 ),
2536 'store-auths' => array(
2537 function ($val) {
2538 return in_array($val, array('true', 'false', 'prompt'), true);
2539 },
2540 function ($val) {
2541 if ('prompt' === $val) {
2542 return 'prompt';
2543 }
2544
2545 return $val !== 'false' && (bool) $val;
2546 },
2547 ),
2548 'notify-on-install' => array($booleanValidator, $booleanNormalizer),
2549 'vendor-dir' => array('is_string', function ($val) {
2550 return $val;
2551 }),
2552 'bin-dir' => array('is_string', function ($val) {
2553 return $val;
2554 }),
2555 'archive-dir' => array('is_string', function ($val) {
2556 return $val;
2557 }),
2558 'archive-format' => array('is_string', function ($val) {
2559 return $val;
2560 }),
2561 'data-dir' => array('is_string', function ($val) {
2562 return $val;
2563 }),
2564 'cache-dir' => array('is_string', function ($val) {
2565 return $val;
2566 }),
2567 'cache-files-dir' => array('is_string', function ($val) {
2568 return $val;
2569 }),
2570 'cache-repo-dir' => array('is_string', function ($val) {
2571 return $val;
2572 }),
2573 'cache-vcs-dir' => array('is_string', function ($val) {
2574 return $val;
2575 }),
2576 'cache-ttl' => array('is_numeric', 'intval'),
2577 'cache-files-ttl' => array('is_numeric', 'intval'),
2578 'cache-files-maxsize' => array(
2579 function ($val) {
2580 return preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $val) > 0;
2581 },
2582 function ($val) {
2583 return $val;
2584 },
2585 ),
2586 'bin-compat' => array(
2587 function ($val) {
2588 return in_array($val, array('auto', 'full'));
2589 },
2590 function ($val) {
2591 return $val;
2592 },
2593 ),
2594 'discard-changes' => array(
2595 function ($val) {
2596 return in_array($val, array('stash', 'true', 'false', '1', '0'), true);
2597 },
2598 function ($val) {
2599 if ('stash' === $val) {
2600 return 'stash';
2601 }
2602
2603 return $val !== 'false' && (bool) $val;
2604 },
2605 ),
2606 'autoloader-suffix' => array('is_string', function ($val) {
2607 return $val === 'null' ? null : $val;
2608 }),
2609 'sort-packages' => array($booleanValidator, $booleanNormalizer),
2610 'optimize-autoloader' => array($booleanValidator, $booleanNormalizer),
2611 'classmap-authoritative' => array($booleanValidator, $booleanNormalizer),
2612 'apcu-autoloader' => array($booleanValidator, $booleanNormalizer),
2613 'prepend-autoloader' => array($booleanValidator, $booleanNormalizer),
2614 'disable-tls' => array($booleanValidator, $booleanNormalizer),
2615 'secure-http' => array($booleanValidator, $booleanNormalizer),
2616 'cafile' => array(
2617 function ($val) {
2618 return file_exists($val) && is_readable($val);
2619 },
2620 function ($val) {
2621 return $val === 'null' ? null : $val;
2622 },
2623 ),
2624 'capath' => array(
2625 function ($val) {
2626 return is_dir($val) && is_readable($val);
2627 },
2628 function ($val) {
2629 return $val === 'null' ? null : $val;
2630 },
2631 ),
2632 'github-expose-hostname' => array($booleanValidator, $booleanNormalizer),
2633 'htaccess-protect' => array($booleanValidator, $booleanNormalizer),
2634 );
2635 $multiConfigValues = array(
2636 'github-protocols' => array(
2637 function ($vals) {
2638 if (!is_array($vals)) {
2639 return 'array expected';
2640 }
2641
2642 foreach ($vals as $val) {
2643 if (!in_array($val, array('git', 'https', 'ssh'))) {
2644 return 'valid protocols include: git, https, ssh';
2645 }
2646 }
2647
2648 return true;
2649 },
2650 function ($vals) {
2651 return $vals;
2652 },
2653 ),
2654 'github-domains' => array(
2655 function ($vals) {
2656 if (!is_array($vals)) {
2657 return 'array expected';
2658 }
2659
2660 return true;
2661 },
2662 function ($vals) {
2663 return $vals;
2664 },
2665 ),
2666 'gitlab-domains' => array(
2667 function ($vals) {
2668 if (!is_array($vals)) {
2669 return 'array expected';
2670 }
2671
2672 return true;
2673 },
2674 function ($vals) {
2675 return $vals;
2676 },
2677 ),
2678 );
2679
2680 if ($input->getOption('unset') && (isset($uniqueConfigValues[$settingKey]) || isset($multiConfigValues[$settingKey]))) {
2681 return $this->configSource->removeConfigSetting($settingKey);
2682 }
2683 if (isset($uniqueConfigValues[$settingKey])) {
2684 return $this->handleSingleValue($settingKey, $uniqueConfigValues[$settingKey], $values, 'addConfigSetting');
2685 }
2686 if (isset($multiConfigValues[$settingKey])) {
2687 return $this->handleMultiValue($settingKey, $multiConfigValues[$settingKey], $values, 'addConfigSetting');
2688 }
2689
2690
2691  $uniqueProps = array(
2692 'name' => array('is_string', function ($val) {
2693 return $val;
2694 }),
2695 'type' => array('is_string', function ($val) {
2696 return $val;
2697 }),
2698 'description' => array('is_string', function ($val) {
2699 return $val;
2700 }),
2701 'homepage' => array('is_string', function ($val) {
2702 return $val;
2703 }),
2704 'version' => array('is_string', function ($val) {
2705 return $val;
2706 }),
2707 'minimum-stability' => array(
2708 function ($val) {
2709 return isset(BasePackage::$stabilities[VersionParser::normalizeStability($val)]);
2710 },
2711 function ($val) {
2712 return VersionParser::normalizeStability($val);
2713 },
2714 ),
2715 'prefer-stable' => array($booleanValidator, $booleanNormalizer),
2716 );
2717 $multiProps = array(
2718 'keywords' => array(
2719 function ($vals) {
2720 if (!is_array($vals)) {
2721 return 'array expected';
2722 }
2723
2724 return true;
2725 },
2726 function ($vals) {
2727 return $vals;
2728 },
2729 ),
2730 'license' => array(
2731 function ($vals) {
2732 if (!is_array($vals)) {
2733 return 'array expected';
2734 }
2735
2736 return true;
2737 },
2738 function ($vals) {
2739 return $vals;
2740 },
2741 ),
2742 );
2743
2744 if ($input->getOption('global') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]) || substr($settingKey, 0, 6) === 'extra.')) {
2745 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');
2746 }
2747 if ($input->getOption('unset') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]))) {
2748 return $this->configSource->removeProperty($settingKey);
2749 }
2750 if (isset($uniqueProps[$settingKey])) {
2751 return $this->handleSingleValue($settingKey, $uniqueProps[$settingKey], $values, 'addProperty');
2752 }
2753 if (isset($multiProps[$settingKey])) {
2754 return $this->handleMultiValue($settingKey, $multiProps[$settingKey], $values, 'addProperty');
2755 }
2756
2757
2758  if (preg_match('/^repos?(?:itories)?\.(.+)/', $settingKey, $matches)) {
2759 if ($input->getOption('unset')) {
2760 return $this->configSource->removeRepository($matches[1]);
2761 }
2762
2763 if (2 === count($values)) {
2764 return $this->configSource->addRepository($matches[1], array(
2765 'type' => $values[0],
2766 'url' => $values[1],
2767 ));
2768 }
2769
2770 if (1 === count($values)) {
2771 $value = strtolower($values[0]);
2772 if (true === $booleanValidator($value)) {
2773 if (false === $booleanNormalizer($value)) {
2774 return $this->configSource->addRepository($matches[1], false);
2775 }
2776 } else {
2777 $value = JsonFile::parseJson($values[0]);
2778
2779 return $this->configSource->addRepository($matches[1], $value);
2780 }
2781 }
2782
2783 throw new \RuntimeException('You must pass the type and a url. Example: php composer.phar config repositories.foo vcs https://bar.com');
2784 }
2785
2786
2787  if (preg_match('/^extra\.(.+)/', $settingKey, $matches)) {
2788 if ($input->getOption('unset')) {
2789 return $this->configSource->removeProperty($settingKey);
2790 }
2791
2792 return $this->configSource->addProperty($settingKey, $values[0]);
2793 }
2794
2795
2796  if (preg_match('/^platform\.(.+)/', $settingKey, $matches)) {
2797 if ($input->getOption('unset')) {
2798 return $this->configSource->removeConfigSetting($settingKey);
2799 }
2800
2801 return $this->configSource->addConfigSetting($settingKey, $values[0]);
2802 }
2803
2804
2805  if (preg_match('/^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic)\.(.+)/', $settingKey, $matches)) {
2806 if ($input->getOption('unset')) {
2807 $this->authConfigSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2808 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2809
2810 return;
2811 }
2812
2813 if ($matches[1] === 'bitbucket-oauth') {
2814 if (2 !== count($values)) {
2815 throw new \RuntimeException('Expected two arguments (consumer-key, consumer-secret), got '.count($values));
2816 }
2817 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2818 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('consumer-key' => $values[0], 'consumer-secret' => $values[1]));
2819 } elseif (in_array($matches[1], array('github-oauth', 'gitlab-oauth', 'gitlab-token'), true)) {
2820 if (1 !== count($values)) {
2821 throw new \RuntimeException('Too many arguments, expected only one token');
2822 }
2823 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2824 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], $values[0]);
2825 } elseif ($matches[1] === 'http-basic') {
2826 if (2 !== count($values)) {
2827 throw new \RuntimeException('Expected two arguments (username, password), got '.count($values));
2828 }
2829 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2830 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('username' => $values[0], 'password' => $values[1]));
2831 }
2832
2833 return;
2834 }
2835
2836 throw new \InvalidArgumentException('Setting '.$settingKey.' does not exist or is not supported by this command');
2837 }
2838
2839 protected function handleSingleValue($key, array $callbacks, array $values, $method)
2840 {
2841 list($validator, $normalizer) = $callbacks;
2842 if (1 !== count($values)) {
2843 throw new \RuntimeException('You can only pass one value. Example: php composer.phar config process-timeout 300');
2844 }
2845
2846 if (true !== $validation = $validator($values[0])) {
2847 throw new \RuntimeException(sprintf(
2848 '"%s" is an invalid value'.($validation ? ' ('.$validation.')' : ''),
2849 $values[0]
2850 ));
2851 }
2852
2853 return call_user_func(array($this->configSource, $method), $key, $normalizer($values[0]));
2854 }
2855
2856 protected function handleMultiValue($key, array $callbacks, array $values, $method)
2857 {
2858 list($validator, $normalizer) = $callbacks;
2859 if (true !== $validation = $validator($values)) {
2860 throw new \RuntimeException(sprintf(
2861 '%s is an invalid value'.($validation ? ' ('.$validation.')' : ''),
2862 json_encode($values)
2863 ));
2864 }
2865
2866 return call_user_func(array($this->configSource, $method), $key, $normalizer($values));
2867 }
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877 protected function listConfiguration(array $contents, array $rawContents, OutputInterface $output, $k = null)
2878 {
2879 $origK = $k;
2880 $io = $this->getIO();
2881 foreach ($contents as $key => $value) {
2882 if ($k === null && !in_array($key, array('config', 'repositories'))) {
2883 continue;
2884 }
2885
2886 $rawVal = isset($rawContents[$key]) ? $rawContents[$key] : null;
2887
2888 if (is_array($value) && (!is_numeric(key($value)) || ($key === 'repositories' && null === $k))) {
2889 $k .= preg_replace('{^config\.}', '', $key . '.');
2890 $this->listConfiguration($value, $rawVal, $output, $k);
2891 $k = $origK;
2892
2893 continue;
2894 }
2895
2896 if (is_array($value)) {
2897 $value = array_map(function ($val) {
2898 return is_array($val) ? json_encode($val) : $val;
2899 }, $value);
2900
2901 $value = '['.implode(', ', $value).']';
2902 }
2903
2904 if (is_bool($value)) {
2905 $value = var_export($value, true);
2906 }
2907
2908 if (is_string($rawVal) && $rawVal != $value) {
2909 $io->write('[<comment>' . $k . $key . '</comment>] <info>' . $rawVal . ' (' . $value . ')</info>');
2910 } else {
2911 $io->write('[<comment>' . $k . $key . '</comment>] <info>' . $value . '</info>');
2912 }
2913 }
2914 }
2915 }
2916 <?php
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928 namespace Composer\Command;
2929
2930 use Composer\Config;
2931 use Composer\Factory;
2932 use Composer\Installer;
2933 use Composer\Installer\ProjectInstaller;
2934 use Composer\Installer\InstallationManager;
2935 use Composer\Installer\SuggestedPackagesReporter;
2936 use Composer\IO\IOInterface;
2937 use Composer\Package\BasePackage;
2938 use Composer\DependencyResolver\Pool;
2939 use Composer\DependencyResolver\Operation\InstallOperation;
2940 use Composer\Package\Version\VersionSelector;
2941 use Composer\Package\AliasPackage;
2942 use Composer\Repository\RepositoryFactory;
2943 use Composer\Repository\CompositeRepository;
2944 use Composer\Repository\PlatformRepository;
2945 use Composer\Repository\InstalledFilesystemRepository;
2946 use Composer\Script\ScriptEvents;
2947 use Composer\Util\Silencer;
2948 use Symfony\Component\Console\Input\InputArgument;
2949 use Symfony\Component\Console\Input\InputInterface;
2950 use Symfony\Component\Console\Input\InputOption;
2951 use Symfony\Component\Console\Output\OutputInterface;
2952 use Symfony\Component\Finder\Finder;
2953 use Composer\Json\JsonFile;
2954 use Composer\Config\JsonConfigSource;
2955 use Composer\Util\Filesystem;
2956 use Composer\Package\Version\VersionParser;
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966 class CreateProjectCommand extends BaseCommand
2967 {
2968
2969
2970
2971 protected $suggestedPackagesReporter;
2972
2973 protected function configure()
2974 {
2975 $this
2976 ->setName('create-project')
2977 ->setDescription('Creates new project from a package into given directory.')
2978 ->setDefinition(array(
2979 new InputArgument('package', InputArgument::OPTIONAL, 'Package name to be installed'),
2980 new InputArgument('directory', InputArgument::OPTIONAL, 'Directory where the files should be created'),
2981 new InputArgument('version', InputArgument::OPTIONAL, 'Version, will default to latest'),
2982 new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum-stability allowed (unless a version is specified).'),
2983 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
2984 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
2985 new InputOption('repository', null, InputOption::VALUE_REQUIRED, 'Pick a different repository (as url or json config) to look for the package.'),
2986 new InputOption('repository-url', null, InputOption::VALUE_REQUIRED, 'DEPRECATED: Use --repository instead.'),
2987 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
2988 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
2989 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
2990 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Whether to prevent execution of all defined scripts in the root package.'),
2991 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
2992 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.'),
2993 new InputOption('keep-vcs', null, InputOption::VALUE_NONE, 'Whether to prevent deletion vcs folder.'),
2994 new InputOption('no-install', null, InputOption::VALUE_NONE, 'Whether to skip installation of the package dependencies.'),
2995 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
2996 ))
2997 ->setHelp(<<<EOT
2998 The <info>create-project</info> command creates a new project from a given
2999 package into a new directory. If executed without params and in a directory
3000 with a composer.json file it installs the packages for the current project.
3001
3002 You can use this command to bootstrap new projects or setup a clean
3003 version-controlled installation for developers of your project.
3004
3005 <info>php composer.phar create-project vendor/project target-directory [version]</info>
3006
3007 You can also specify the version with the package name using = or : as separator.
3008
3009 <info>php composer.phar create-project vendor/project:version target-directory</info>
3010
3011 To install unstable packages, either specify the version you want, or use the
3012 --stability=dev (where dev can be one of RC, beta, alpha or dev).
3013
3014 To setup a developer workable version you should create the project using the source
3015 controlled code by appending the <info>'--prefer-source'</info> flag.
3016
3017 To install a package from another repository than the default one you
3018 can pass the <info>'--repository=https://myrepository.org'</info> flag.
3019
3020 EOT
3021 )
3022 ;
3023 }
3024
3025 protected function execute(InputInterface $input, OutputInterface $output)
3026 {
3027 $config = Factory::createConfig();
3028 $io = $this->getIO();
3029
3030 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input, true);
3031
3032 if ($input->getOption('dev')) {
3033 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
3034 }
3035 if ($input->getOption('no-custom-installers')) {
3036 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
3037 $input->setOption('no-plugins', true);
3038 }
3039
3040 return $this->installProject(
3041 $io,
3042 $config,
3043 $input,
3044 $input->getArgument('package'),
3045 $input->getArgument('directory'),
3046 $input->getArgument('version'),
3047 $input->getOption('stability'),
3048 $preferSource,
3049 $preferDist,
3050 !$input->getOption('no-dev'),
3051 $input->getOption('repository') ?: $input->getOption('repository-url'),
3052 $input->getOption('no-plugins'),
3053 $input->getOption('no-scripts'),
3054 $input->getOption('keep-vcs'),
3055 $input->getOption('no-progress'),
3056 $input->getOption('no-install'),
3057 $input->getOption('ignore-platform-reqs'),
3058 !$input->getOption('no-secure-http')
3059 );
3060 }
3061
3062 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)
3063 {
3064 $oldCwd = getcwd();
3065
3066
3067  $io->loadConfiguration($config);
3068
3069 $this->suggestedPackagesReporter = new SuggestedPackagesReporter($io);
3070
3071 if ($packageName !== null) {
3072 $installedFromVcs = $this->installRootPackage($io, $config, $packageName, $directory, $packageVersion, $stability, $preferSource, $preferDist, $installDevPackages, $repository, $disablePlugins, $noScripts, $keepVcs, $noProgress, $ignorePlatformReqs, $secureHttp);
3073 } else {
3074 $installedFromVcs = false;
3075 }
3076
3077 $composer = Factory::create($io, null, $disablePlugins);
3078 $composer->getDownloadManager()->setOutputProgress(!$noProgress);
3079
3080 $fs = new Filesystem();
3081
3082 if ($noScripts === false) {
3083
3084  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ROOT_PACKAGE_INSTALL, $installDevPackages);
3085 }
3086
3087
3088  $config = $composer->getConfig();
3089 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
3090
3091
3092  if ($noInstall === false) {
3093 $installer = Installer::create($io, $composer);
3094 $installer->setPreferSource($preferSource)
3095 ->setPreferDist($preferDist)
3096 ->setDevMode($installDevPackages)
3097 ->setRunScripts(!$noScripts)
3098 ->setIgnorePlatformRequirements($ignorePlatformReqs)
3099 ->setSuggestedPackagesReporter($this->suggestedPackagesReporter)
3100 ->setOptimizeAutoloader($config->get('optimize-autoloader'));
3101
3102 if ($disablePlugins) {
3103 $installer->disablePlugins();
3104 }
3105
3106 $status = $installer->run();
3107 if (0 !== $status) {
3108 return $status;
3109 }
3110 }
3111
3112 $hasVcs = $installedFromVcs;
3113 if (!$keepVcs && $installedFromVcs
3114 && (
3115 !$io->isInteractive()
3116 || $io->askConfirmation('<info>Do you want to remove the existing VCS (.git, .svn..) history?</info> [<comment>Y,n</comment>]? ', true)
3117 )
3118 ) {
3119 $finder = new Finder();
3120 $finder->depth(0)->directories()->in(getcwd())->ignoreVCS(false)->ignoreDotFiles(false);
3121 foreach (array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg', '.fslckout', '_FOSSIL_') as $vcsName) {
3122 $finder->name($vcsName);
3123 }
3124
3125 try {
3126 $dirs = iterator_to_array($finder);
3127 unset($finder);
3128 foreach ($dirs as $dir) {
3129 if (!$fs->removeDirectory($dir)) {
3130 throw new \RuntimeException('Could not remove '.$dir);
3131 }
3132 }
3133 } catch (\Exception $e) {
3134 $io->writeError('<error>An error occurred while removing the VCS metadata: '.$e->getMessage().'</error>');
3135 }
3136
3137 $hasVcs = false;
3138 }
3139
3140
3141  if (!$hasVcs) {
3142 $package = $composer->getPackage();
3143 $configSource = new JsonConfigSource(new JsonFile('composer.json'));
3144 foreach (BasePackage::$supportedLinkTypes as $type => $meta) {
3145 foreach ($package->{'get'.$meta['method']}() as $link) {
3146 if ($link->getPrettyConstraint() === 'self.version') {
3147 $configSource->addLink($type, $link->getTarget(), $package->getPrettyVersion());
3148 }
3149 }
3150 }
3151 }
3152
3153 if ($noScripts === false) {
3154
3155  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_CREATE_PROJECT_CMD, $installDevPackages);
3156 }
3157
3158 chdir($oldCwd);
3159 $vendorComposerDir = $config->get('vendor-dir').'/composer';
3160 if (is_dir($vendorComposerDir) && $fs->isDirEmpty($vendorComposerDir)) {
3161 Silencer::call('rmdir', $vendorComposerDir);
3162 $vendorDir = $config->get('vendor-dir');
3163 if (is_dir($vendorDir) && $fs->isDirEmpty($vendorDir)) {
3164 Silencer::call('rmdir', $vendorDir);
3165 }
3166 }
3167
3168 return 0;
3169 }
3170
3171 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)
3172 {
3173 if (!$secureHttp) {
3174 $config->merge(array('config' => array('secure-http' => false)));
3175 }
3176
3177 if (null === $repository) {
3178 $sourceRepo = new CompositeRepository(RepositoryFactory::defaultRepos($io, $config));
3179 } else {
3180 $sourceRepo = RepositoryFactory::fromString($io, $config, $repository, true);
3181 }
3182
3183 $parser = new VersionParser();
3184 $requirements = $parser->parseNameVersionPairs(array($packageName));
3185 $name = strtolower($requirements[0]['name']);
3186 if (!$packageVersion && isset($requirements[0]['version'])) {
3187 $packageVersion = $requirements[0]['version'];
3188 }
3189
3190 if (null === $stability) {
3191 if (preg_match('{^[^,\s]*?@('.implode('|', array_keys(BasePackage::$stabilities)).')$}i', $packageVersion, $match)) {
3192 $stability = $match[1];
3193 } else {
3194 $stability = VersionParser::parseStability($packageVersion);
3195 }
3196 }
3197
3198 $stability = VersionParser::normalizeStability($stability);
3199
3200 if (!isset(BasePackage::$stabilities[$stability])) {
3201 throw new \InvalidArgumentException('Invalid stability provided ('.$stability.'), must be one of: '.implode(', ', array_keys(BasePackage::$stabilities)));
3202 }
3203
3204 $pool = new Pool($stability);
3205 $pool->addRepository($sourceRepo);
3206
3207 $phpVersion = null;
3208 $prettyPhpVersion = null;
3209 if (!$ignorePlatformReqs) {
3210 $platformOverrides = $config->get('platform') ?: array();
3211
3212  $platform = new PlatformRepository(array(), $platformOverrides);
3213 $phpPackage = $platform->findPackage('php', '*');
3214 $phpVersion = $phpPackage->getVersion();
3215 $prettyPhpVersion = $phpPackage->getPrettyVersion();
3216 }
3217
3218
3219  $versionSelector = new VersionSelector($pool);
3220 $package = $versionSelector->findBestCandidate($name, $packageVersion, $phpVersion, $stability);
3221
3222 if (!$package) {
3223 $errorMessage = "Could not find package $name with " . ($packageVersion ? "version $packageVersion" : "stability $stability");
3224 if ($phpVersion && $versionSelector->findBestCandidate($name, $packageVersion, null, $stability)) {
3225 throw new \InvalidArgumentException($errorMessage .' in a version installable using your PHP version '.$prettyPhpVersion.'.');
3226 }
3227
3228 throw new \InvalidArgumentException($errorMessage .'.');
3229 }
3230
3231 if (null === $directory) {
3232 $parts = explode("/", $name, 2);
3233 $directory = getcwd() . DIRECTORY_SEPARATOR . array_pop($parts);
3234 }
3235
3236
3237  if (function_exists('pcntl_signal')) {
3238 declare(ticks=100);
3239 pcntl_signal(SIGINT, function () use ($directory) {
3240 $fs = new Filesystem();
3241 $fs->removeDirectory($directory);
3242 exit(130);
3243 });
3244 }
3245
3246 $io->writeError('<info>Installing ' . $package->getName() . ' (' . $package->getFullPrettyVersion(false) . ')</info>');
3247
3248 if ($disablePlugins) {
3249 $io->writeError('<info>Plugins have been disabled.</info>');
3250 }
3251
3252 if ($package instanceof AliasPackage) {
3253 $package = $package->getAliasOf();
3254 }
3255
3256 if (0 === strpos($package->getPrettyVersion(), 'dev-') && in_array($package->getSourceType(), array('git', 'hg'))) {
3257 $package->setSourceReference(substr($package->getPrettyVersion(), 4));
3258 }
3259
3260 $dm = $this->createDownloadManager($io, $config);
3261 $dm->setPreferSource($preferSource)
3262 ->setPreferDist($preferDist)
3263 ->setOutputProgress(!$noProgress);
3264
3265 $projectInstaller = new ProjectInstaller($directory, $dm);
3266 $im = $this->createInstallationManager();
3267 $im->addInstaller($projectInstaller);
3268 $im->install(new InstalledFilesystemRepository(new JsonFile('php://memory')), new InstallOperation($package));
3269 $im->notifyInstalls($io);
3270
3271
3272  $this->suggestedPackagesReporter->addSuggestionsFromPackage($package);
3273
3274 $installedFromVcs = 'source' === $package->getInstallationSource();
3275
3276 $io->writeError('<info>Created project in ' . $directory . '</info>');
3277 chdir($directory);
3278
3279 $_SERVER['COMPOSER_ROOT_VERSION'] = $package->getPrettyVersion();
3280 putenv('COMPOSER_ROOT_VERSION='.$_SERVER['COMPOSER_ROOT_VERSION']);
3281
3282 return $installedFromVcs;
3283 }
3284
3285 protected function createDownloadManager(IOInterface $io, Config $config)
3286 {
3287 $factory = new Factory();
3288
3289 return $factory->createDownloadManager($io, $config);
3290 }
3291
3292 protected function createInstallationManager()
3293 {
3294 return new InstallationManager();
3295 }
3296 }
3297 <?php
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309 namespace Composer\Command;
3310
3311 use Symfony\Component\Console\Input\InputInterface;
3312 use Symfony\Component\Console\Output\OutputInterface;
3313
3314
3315
3316
3317 class DependsCommand extends BaseDependencyCommand
3318 {
3319
3320
3321
3322 protected function configure()
3323 {
3324 parent::configure();
3325
3326 $this
3327 ->setName('depends')
3328 ->setAliases(array('why'))
3329 ->setDescription('Shows which packages cause the given package to be installed.')
3330 ->setHelp(<<<EOT
3331 Displays detailed information about where a package is referenced.
3332
3333 <info>php composer.phar depends composer/composer</info>
3334
3335 EOT
3336 )
3337 ;
3338 }
3339
3340
3341
3342
3343
3344
3345
3346
3347 protected function execute(InputInterface $input, OutputInterface $output)
3348 {
3349 return parent::doExecute($input, $output, false);
3350 }
3351 }
3352 <?php
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364 namespace Composer\Command;
3365
3366 use Composer\Composer;
3367 use Composer\Factory;
3368 use Composer\Config;
3369 use Composer\Downloader\TransportException;
3370 use Composer\Plugin\CommandEvent;
3371 use Composer\Plugin\PluginEvents;
3372 use Composer\Util\ConfigValidator;
3373 use Composer\Util\IniHelper;
3374 use Composer\Util\ProcessExecutor;
3375 use Composer\Util\RemoteFilesystem;
3376 use Composer\Util\StreamContextFactory;
3377 use Composer\SelfUpdate\Keys;
3378 use Composer\SelfUpdate\Versions;
3379 use Composer\IO\NullIO;
3380 use Symfony\Component\Console\Input\InputInterface;
3381 use Symfony\Component\Console\Output\OutputInterface;
3382
3383
3384
3385
3386 class DiagnoseCommand extends BaseCommand
3387 {
3388
3389 protected $rfs;
3390
3391
3392 protected $process;
3393
3394
3395 protected $exitCode = 0;
3396
3397 protected function configure()
3398 {
3399 $this
3400 ->setName('diagnose')
3401 ->setDescription('Diagnoses the system to identify common errors.')
3402 ->setHelp(<<<EOT
3403 The <info>diagnose</info> command checks common errors to help debugging problems.
3404
3405 The process exit code will be 1 in case of warnings and 2 for errors.
3406
3407 EOT
3408 )
3409 ;
3410 }
3411
3412
3413
3414
3415 protected function execute(InputInterface $input, OutputInterface $output)
3416 {
3417 $composer = $this->getComposer(false);
3418 $io = $this->getIO();
3419
3420 if ($composer) {
3421 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'diagnose', $input, $output);
3422 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
3423
3424 $io->write('Checking composer.json: ', false);
3425 $this->outputResult($this->checkComposerSchema());
3426 }
3427
3428 if ($composer) {
3429 $config = $composer->getConfig();
3430 } else {
3431 $config = Factory::createConfig();
3432 }
3433
3434 $config->merge(array('config' => array('secure-http' => false)));
3435 $config->prohibitUrlByConfig('http://packagist.org', new NullIO);
3436
3437 $this->rfs = Factory::createRemoteFilesystem($io, $config);
3438 $this->process = new ProcessExecutor($io);
3439
3440 $io->write('Checking platform settings: ', false);
3441 $this->outputResult($this->checkPlatform());
3442
3443 $io->write('Checking git settings: ', false);
3444 $this->outputResult($this->checkGit());
3445
3446 $io->write('Checking http connectivity to packagist: ', false);
3447 $this->outputResult($this->checkHttp('http', $config));
3448
3449 $io->write('Checking https connectivity to packagist: ', false);
3450 $this->outputResult($this->checkHttp('https', $config));
3451
3452 $opts = stream_context_get_options(StreamContextFactory::getContext('http://example.org'));
3453 if (!empty($opts['http']['proxy'])) {
3454 $io->write('Checking HTTP proxy: ', false);
3455 $this->outputResult($this->checkHttpProxy());
3456 $io->write('Checking HTTP proxy support for request_fulluri: ', false);
3457 $this->outputResult($this->checkHttpProxyFullUriRequestParam());
3458 $io->write('Checking HTTPS proxy support for request_fulluri: ', false);
3459 $this->outputResult($this->checkHttpsProxyFullUriRequestParam());
3460 }
3461
3462 if ($oauth = $config->get('github-oauth')) {
3463 foreach ($oauth as $domain => $token) {
3464 $io->write('Checking '.$domain.' oauth access: ', false);
3465 $this->outputResult($this->checkGithubOauth($domain, $token));
3466 }
3467 } else {
3468 $io->write('Checking github.com rate limit: ', false);
3469 try {
3470 $rate = $this->getGithubRateLimit('github.com');
3471 $this->outputResult(true);
3472 if (10 > $rate['remaining']) {
3473 $io->write('<warning>WARNING</warning>');
3474 $io->write(sprintf(
3475 '<comment>Github has a rate limit on their API. '
3476 . 'You currently have <options=bold>%u</options=bold> '
3477 . 'out of <options=bold>%u</options=bold> requests left.' . PHP_EOL
3478 . 'See https://developer.github.com/v3/#rate-limiting and also' . PHP_EOL
3479 . '    https://getcomposer.org/doc/articles/troubleshooting.md#api-rate-limit-and-oauth-tokens</comment>',
3480 $rate['remaining'],
3481 $rate['limit']
3482 ));
3483 }
3484 } catch (\Exception $e) {
3485 if ($e instanceof TransportException && $e->getCode() === 401) {
3486 $this->outputResult('<comment>The oauth token for github.com seems invalid, run "composer config --global --unset github-oauth.github.com" to remove it</comment>');
3487 } else {
3488 $this->outputResult($e);
3489 }
3490 }
3491 }
3492
3493 $io->write('Checking disk free space: ', false);
3494 $this->outputResult($this->checkDiskSpace($config));
3495
3496 if ('phar:' === substr(__FILE__, 0, 5)) {
3497 $io->write('Checking pubkeys: ', false);
3498 $this->outputResult($this->checkPubKeys($config));
3499
3500 $io->write('Checking composer version: ', false);
3501 $this->outputResult($this->checkVersion($config));
3502 }
3503
3504 return $this->exitCode;
3505 }
3506
3507 private function checkComposerSchema()
3508 {
3509 $validator = new ConfigValidator($this->getIO());
3510 list($errors, , $warnings) = $validator->validate(Factory::getComposerFile());
3511
3512 if ($errors || $warnings) {
3513 $messages = array(
3514 'error' => $errors,
3515 'warning' => $warnings,
3516 );
3517
3518 $output = '';
3519 foreach ($messages as $style => $msgs) {
3520 foreach ($msgs as $msg) {
3521 $output .= '<' . $style . '>' . $msg . '</' . $style . '>' . PHP_EOL;
3522 }
3523 }
3524
3525 return rtrim($output);
3526 }
3527
3528 return true;
3529 }
3530
3531 private function checkGit()
3532 {
3533 $this->process->execute('git config color.ui', $output);
3534 if (strtolower(trim($output)) === 'always') {
3535 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>';
3536 }
3537
3538 return true;
3539 }
3540
3541 private function checkHttp($proto, Config $config)
3542 {
3543 $disableTls = false;
3544 $result = array();
3545 if ($proto === 'https' && $config->get('disable-tls') === true) {
3546 $disableTls = true;
3547 $result[] = '<warning>Composer is configured to disable SSL/TLS protection. This will leave remote HTTPS requests vulnerable to Man-In-The-Middle attacks.</warning>';
3548 }
3549 if ($proto === 'https' && !extension_loaded('openssl') && !$disableTls) {
3550 $result[] = '<error>Composer is configured to use SSL/TLS protection but the openssl extension is not available.</error>';
3551 }
3552
3553 try {
3554 $this->rfs->getContents('packagist.org', $proto . '://packagist.org/packages.json', false);
3555 } catch (TransportException $e) {
3556 if (false !== strpos($e->getMessage(), 'cafile')) {
3557 $result[] = '<error>[' . get_class($e) . '] ' . $e->getMessage() . '</error>';
3558 $result[] = '<error>Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.</error>';
3559 $result[] = '<error>You can alternatively disable this error, at your own risk, by enabling the \'disable-tls\' option.</error>';
3560 } else {
3561 array_unshift($result, '[' . get_class($e) . '] ' . $e->getMessage());
3562 }
3563 }
3564
3565 if (count($result) > 0) {
3566 return $result;
3567 }
3568
3569 return true;
3570 }
3571
3572 private function checkHttpProxy()
3573 {
3574 $protocol = extension_loaded('openssl') ? 'https' : 'http';
3575 try {
3576 $json = json_decode($this->rfs->getContents('packagist.org', $protocol . '://packagist.org/packages.json', false), true);
3577 $hash = reset($json['provider-includes']);
3578 $hash = $hash['sha256'];
3579 $path = str_replace('%hash%', $hash, key($json['provider-includes']));
3580 $provider = $this->rfs->getContents('packagist.org', $protocol . '://packagist.org/'.$path, false);
3581
3582 if (hash('sha256', $provider) !== $hash) {
3583 return 'It seems that your proxy is modifying http traffic on the fly';
3584 }
3585 } catch (\Exception $e) {
3586 return $e;
3587 }
3588
3589 return true;
3590 }
3591
3592
3593
3594
3595
3596
3597
3598
3599 private function checkHttpProxyFullUriRequestParam()
3600 {
3601 $url = 'http://packagist.org/packages.json';
3602 try {
3603 $this->rfs->getContents('packagist.org', $url, false);
3604 } catch (TransportException $e) {
3605 try {
3606 $this->rfs->getContents('packagist.org', $url, false, array('http' => array('request_fulluri' => false)));
3607 } catch (TransportException $e) {
3608 return 'Unable to assess the situation, maybe packagist.org is down ('.$e->getMessage().')';
3609 }
3610
3611 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"';
3612 }
3613
3614 return true;
3615 }
3616
3617
3618
3619
3620
3621
3622
3623
3624 private function checkHttpsProxyFullUriRequestParam()
3625 {
3626 if (!extension_loaded('openssl')) {
3627 return 'You need the openssl extension installed for this check';
3628 }
3629
3630 $url = 'https://api.github.com/repos/Seldaek/jsonlint/zipball/1.0.0';
3631 try {
3632 $this->rfs->getContents('github.com', $url, false);
3633 } catch (TransportException $e) {
3634 try {
3635 $this->rfs->getContents('github.com', $url, false, array('http' => array('request_fulluri' => false)));
3636 } catch (TransportException $e) {
3637 return 'Unable to assess the situation, maybe github is down ('.$e->getMessage().')';
3638 }
3639
3640 return 'It seems there is a problem with your proxy server, try setting the "HTTPS_PROXY_REQUEST_FULLURI" environment variable to "false"';
3641 }
3642
3643 return true;
3644 }
3645
3646 private function checkGithubOauth($domain, $token)
3647 {
3648 $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
3649 try {
3650 $url = $domain === 'github.com' ? 'https://api.'.$domain.'/' : 'https://'.$domain.'/api/v3/';
3651
3652 return $this->rfs->getContents($domain, $url, false, array(
3653 'retry-auth-failure' => false,
3654 )) ? true : 'Unexpected error';
3655 } catch (\Exception $e) {
3656 if ($e instanceof TransportException && $e->getCode() === 401) {
3657 return '<comment>The oauth token for '.$domain.' seems invalid, run "composer config --global --unset github-oauth.'.$domain.'" to remove it</comment>';
3658 }
3659
3660 return $e;
3661 }
3662 }
3663
3664
3665
3666
3667
3668
3669
3670 private function getGithubRateLimit($domain, $token = null)
3671 {
3672 if ($token) {
3673 $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
3674 }
3675
3676 $url = $domain === 'github.com' ? 'https://api.'.$domain.'/rate_limit' : 'https://'.$domain.'/api/rate_limit';
3677 $json = $this->rfs->getContents($domain, $url, false, array('retry-auth-failure' => false));
3678 $data = json_decode($json, true);
3679
3680 return $data['resources']['core'];
3681 }
3682
3683 private function checkDiskSpace($config)
3684 {
3685 $minSpaceFree = 1024 * 1024;
3686 if ((($df = @disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
3687 || (($df = @disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
3688 ) {
3689 return '<error>The disk hosting '.$dir.' is full</error>';
3690 }
3691
3692 return true;
3693 }
3694
3695 private function checkPubKeys($config)
3696 {
3697 $home = $config->get('home');
3698 $errors = array();
3699 $io = $this->getIO();
3700
3701 if (file_exists($home.'/keys.tags.pub') && file_exists($home.'/keys.dev.pub')) {
3702 $io->write('');
3703 }
3704
3705 if (file_exists($home.'/keys.tags.pub')) {
3706 $io->write('Tags Public Key Fingerprint: ' . Keys::fingerprint($home.'/keys.tags.pub'));
3707 } else {
3708 $errors[] = '<error>Missing pubkey for tags verification</error>';
3709 }
3710
3711 if (file_exists($home.'/keys.dev.pub')) {
3712 $io->write('Dev Public Key Fingerprint: ' . Keys::fingerprint($home.'/keys.dev.pub'));
3713 } else {
3714 $errors[] = '<error>Missing pubkey for dev verification</error>';
3715 }
3716
3717 if ($errors) {
3718 $errors[] = '<error>Run composer self-update --update-keys to set them up</error>';
3719 }
3720
3721 return $errors ?: true;
3722 }
3723
3724 private function checkVersion($config)
3725 {
3726 $versionsUtil = new Versions($config, $this->rfs);
3727 $latest = $versionsUtil->getLatest();
3728
3729 if (Composer::VERSION !== $latest['version'] && Composer::VERSION !== '@package_version@') {
3730 return '<comment>You are not running the latest '.$versionsUtil->getChannel().' version, run `composer self-update` to update ('.Composer::VERSION.' => '.$latest['version'].')</comment>';
3731 }
3732
3733 return true;
3734 }
3735
3736
3737
3738
3739 private function outputResult($result)
3740 {
3741 $io = $this->getIO();
3742 if (true === $result) {
3743 $io->write('<info>OK</info>');
3744
3745 return;
3746 }
3747
3748 $hadError = false;
3749 if ($result instanceof \Exception) {
3750 $result = '<error>['.get_class($result).'] '.$result->getMessage().'</error>';
3751 }
3752
3753 if (!$result) {
3754
3755  $hadError = true;
3756 } else {
3757 if (!is_array($result)) {
3758 $result = array($result);
3759 }
3760 foreach ($result as $message) {
3761 if (false !== strpos($message, '<error>')) {
3762 $hadError = true;
3763 }
3764 }
3765 }
3766
3767 if ($hadError) {
3768 $io->write('<error>FAIL</error>');
3769 $this->exitCode = 2;
3770 } else {
3771 $io->write('<warning>WARNING</warning>');
3772 $this->exitCode = 1;
3773 }
3774
3775 if ($result) {
3776 foreach ($result as $message) {
3777 $io->write($message);
3778 }
3779 }
3780 }
3781
3782 private function checkPlatform()
3783 {
3784 $output = '';
3785 $out = function ($msg, $style) use (&$output) {
3786 $output .= '<'.$style.'>'.$msg.'</'.$style.'>'.PHP_EOL;
3787 };
3788
3789
3790  $errors = array();
3791 $warnings = array();
3792 $displayIniMessage = false;
3793
3794 $iniMessage = PHP_EOL.PHP_EOL.IniHelper::getMessage();
3795 $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.';
3796
3797 if (!function_exists('json_decode')) {
3798 $errors['json'] = true;
3799 }
3800
3801 if (!extension_loaded('Phar')) {
3802 $errors['phar'] = true;
3803 }
3804
3805 if (!extension_loaded('filter')) {
3806 $errors['filter'] = true;
3807 }
3808
3809 if (!extension_loaded('hash')) {
3810 $errors['hash'] = true;
3811 }
3812
3813 if (!extension_loaded('iconv') && !extension_loaded('mbstring')) {
3814 $errors['iconv_mbstring'] = true;
3815 }
3816
3817 if (!ini_get('allow_url_fopen')) {
3818 $errors['allow_url_fopen'] = true;
3819 }
3820
3821 if (extension_loaded('ionCube Loader') && ioncube_loader_iversion() < 40009) {
3822 $errors['ioncube'] = ioncube_loader_version();
3823 }
3824
3825 if (PHP_VERSION_ID < 50302) {
3826 $errors['php'] = PHP_VERSION;
3827 }
3828
3829 if (!isset($errors['php']) && PHP_VERSION_ID < 50304) {
3830 $warnings['php'] = PHP_VERSION;
3831 }
3832
3833 if (!extension_loaded('openssl')) {
3834 $errors['openssl'] = true;
3835 }
3836
3837 if (extension_loaded('openssl') && OPENSSL_VERSION_NUMBER < 0x1000100f) {
3838 $warnings['openssl_version'] = true;
3839 }
3840
3841 if (!defined('HHVM_VERSION') && !extension_loaded('apcu') && ini_get('apc.enable_cli')) {
3842 $warnings['apc_cli'] = true;
3843 }
3844
3845 if (!extension_loaded('zlib')) {
3846 $warnings['zlib'] = true;
3847 }
3848
3849 ob_start();
3850 phpinfo(INFO_GENERAL);
3851 $phpinfo = ob_get_clean();
3852 if (preg_match('{Configure Command(?: *</td><td class="v">| *=> *)(.*?)(?:</td>|$)}m', $phpinfo, $match)) {
3853 $configure = $match[1];
3854
3855 if (false !== strpos($configure, '--enable-sigchild')) {
3856 $warnings['sigchild'] = true;
3857 }
3858
3859 if (false !== strpos($configure, '--with-curlwrappers')) {
3860 $warnings['curlwrappers'] = true;
3861 }
3862 }
3863
3864 if (ini_get('xdebug.profiler_enabled')) {
3865 $warnings['xdebug_profile'] = true;
3866 } elseif (extension_loaded('xdebug')) {
3867 $warnings['xdebug_loaded'] = true;
3868 }
3869
3870 if (!empty($errors)) {
3871 foreach ($errors as $error => $current) {
3872 switch ($error) {
3873 case 'json':
3874 $text = PHP_EOL."The json extension is missing.".PHP_EOL;
3875 $text .= "Install it or recompile php without --disable-json";
3876 break;
3877
3878 case 'phar':
3879 $text = PHP_EOL."The phar extension is missing.".PHP_EOL;
3880 $text .= "Install it or recompile php without --disable-phar";
3881 break;
3882
3883 case 'filter':
3884 $text = PHP_EOL."The filter extension is missing.".PHP_EOL;
3885 $text .= "Install it or recompile php without --disable-filter";
3886 break;
3887
3888 case 'hash':
3889 $text = PHP_EOL."The hash extension is missing.".PHP_EOL;
3890 $text .= "Install it or recompile php without --disable-hash";
3891 break;
3892
3893 case 'iconv_mbstring':
3894 $text = PHP_EOL."The iconv OR mbstring extension is required and both are missing.".PHP_EOL;
3895 $text .= "Install either of them or recompile php without --disable-iconv";
3896 break;
3897
3898 case 'unicode':
3899 $text = PHP_EOL."The detect_unicode setting must be disabled.".PHP_EOL;
3900 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
3901 $text .= "    detect_unicode = Off";
3902 $displayIniMessage = true;
3903 break;
3904
3905 case 'suhosin':
3906 $text = PHP_EOL."The suhosin.executor.include.whitelist setting is incorrect.".PHP_EOL;
3907 $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;
3908 $text .= "    suhosin.executor.include.whitelist = phar ".$current;
3909 $displayIniMessage = true;
3910 break;
3911
3912 case 'php':
3913 $text = PHP_EOL."Your PHP ({$current}) is too old, you must upgrade to PHP 5.3.2 or higher.";
3914 break;
3915
3916 case 'allow_url_fopen':
3917 $text = PHP_EOL."The allow_url_fopen setting is incorrect.".PHP_EOL;
3918 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
3919 $text .= "    allow_url_fopen = On";
3920 $displayIniMessage = true;
3921 break;
3922
3923 case 'ioncube':
3924 $text = PHP_EOL."Your ionCube Loader extension ($current) is incompatible with Phar files.".PHP_EOL;
3925 $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;
3926 $text .= "    zend_extension = /usr/lib/php5/20090626+lfs/ioncube_loader_lin_5.3.so";
3927 $displayIniMessage = true;
3928 break;
3929
3930 case 'openssl':
3931 $text = PHP_EOL."The openssl extension is missing, which means that secure HTTPS transfers are impossible.".PHP_EOL;
3932 $text .= "If possible you should enable it or recompile php with --with-openssl";
3933 break;
3934 }
3935 $out($text, 'error');
3936 }
3937
3938 $output .= PHP_EOL;
3939 }
3940
3941 if (!empty($warnings)) {
3942 foreach ($warnings as $warning => $current) {
3943 switch ($warning) {
3944 case 'apc_cli':
3945 $text = "The apc.enable_cli setting is incorrect.".PHP_EOL;
3946 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
3947 $text .= "  apc.enable_cli = Off";
3948 $displayIniMessage = true;
3949 break;
3950
3951 case 'zlib':
3952 $text = 'The zlib extension is not loaded, this can slow down Composer a lot.'.PHP_EOL;
3953 $text .= 'If possible, enable it or recompile php with --with-zlib'.PHP_EOL;
3954 $displayIniMessage = true;
3955 break;
3956
3957 case 'sigchild':
3958 $text = "PHP was compiled with --enable-sigchild which can cause issues on some platforms.".PHP_EOL;
3959 $text .= "Recompile it without this flag if possible, see also:".PHP_EOL;
3960 $text .= "  https://bugs.php.net/bug.php?id=22999";
3961 break;
3962
3963 case 'curlwrappers':
3964 $text = "PHP was compiled with --with-curlwrappers which will cause issues with HTTP authentication and GitHub.".PHP_EOL;
3965 $text .= " Recompile it without this flag if possible";
3966 break;
3967
3968 case 'php':
3969 $text = "Your PHP ({$current}) is quite old, upgrading to PHP 5.3.4 or higher is recommended.".PHP_EOL;
3970 $text .= " Composer works with 5.3.2+ for most people, but there might be edge case issues.";
3971 break;
3972
3973 case 'openssl_version':
3974
3975  $opensslVersion = strstr(trim(strstr(OPENSSL_VERSION_TEXT, ' ')), ' ', true);
3976 $opensslVersion = $opensslVersion ?: OPENSSL_VERSION_TEXT;
3977
3978 $text = "The OpenSSL library ({$opensslVersion}) used by PHP does not support TLSv1.2 or TLSv1.1.".PHP_EOL;
3979 $text .= "If possible you should upgrade OpenSSL to version 1.0.1 or above.";
3980 break;
3981
3982 case 'xdebug_loaded':
3983 $text = "The xdebug extension is loaded, this can slow down Composer a little.".PHP_EOL;
3984 $text .= " Disabling it when using Composer is recommended.";
3985 break;
3986
3987 case 'xdebug_profile':
3988 $text = "The xdebug.profiler_enabled setting is enabled, this can slow down Composer a lot.".PHP_EOL;
3989 $text .= "Add the following to the end of your `php.ini` to disable it:".PHP_EOL;
3990 $text .= "  xdebug.profiler_enabled = 0";
3991 $displayIniMessage = true;
3992 break;
3993 }
3994 $out($text, 'comment');
3995 }
3996 }
3997
3998 if ($displayIniMessage) {
3999 $out($iniMessage, 'comment');
4000 }
4001
4002 return !$warnings && !$errors ? true : $output;
4003 }
4004 }
4005 <?php
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017 namespace Composer\Command;
4018
4019 use Composer\Plugin\CommandEvent;
4020 use Composer\Plugin\PluginEvents;
4021 use Symfony\Component\Console\Input\InputInterface;
4022 use Symfony\Component\Console\Input\InputOption;
4023 use Symfony\Component\Console\Output\OutputInterface;
4024
4025
4026
4027
4028 class DumpAutoloadCommand extends BaseCommand
4029 {
4030 protected function configure()
4031 {
4032 $this
4033 ->setName('dump-autoload')
4034 ->setAliases(array('dumpautoload'))
4035 ->setDescription('Dumps the autoloader.')
4036 ->setDefinition(array(
4037 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
4038 new InputOption('optimize', 'o', InputOption::VALUE_NONE, 'Optimizes PSR0 and PSR4 packages to be loaded with classmaps too, good for production.'),
4039 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize`.'),
4040 new InputOption('apcu', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
4041 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables autoload-dev rules.'),
4042 ))
4043 ->setHelp(<<<EOT
4044 <info>php composer.phar dump-autoload</info>
4045 EOT
4046 )
4047 ;
4048 }
4049
4050 protected function execute(InputInterface $input, OutputInterface $output)
4051 {
4052 $composer = $this->getComposer();
4053
4054 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'dump-autoload', $input, $output);
4055 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
4056
4057 $installationManager = $composer->getInstallationManager();
4058 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
4059 $package = $composer->getPackage();
4060 $config = $composer->getConfig();
4061
4062 $optimize = $input->getOption('optimize') || $config->get('optimize-autoloader');
4063 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
4064 $apcu = $input->getOption('apcu') || $config->get('apcu-autoloader');
4065
4066 if ($optimize || $authoritative) {
4067 $this->getIO()->writeError('<info>Generating optimized autoload files</info>');
4068 } else {
4069 $this->getIO()->writeError('<info>Generating autoload files</info>');
4070 }
4071
4072 $generator = $composer->getAutoloadGenerator();
4073 $generator->setDevMode(!$input->getOption('no-dev'));
4074 $generator->setClassMapAuthoritative($authoritative);
4075 $generator->setApcu($apcu);
4076 $generator->setRunScripts(!$input->getOption('no-scripts'));
4077 $generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize);
4078 }
4079 }
4080 <?php
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092 namespace Composer\Command;
4093
4094 use Symfony\Component\Console\Input\InputInterface;
4095 use Symfony\Component\Console\Input\InputOption;
4096 use Symfony\Component\Console\Output\OutputInterface;
4097 use Symfony\Component\Console\Input\InputArgument;
4098
4099
4100
4101
4102 class ExecCommand extends BaseCommand
4103 {
4104 protected function configure()
4105 {
4106 $this
4107 ->setName('exec')
4108 ->setDescription('Executes a vendored binary/script.')
4109 ->setDefinition(array(
4110 new InputOption('list', 'l', InputOption::VALUE_NONE),
4111 new InputArgument('binary', InputArgument::OPTIONAL, 'The binary to run, e.g. phpunit'),
4112 new InputArgument(
4113 'args',
4114 InputArgument::IS_ARRAY | InputArgument::OPTIONAL,
4115 'Arguments to pass to the binary. Use <info>--</info> to separate from composer arguments'
4116 ),
4117 ))
4118 ;
4119 }
4120
4121 protected function execute(InputInterface $input, OutputInterface $output)
4122 {
4123 $composer = $this->getComposer();
4124 $binDir = $composer->getConfig()->get('bin-dir');
4125 if ($input->getOption('list') || !$input->getArgument('binary')) {
4126 $bins = glob($binDir . '/*');
4127 $bins = array_merge($bins, array_map(function ($e) {
4128 return "$e (local)";
4129 }, $composer->getPackage()->getBinaries()));
4130
4131 if (!$bins) {
4132 throw new \RuntimeException("No binaries found in composer.json or in bin-dir ($binDir)");
4133 }
4134
4135 $this->getIO()->write(<<<EOT
4136 <comment>Available binaries:</comment>
4137 EOT
4138 );
4139
4140 foreach ($bins as $bin) {
4141
4142  if (isset($previousBin) && $bin === $previousBin.'.bat') {
4143 continue;
4144 }
4145
4146 $previousBin = $bin;
4147 $bin = basename($bin);
4148 $this->getIO()->write(<<<EOT
4149 <info>- $bin</info>
4150 EOT
4151 );
4152 }
4153
4154 return 0;
4155 }
4156
4157 $binary = $input->getArgument('binary');
4158
4159 $dispatcher = $composer->getEventDispatcher();
4160 $dispatcher->addListener('__exec_command', $binary);
4161 if ($output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL) {
4162 $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
4163 }
4164
4165 return $dispatcher->dispatchScript('__exec_command', true, $input->getArgument('args'));
4166 }
4167 }
4168 <?php
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180 namespace Composer\Command;
4181
4182 use Composer\Factory;
4183 use Symfony\Component\Console\Input\InputInterface;
4184 use Symfony\Component\Console\Input\InputArgument;
4185 use Symfony\Component\Console\Input\StringInput;
4186 use Symfony\Component\Console\Output\OutputInterface;
4187
4188
4189
4190
4191 class GlobalCommand extends BaseCommand
4192 {
4193 protected function configure()
4194 {
4195 $this
4196 ->setName('global')
4197 ->setDescription('Allows running commands in the global composer dir ($COMPOSER_HOME).')
4198 ->setDefinition(array(
4199 new InputArgument('command-name', InputArgument::REQUIRED, ''),
4200 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
4201 ))
4202 ->setHelp(<<<EOT
4203 Use this command as a wrapper to run other Composer commands
4204 within the global context of COMPOSER_HOME.
4205
4206 You can use this to install CLI utilities globally, all you need
4207 is to add the COMPOSER_HOME/vendor/bin dir to your PATH env var.
4208
4209 COMPOSER_HOME is c:\Users\<user>\AppData\Roaming\Composer on Windows
4210 and /home/<user>/.composer on unix systems.
4211
4212 If your system uses freedesktop.org standards, then it will first check
4213 XDG_CONFIG_HOME or default to /home/<user>/.config/composer
4214
4215 Note: This path may vary depending on customizations to bin-dir in
4216 composer.json or the environmental variable COMPOSER_BIN_DIR.
4217
4218 EOT
4219 )
4220 ;
4221 }
4222
4223 public function run(InputInterface $input, OutputInterface $output)
4224 {
4225
4226  $tokens = preg_split('{\s+}', $input->__toString());
4227 $args = array();
4228 foreach ($tokens as $token) {
4229 if ($token && $token[0] !== '-') {
4230 $args[] = $token;
4231 if (count($args) >= 2) {
4232 break;
4233 }
4234 }
4235 }
4236
4237
4238  if (count($args) < 2) {
4239 return parent::run($input, $output);
4240 }
4241
4242
4243  $config = Factory::createConfig();
4244 chdir($config->get('home'));
4245 $this->getIO()->writeError('<info>Changed current directory to '.$config->get('home').'</info>');
4246
4247
4248  $input = new StringInput(preg_replace('{\bg(?:l(?:o(?:b(?:a(?:l)?)?)?)?)?\b}', '', $input->__toString(), 1));
4249 $this->getApplication()->resetComposer();
4250
4251 return $this->getApplication()->run($input, $output);
4252 }
4253
4254
4255
4256
4257 public function isProxyCommand()
4258 {
4259 return true;
4260 }
4261 }
4262 <?php
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274 namespace Composer\Command;
4275
4276 use Composer\Package\CompletePackageInterface;
4277 use Composer\Repository\RepositoryInterface;
4278 use Composer\Repository\ArrayRepository;
4279 use Composer\Repository\RepositoryFactory;
4280 use Composer\Util\Platform;
4281 use Composer\Util\ProcessExecutor;
4282 use Symfony\Component\Console\Input\InputArgument;
4283 use Symfony\Component\Console\Input\InputOption;
4284 use Symfony\Component\Console\Input\InputInterface;
4285 use Symfony\Component\Console\Output\OutputInterface;
4286
4287
4288
4289
4290 class HomeCommand extends BaseCommand
4291 {
4292
4293
4294
4295 protected function configure()
4296 {
4297 $this
4298 ->setName('browse')
4299 ->setAliases(array('home'))
4300 ->setDescription('Opens the package\'s repository URL or homepage in your browser.')
4301 ->setDefinition(array(
4302 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'Package(s) to browse to.'),
4303 new InputOption('homepage', 'H', InputOption::VALUE_NONE, 'Open the homepage instead of the repository URL.'),
4304 new InputOption('show', 's', InputOption::VALUE_NONE, 'Only show the homepage or repository URL.'),
4305 ))
4306 ->setHelp(<<<EOT
4307 The home command opens or shows a package's repository URL or
4308 homepage in your default browser.
4309
4310 To open the homepage by default, use -H or --homepage.
4311 To show instead of open the repository or homepage URL, use -s or --show.
4312 EOT
4313 );
4314 }
4315
4316
4317
4318
4319 protected function execute(InputInterface $input, OutputInterface $output)
4320 {
4321 $repos = $this->initializeRepos();
4322 $io = $this->getIO();
4323 $return = 0;
4324
4325 foreach ($input->getArgument('packages') as $packageName) {
4326 $handled = false;
4327 $packageExists = false;
4328 foreach ($repos as $repo) {
4329 foreach ($repo->findPackages($packageName) as $package) {
4330 $packageExists = true;
4331 if ($package instanceof CompletePackageInterface && $this->handlePackage($package, $input->getOption('homepage'), $input->getOption('show'))) {
4332 $handled = true;
4333 break 2;
4334 }
4335 }
4336 }
4337
4338 if (!$packageExists) {
4339 $return = 1;
4340 $io->writeError('<warning>Package '.$packageName.' not found</warning>');
4341 }
4342
4343 if (!$handled) {
4344 $return = 1;
4345 $io->writeError('<warning>'.($input->getOption('homepage') ? 'Invalid or missing homepage' : 'Invalid or missing repository URL').' for '.$packageName.'</warning>');
4346 }
4347 }
4348
4349 return $return;
4350 }
4351
4352 private function handlePackage(CompletePackageInterface $package, $showHomepage, $showOnly)
4353 {
4354 $support = $package->getSupport();
4355 $url = isset($support['source']) ? $support['source'] : $package->getSourceUrl();
4356 if (!$url || $showHomepage) {
4357 $url = $package->getHomepage();
4358 }
4359
4360 if (!$url || !filter_var($url, FILTER_VALIDATE_URL)) {
4361 return false;
4362 }
4363
4364 if ($showOnly) {
4365 $this->getIO()->write(sprintf('<info>%s</info>', $url));
4366 } else {
4367 $this->openBrowser($url);
4368 }
4369
4370 return true;
4371 }
4372
4373
4374
4375
4376
4377
4378 private function openBrowser($url)
4379 {
4380 $url = ProcessExecutor::escape($url);
4381
4382 $process = new ProcessExecutor($this->getIO());
4383 if (Platform::isWindows()) {
4384 return $process->execute('start "web" explorer "' . $url . '"', $output);
4385 }
4386
4387 $linux = $process->execute('which xdg-open', $output);
4388 $osx = $process->execute('which open', $output);
4389
4390 if (0 === $linux) {
4391 $process->execute('xdg-open ' . $url, $output);
4392 } elseif (0 === $osx) {
4393 $process->execute('open ' . $url, $output);
4394 } else {
4395 $this->getIO()->writeError('No suitable browser opening command found, open yourself: ' . $url);
4396 }
4397 }
4398
4399
4400
4401
4402
4403
4404
4405
4406 private function initializeRepos()
4407 {
4408 $composer = $this->getComposer(false);
4409
4410 if ($composer) {
4411 return array_merge(
4412 array(new ArrayRepository(array($composer->getPackage()))), 
4413  array($composer->getRepositoryManager()->getLocalRepository()), 
4414  $composer->getRepositoryManager()->getRepositories() 
4415  );
4416 }
4417
4418 return RepositoryFactory::defaultRepos($this->getIO());
4419 }
4420 }
4421 <?php
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433 namespace Composer\Command;
4434
4435 use Composer\DependencyResolver\Pool;
4436 use Composer\Json\JsonFile;
4437 use Composer\Factory;
4438 use Composer\Repository\RepositoryFactory;
4439 use Composer\Package\BasePackage;
4440 use Composer\Package\Version\VersionParser;
4441 use Composer\Package\Version\VersionSelector;
4442 use Composer\Repository\CompositeRepository;
4443 use Composer\Repository\PlatformRepository;
4444 use Composer\Util\ProcessExecutor;
4445 use Symfony\Component\Console\Input\InputInterface;
4446 use Symfony\Component\Console\Input\InputOption;
4447 use Symfony\Component\Console\Output\OutputInterface;
4448 use Symfony\Component\Process\Process;
4449 use Symfony\Component\Process\ExecutableFinder;
4450
4451
4452
4453
4454
4455 class InitCommand extends BaseCommand
4456 {
4457
4458 protected $repos;
4459
4460
4461 private $gitConfig;
4462
4463
4464 private $pool;
4465
4466
4467
4468
4469 protected function configure()
4470 {
4471 $this
4472 ->setName('init')
4473 ->setDescription('Creates a basic composer.json file in current directory.')
4474 ->setDefinition(array(
4475 new InputOption('name', null, InputOption::VALUE_REQUIRED, 'Name of the package'),
4476 new InputOption('description', null, InputOption::VALUE_REQUIRED, 'Description of package'),
4477 new InputOption('author', null, InputOption::VALUE_REQUIRED, 'Author name of package'),
4478
4479  new InputOption('type', null, InputOption::VALUE_OPTIONAL, 'Type of package (e.g. library, project, metapackage, composer-plugin)'),
4480 new InputOption('homepage', null, InputOption::VALUE_REQUIRED, 'Homepage of package'),
4481 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"'),
4482 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"'),
4483 new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum stability (empty or one of: '.implode(', ', array_keys(BasePackage::$stabilities)).')'),
4484 new InputOption('license', 'l', InputOption::VALUE_REQUIRED, 'License of package'),
4485 new InputOption('repository', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Add custom repositories, either by URL or using JSON arrays'),
4486 ))
4487 ->setHelp(<<<EOT
4488 The <info>init</info> command creates a basic composer.json file
4489 in the current directory.
4490
4491 <info>php composer.phar init</info>
4492
4493 EOT
4494 )
4495 ;
4496 }
4497
4498
4499
4500
4501 protected function execute(InputInterface $input, OutputInterface $output)
4502 {
4503 $io = $this->getIO();
4504
4505 $whitelist = array('name', 'description', 'author', 'type', 'homepage', 'require', 'require-dev', 'stability', 'license');
4506 $options = array_filter(array_intersect_key($input->getOptions(), array_flip($whitelist)));
4507
4508 if (isset($options['author'])) {
4509 $options['authors'] = $this->formatAuthors($options['author']);
4510 unset($options['author']);
4511 }
4512
4513 $repositories = $input->getOption('repository');
4514 if ($repositories) {
4515 $config = Factory::createConfig($io);
4516 foreach ($repositories as $repo) {
4517 $options['repositories'][] = RepositoryFactory::configFromString($io, $config, $repo);
4518 }
4519 }
4520
4521 if (isset($options['stability'])) {
4522 $options['minimum-stability'] = $options['stability'];
4523 unset($options['stability']);
4524 }
4525
4526 $options['require'] = isset($options['require']) ? $this->formatRequirements($options['require']) : new \stdClass;
4527 if (array() === $options['require']) {
4528 $options['require'] = new \stdClass;
4529 }
4530
4531 if (isset($options['require-dev'])) {
4532 $options['require-dev'] = $this->formatRequirements($options['require-dev']);
4533 if (array() === $options['require-dev']) {
4534 $options['require-dev'] = new \stdClass;
4535 }
4536 }
4537
4538 $file = new JsonFile(Factory::getComposerFile());
4539 $json = $file->encode($options);
4540
4541 if ($input->isInteractive()) {
4542 $io->writeError(array('', $json, ''));
4543 if (!$io->askConfirmation('Do you confirm generation [<comment>yes</comment>]? ', true)) {
4544 $io->writeError('<error>Command aborted</error>');
4545
4546 return 1;
4547 }
4548 }
4549
4550 $file->write($options);
4551
4552 if ($input->isInteractive() && is_dir('.git')) {
4553 $ignoreFile = realpath('.gitignore');
4554
4555 if (false === $ignoreFile) {
4556 $ignoreFile = realpath('.') . '/.gitignore';
4557 }
4558
4559 if (!$this->hasVendorIgnore($ignoreFile)) {
4560 $question = 'Would you like the <info>vendor</info> directory added to your <info>.gitignore</info> [<comment>yes</comment>]? ';
4561
4562 if ($io->askConfirmation($question, true)) {
4563 $this->addVendorIgnore($ignoreFile);
4564 }
4565 }
4566 }
4567 }
4568
4569
4570
4571
4572 protected function interact(InputInterface $input, OutputInterface $output)
4573 {
4574 $git = $this->getGitConfig();
4575 $io = $this->getIO();
4576 $formatter = $this->getHelperSet()->get('formatter');
4577
4578
4579  $repositories = $input->getOption('repository');
4580 if ($repositories) {
4581 $config = Factory::createConfig($io);
4582 $repos = array(new PlatformRepository);
4583 foreach ($repositories as $repo) {
4584 $repos[] = RepositoryFactory::fromString($io, $config, $repo);
4585 }
4586 $repos[] = RepositoryFactory::createRepo($io, $config, array(
4587 'type' => 'composer',
4588 'url' => 'https://packagist.org',
4589 ));
4590
4591 $this->repos = new CompositeRepository($repos);
4592 unset($repos, $config, $repositories);
4593 }
4594
4595 $io->writeError(array(
4596 '',
4597 $formatter->formatBlock('Welcome to the Composer config generator', 'bg=blue;fg=white', true),
4598 '',
4599 ));
4600
4601
4602  $io->writeError(array(
4603 '',
4604 'This command will guide you through creating your composer.json config.',
4605 '',
4606 ));
4607
4608 $cwd = realpath(".");
4609
4610 if (!$name = $input->getOption('name')) {
4611 $name = basename($cwd);
4612 $name = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $name);
4613 $name = strtolower($name);
4614 if (isset($git['github.user'])) {
4615 $name = $git['github.user'] . '/' . $name;
4616 } elseif (!empty($_SERVER['USERNAME'])) {
4617 $name = $_SERVER['USERNAME'] . '/' . $name;
4618 } elseif (!empty($_SERVER['USER'])) {
4619 $name = $_SERVER['USER'] . '/' . $name;
4620 } elseif (get_current_user()) {
4621 $name = get_current_user() . '/' . $name;
4622 } else {
4623
4624  $name = $name . '/' . $name;
4625 }
4626 $name = strtolower($name);
4627 } else {
4628 if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}', $name)) {
4629 throw new \InvalidArgumentException(
4630 '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_.-]+'
4631 );
4632 }
4633 }
4634
4635 $name = $io->askAndValidate(
4636 'Package name (<vendor>/<name>) [<comment>'.$name.'</comment>]: ',
4637 function ($value) use ($name) {
4638 if (null === $value) {
4639 return $name;
4640 }
4641
4642 if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}', $value)) {
4643 throw new \InvalidArgumentException(
4644 '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_.-]+'
4645 );
4646 }
4647
4648 return $value;
4649 },
4650 null,
4651 $name
4652 );
4653 $input->setOption('name', $name);
4654
4655 $description = $input->getOption('description') ?: false;
4656 $description = $io->ask(
4657 'Description [<comment>'.$description.'</comment>]: ',
4658 $description
4659 );
4660 $input->setOption('description', $description);
4661
4662 if (null === $author = $input->getOption('author')) {
4663 if (isset($git['user.name']) && isset($git['user.email'])) {
4664 $author = sprintf('%s <%s>', $git['user.name'], $git['user.email']);
4665 }
4666 }
4667
4668 $self = $this;
4669 $author = $io->askAndValidate(
4670 'Author [<comment>'.$author.'</comment>, n to skip]: ',
4671 function ($value) use ($self, $author) {
4672 if ($value === 'n' || $value === 'no') {
4673 return;
4674 }
4675 $value = $value ?: $author;
4676 $author = $self->parseAuthorString($value);
4677
4678 return sprintf('%s <%s>', $author['name'], $author['email']);
4679 },
4680 null,
4681 $author
4682 );
4683 $input->setOption('author', $author);
4684
4685 $minimumStability = $input->getOption('stability') ?: null;
4686 $minimumStability = $io->askAndValidate(
4687 'Minimum Stability [<comment>'.$minimumStability.'</comment>]: ',
4688 function ($value) use ($self, $minimumStability) {
4689 if (null === $value) {
4690 return $minimumStability;
4691 }
4692
4693 if (!isset(BasePackage::$stabilities[$value])) {
4694 throw new \InvalidArgumentException(
4695 'Invalid minimum stability "'.$value.'". Must be empty or one of: '.
4696 implode(', ', array_keys(BasePackage::$stabilities))
4697 );
4698 }
4699
4700 return $value;
4701 },
4702 null,
4703 $minimumStability
4704 );
4705 $input->setOption('stability', $minimumStability);
4706
4707 $type = $input->getOption('type') ?: false;
4708 $type = $io->ask(
4709 'Package Type (e.g. library, project, metapackage, composer-plugin) [<comment>'.$type.'</comment>]: ',
4710 $type
4711 );
4712 $input->setOption('type', $type);
4713
4714 $license = $input->getOption('license') ?: false;
4715 $license = $io->ask(
4716 'License [<comment>'.$license.'</comment>]: ',
4717 $license
4718 );
4719 $input->setOption('license', $license);
4720
4721 $io->writeError(array('', 'Define your dependencies.', ''));
4722
4723 $question = 'Would you like to define your dependencies (require) interactively [<comment>yes</comment>]? ';
4724 $require = $input->getOption('require');
4725 $requirements = array();
4726 if ($require || $io->askConfirmation($question, true)) {
4727 $requirements = $this->determineRequirements($input, $output, $require);
4728 }
4729 $input->setOption('require', $requirements);
4730
4731 $question = 'Would you like to define your dev dependencies (require-dev) interactively [<comment>yes</comment>]? ';
4732 $requireDev = $input->getOption('require-dev');
4733 $devRequirements = array();
4734 if ($requireDev || $io->askConfirmation($question, true)) {
4735 $devRequirements = $this->determineRequirements($input, $output, $requireDev);
4736 }
4737 $input->setOption('require-dev', $devRequirements);
4738 }
4739
4740
4741
4742
4743
4744
4745 public function parseAuthorString($author)
4746 {
4747 if (preg_match('/^(?P<name>[- .,\p{L}\p{N}\p{Mn}\'’"()]+) <(?P<email>.+?)>$/u', $author, $match)) {
4748 if ($this->isValidEmail($match['email'])) {
4749 return array(
4750 'name' => trim($match['name']),
4751 'email' => $match['email'],
4752 );
4753 }
4754 }
4755
4756 throw new \InvalidArgumentException(
4757 'Invalid author string.  Must be in the format: '.
4758 'John Smith <john@example.com>'
4759 );
4760 }
4761
4762 protected function findPackages($name)
4763 {
4764 return $this->getRepos()->search($name);
4765 }
4766
4767 protected function getRepos()
4768 {
4769 if (!$this->repos) {
4770 $this->repos = new CompositeRepository(array_merge(
4771 array(new PlatformRepository),
4772 RepositoryFactory::defaultRepos($this->getIO())
4773 ));
4774 }
4775
4776 return $this->repos;
4777 }
4778
4779 protected function determineRequirements(InputInterface $input, OutputInterface $output, $requires = array(), $phpVersion = null, $preferredStability = 'stable')
4780 {
4781 if ($requires) {
4782 $requires = $this->normalizeRequirements($requires);
4783 $result = array();
4784 $io = $this->getIO();
4785
4786 foreach ($requires as $requirement) {
4787 if (!isset($requirement['version'])) {
4788
4789  $version = $this->findBestVersionForPackage($input, $requirement['name'], $phpVersion, $preferredStability);
4790 $requirement['version'] = $version;
4791
4792 $io->writeError(sprintf(
4793 'Using version <info>%s</info> for <info>%s</info>',
4794 $requirement['version'],
4795 $requirement['name']
4796 ));
4797 } else {
4798
4799  $this->findBestVersionForPackage($input, $requirement['name'], $phpVersion, $preferredStability, $requirement['version'], 'dev');
4800 }
4801
4802 $result[] = $requirement['name'] . ' ' . $requirement['version'];
4803 }
4804
4805 return $result;
4806 }
4807
4808 $versionParser = new VersionParser();
4809 $io = $this->getIO();
4810 while (null !== $package = $io->ask('Search for a package: ')) {
4811 $matches = $this->findPackages($package);
4812
4813 if (count($matches)) {
4814 $exactMatch = null;
4815 $choices = array();
4816 foreach ($matches as $position => $foundPackage) {
4817 $choices[] = sprintf(' <info>%5s</info> %s', "[$position]", $foundPackage['name']);
4818 if ($foundPackage['name'] === $package) {
4819 $exactMatch = true;
4820 break;
4821 }
4822 }
4823
4824
4825  if (!$exactMatch) {
4826 $io->writeError(array(
4827 '',
4828 sprintf('Found <info>%s</info> packages matching <info>%s</info>', count($matches), $package),
4829 '',
4830 ));
4831
4832 $io->writeError($choices);
4833 $io->writeError('');
4834
4835 $validator = function ($selection) use ($matches, $versionParser) {
4836 if ('' === $selection) {
4837 return false;
4838 }
4839
4840 if (is_numeric($selection) && isset($matches[(int) $selection])) {
4841 $package = $matches[(int) $selection];
4842
4843 return $package['name'];
4844 }
4845
4846 if (preg_match('{^\s*(?P<name>[\S/]+)(?:\s+(?P<version>\S+))?\s*$}', $selection, $packageMatches)) {
4847 if (isset($packageMatches['version'])) {
4848
4849
4850
4851  $versionParser->parseConstraints($packageMatches['version']);
4852
4853 return $packageMatches['name'].' '.$packageMatches['version'];
4854 }
4855
4856
4857  return $packageMatches['name'];
4858 }
4859
4860 throw new \Exception('Not a valid selection');
4861 };
4862
4863 $package = $io->askAndValidate(
4864 'Enter package # to add, or the complete package name if it is not listed: ',
4865 $validator,
4866 3,
4867 false
4868 );
4869 }
4870
4871
4872  if (false !== $package && false === strpos($package, ' ')) {
4873 $validator = function ($input) {
4874 $input = trim($input);
4875
4876 return $input ?: false;
4877 };
4878
4879 $constraint = $io->askAndValidate(
4880 'Enter the version constraint to require (or leave blank to use the latest version): ',
4881 $validator,
4882 3,
4883 false
4884 );
4885
4886 if (false === $constraint) {
4887 $constraint = $this->findBestVersionForPackage($input, $package, $phpVersion, $preferredStability);
4888
4889 $io->writeError(sprintf(
4890 'Using version <info>%s</info> for <info>%s</info>',
4891 $constraint,
4892 $package
4893 ));
4894 }
4895
4896 $package .= ' '.$constraint;
4897 }
4898
4899 if (false !== $package) {
4900 $requires[] = $package;
4901 }
4902 }
4903 }
4904
4905 return $requires;
4906 }
4907
4908 protected function formatAuthors($author)
4909 {
4910 return array($this->parseAuthorString($author));
4911 }
4912
4913 protected function formatRequirements(array $requirements)
4914 {
4915 $requires = array();
4916 $requirements = $this->normalizeRequirements($requirements);
4917 foreach ($requirements as $requirement) {
4918 $requires[$requirement['name']] = $requirement['version'];
4919 }
4920
4921 return $requires;
4922 }
4923
4924 protected function getGitConfig()
4925 {
4926 if (null !== $this->gitConfig) {
4927 return $this->gitConfig;
4928 }
4929
4930 $finder = new ExecutableFinder();
4931 $gitBin = $finder->find('git');
4932
4933 $cmd = new Process(sprintf('%s config -l', ProcessExecutor::escape($gitBin)));
4934 $cmd->run();
4935
4936 if ($cmd->isSuccessful()) {
4937 $this->gitConfig = array();
4938 preg_match_all('{^([^=]+)=(.*)$}m', $cmd->getOutput(), $matches, PREG_SET_ORDER);
4939 foreach ($matches as $match) {
4940 $this->gitConfig[$match[1]] = $match[2];
4941 }
4942
4943 return $this->gitConfig;
4944 }
4945
4946 return $this->gitConfig = array();
4947 }
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960
4961
4962
4963
4964
4965 protected function hasVendorIgnore($ignoreFile, $vendor = 'vendor')
4966 {
4967 if (!file_exists($ignoreFile)) {
4968 return false;
4969 }
4970
4971 $pattern = sprintf('{^/?%s(/\*?)?$}', preg_quote($vendor));
4972
4973 $lines = file($ignoreFile, FILE_IGNORE_NEW_LINES);
4974 foreach ($lines as $line) {
4975 if (preg_match($pattern, $line)) {
4976 return true;
4977 }
4978 }
4979
4980 return false;
4981 }
4982
4983 protected function normalizeRequirements(array $requirements)
4984 {
4985 $parser = new VersionParser();
4986
4987 return $parser->parseNameVersionPairs($requirements);
4988 }
4989
4990 protected function addVendorIgnore($ignoreFile, $vendor = '/vendor/')
4991 {
4992 $contents = "";
4993 if (file_exists($ignoreFile)) {
4994 $contents = file_get_contents($ignoreFile);
4995
4996 if ("\n" !== substr($contents, 0, -1)) {
4997 $contents .= "\n";
4998 }
4999 }
5000
5001 file_put_contents($ignoreFile, $contents . $vendor. "\n");
5002 }
5003
5004 protected function isValidEmail($email)
5005 {
5006
5007  if (!function_exists('filter_var')) {
5008 return true;
5009 }
5010
5011
5012  if (PHP_VERSION_ID < 50303) {
5013 return true;
5014 }
5015
5016 return false !== filter_var($email, FILTER_VALIDATE_EMAIL);
5017 }
5018
5019 private function getPool(InputInterface $input, $minimumStability = null)
5020 {
5021 if (!$this->pool) {
5022 $this->pool = new Pool($minimumStability ?: $this->getMinimumStability($input));
5023 $this->pool->addRepository($this->getRepos());
5024 }
5025
5026 return $this->pool;
5027 }
5028
5029 private function getMinimumStability(InputInterface $input)
5030 {
5031 if ($input->hasOption('stability')) {
5032 return $input->getOption('stability') ?: 'stable';
5033 }
5034
5035 $file = Factory::getComposerFile();
5036 if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
5037 if (!empty($composer['minimum-stability'])) {
5038 return $composer['minimum-stability'];
5039 }
5040 }
5041
5042 return 'stable';
5043 }
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
5054
5055
5056
5057
5058 private function findBestVersionForPackage(InputInterface $input, $name, $phpVersion, $preferredStability = 'stable', $requiredVersion = null, $minimumStability = null)
5059 {
5060
5061  $versionSelector = new VersionSelector($this->getPool($input, $minimumStability));
5062 $package = $versionSelector->findBestCandidate($name, $requiredVersion, $phpVersion, $preferredStability);
5063
5064 if (!$package) {
5065 if ($requiredVersion && $versionSelector->findBestCandidate($name, null, $phpVersion, $preferredStability)) {
5066
5067  if ($phpVersion && $versionSelector->findBestCandidate($name, null, null, $preferredStability)) {
5068 throw new \InvalidArgumentException(sprintf(
5069 'Package %s at version %s has a PHP requirement incompatible with your PHP version (%s)', $name, $requiredVersion, $phpVersion
5070 ));
5071 }
5072 throw new \InvalidArgumentException(sprintf(
5073 'Could not find package %s in a version matching %s', $name, $requiredVersion
5074 ));
5075 }
5076
5077  if ($phpVersion && $versionSelector->findBestCandidate($name)) {
5078 throw new \InvalidArgumentException(sprintf(
5079 'Could not find package %s in any version matching your PHP version (%s)', $name, $phpVersion
5080 ));
5081 }
5082 throw new \InvalidArgumentException(sprintf(
5083 'Could not find a matching version of package %s. Check the package spelling, your version constraint and that the package is available in a stability which matches your minimum-stability (%s).',
5084 $name,
5085 $this->getMinimumStability($input)
5086 ));
5087 }
5088
5089 return $versionSelector->findRecommendedRequireVersion($package);
5090 }
5091 }
5092 <?php
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104 namespace Composer\Command;
5105
5106 use Composer\Installer;
5107 use Composer\Plugin\CommandEvent;
5108 use Composer\Plugin\PluginEvents;
5109 use Symfony\Component\Console\Input\InputInterface;
5110 use Symfony\Component\Console\Input\InputOption;
5111 use Symfony\Component\Console\Input\InputArgument;
5112 use Symfony\Component\Console\Output\OutputInterface;
5113
5114
5115
5116
5117
5118
5119
5120 class InstallCommand extends BaseCommand
5121 {
5122 protected function configure()
5123 {
5124 $this
5125 ->setName('install')
5126 ->setDescription('Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json.')
5127 ->setDefinition(array(
5128 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
5129 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
5130 new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
5131 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
5132 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
5133 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
5134 new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
5135 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
5136 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
5137 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
5138 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
5139 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
5140 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
5141 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
5142 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
5143 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Should not be provided, use composer require instead to add a given package to composer.json.'),
5144 ))
5145 ->setHelp(<<<EOT
5146 The <info>install</info> command reads the composer.lock file from
5147 the current directory, processes it, and downloads and installs all the
5148 libraries and dependencies outlined in that file. If the file does not
5149 exist it will look for composer.json and do the same.
5150
5151 <info>php composer.phar install</info>
5152
5153 EOT
5154 )
5155 ;
5156 }
5157
5158 protected function execute(InputInterface $input, OutputInterface $output)
5159 {
5160 $io = $this->getIO();
5161 if ($args = $input->getArgument('packages')) {
5162 $io->writeError('<error>Invalid argument '.implode(' ', $args).'. Use "composer require '.implode(' ', $args).'" instead to add packages to your composer.json.</error>');
5163
5164 return 1;
5165 }
5166
5167 if ($input->getOption('no-custom-installers')) {
5168 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
5169 $input->setOption('no-plugins', true);
5170 }
5171
5172 if ($input->getOption('dev')) {
5173 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
5174 }
5175
5176 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
5177 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
5178
5179 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'install', $input, $output);
5180 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5181
5182 $install = Installer::create($io, $composer);
5183
5184 $config = $composer->getConfig();
5185 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
5186
5187 $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
5188 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
5189 $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
5190
5191 $install
5192 ->setDryRun($input->getOption('dry-run'))
5193 ->setVerbose($input->getOption('verbose'))
5194 ->setPreferSource($preferSource)
5195 ->setPreferDist($preferDist)
5196 ->setDevMode(!$input->getOption('no-dev'))
5197 ->setDumpAutoloader(!$input->getOption('no-autoloader'))
5198 ->setRunScripts(!$input->getOption('no-scripts'))
5199 ->setSkipSuggest($input->getOption('no-suggest'))
5200 ->setOptimizeAutoloader($optimize)
5201 ->setClassMapAuthoritative($authoritative)
5202 ->setApcuAutoloader($apcu)
5203 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
5204 ;
5205
5206 if ($input->getOption('no-plugins')) {
5207 $install->disablePlugins();
5208 }
5209
5210 return $install->run();
5211 }
5212 }
5213 <?php
5214
5215
5216
5217
5218
5219
5220
5221
5222
5223
5224
5225 namespace Composer\Command;
5226
5227 use Composer\Json\JsonFile;
5228 use Composer\Plugin\CommandEvent;
5229 use Composer\Plugin\PluginEvents;
5230 use Composer\Package\PackageInterface;
5231 use Composer\Repository\RepositoryInterface;
5232 use Symfony\Component\Console\Helper\Table;
5233 use Symfony\Component\Console\Input\InputInterface;
5234 use Symfony\Component\Console\Input\InputOption;
5235 use Symfony\Component\Console\Output\OutputInterface;
5236
5237
5238
5239
5240 class LicensesCommand extends BaseCommand
5241 {
5242 protected function configure()
5243 {
5244 $this
5245 ->setName('licenses')
5246 ->setDescription('Shows information about licenses of dependencies.')
5247 ->setDefinition(array(
5248 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
5249 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'),
5250 ))
5251 ->setHelp(<<<EOT
5252 The license command displays detailed information about the licenses of
5253 the installed dependencies.
5254
5255 EOT
5256 )
5257 ;
5258 }
5259
5260 protected function execute(InputInterface $input, OutputInterface $output)
5261 {
5262 $composer = $this->getComposer();
5263
5264 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'licenses', $input, $output);
5265 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5266
5267 $root = $composer->getPackage();
5268 $repo = $composer->getRepositoryManager()->getLocalRepository();
5269
5270 if ($input->getOption('no-dev')) {
5271 $packages = $this->filterRequiredPackages($repo, $root);
5272 } else {
5273 $packages = $this->appendPackages($repo->getPackages(), array());
5274 }
5275
5276 ksort($packages);
5277 $io = $this->getIO();
5278
5279 switch ($format = $input->getOption('format')) {
5280 case 'text':
5281 $io->write('Name: <comment>'.$root->getPrettyName().'</comment>');
5282 $io->write('Version: <comment>'.$root->getFullPrettyVersion().'</comment>');
5283 $io->write('Licenses: <comment>'.(implode(', ', $root->getLicense()) ?: 'none').'</comment>');
5284 $io->write('Dependencies:');
5285 $io->write('');
5286
5287 $table = new Table($output);
5288 $table->setStyle('compact');
5289 $table->getStyle()->setVerticalBorderChar('');
5290 $table->getStyle()->setCellRowContentFormat('%s  ');
5291 $table->setHeaders(array('Name', 'Version', 'License'));
5292 foreach ($packages as $package) {
5293 $table->addRow(array(
5294 $package->getPrettyName(),
5295 $package->getFullPrettyVersion(),
5296 implode(', ', $package->getLicense()) ?: 'none',
5297 ));
5298 }
5299 $table->render();
5300 break;
5301
5302 case 'json':
5303 $dependencies = array();
5304 foreach ($packages as $package) {
5305 $dependencies[$package->getPrettyName()] = array(
5306 'version' => $package->getFullPrettyVersion(),
5307 'license' => $package->getLicense(),
5308 );
5309 }
5310
5311 $io->write(JsonFile::encode(array(
5312 'name' => $root->getPrettyName(),
5313 'version' => $root->getFullPrettyVersion(),
5314 'license' => $root->getLicense(),
5315 'dependencies' => $dependencies,
5316 )));
5317 break;
5318
5319 default:
5320 throw new \RuntimeException(sprintf('Unsupported format "%s".  See help for supported formats.', $format));
5321 }
5322 }
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332 private function filterRequiredPackages(RepositoryInterface $repo, PackageInterface $package, $bucket = array())
5333 {
5334 $requires = array_keys($package->getRequires());
5335
5336 $packageListNames = array_keys($bucket);
5337 $packages = array_filter(
5338 $repo->getPackages(),
5339 function ($package) use ($requires, $packageListNames) {
5340 return in_array($package->getName(), $requires) && !in_array($package->getName(), $packageListNames);
5341 }
5342 );
5343
5344 $bucket = $this->appendPackages($packages, $bucket);
5345
5346 foreach ($packages as $package) {
5347 $bucket = $this->filterRequiredPackages($repo, $package, $bucket);
5348 }
5349
5350 return $bucket;
5351 }
5352
5353
5354
5355
5356
5357
5358
5359
5360 public function appendPackages(array $packages, array $bucket)
5361 {
5362 foreach ($packages as $package) {
5363 $bucket[$package->getName()] = $package;
5364 }
5365
5366 return $bucket;
5367 }
5368 }
5369 <?php
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381 namespace Composer\Command;
5382
5383 use Symfony\Component\Console\Input\InputInterface;
5384 use Symfony\Component\Console\Input\InputArgument;
5385 use Symfony\Component\Console\Input\ArrayInput;
5386 use Symfony\Component\Console\Input\InputOption;
5387 use Symfony\Component\Console\Output\OutputInterface;
5388
5389
5390
5391
5392 class OutdatedCommand extends ShowCommand
5393 {
5394 protected function configure()
5395 {
5396 $this
5397 ->setName('outdated')
5398 ->setDescription('Shows a list of installed packages that have updates available, including their latest version.')
5399 ->setDefinition(array(
5400 new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
5401 new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show only packages that are outdated (this is the default, but present here for compat with `show`'),
5402 new InputOption('all', 'a', InputOption::VALUE_NONE, 'Show all installed packages with their latest versions'),
5403 new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
5404 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
5405 new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
5406 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
5407 ))
5408 ->setHelp(<<<EOT
5409 The outdated command is just a proxy for `composer show -l`
5410
5411 The color coding (or signage if you have ANSI colors disabled) for dependency versions is as such:
5412
5413 - <info>green</info> (=): Dependency is in the latest version and is up to date.
5414 - <comment>yellow</comment> (~): Dependency has a new version available that includes backwards
5415   compatibility breaks according to semver, so upgrade when you can but it
5416   may involve work.
5417 - <highlight>red</highlight> (!): Dependency has a new version that is semver-compatible and you should upgrade it.
5418
5419
5420 EOT
5421 )
5422 ;
5423 }
5424
5425 protected function execute(InputInterface $input, OutputInterface $output)
5426 {
5427 $args = array(
5428 'show',
5429 '--latest' => true,
5430 );
5431 if (!$input->getOption('all')) {
5432 $args['--outdated'] = true;
5433 }
5434 if ($input->getOption('direct')) {
5435 $args['--direct'] = true;
5436 }
5437 if ($input->getArgument('package')) {
5438 $args['package'] = $input->getArgument('package');
5439 }
5440 if ($input->getOption('strict')) {
5441 $args['--strict'] = true;
5442 }
5443 if ($input->getOption('minor-only')) {
5444 $args['--minor-only'] = true;
5445 }
5446 $args['--format'] = $input->getOption('format');
5447
5448 $input = new ArrayInput($args);
5449
5450 return $this->getApplication()->run($input, $output);
5451 }
5452
5453
5454
5455
5456 public function isProxyCommand()
5457 {
5458 return true;
5459 }
5460 }
5461 <?php
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473 namespace Composer\Command;
5474
5475 use Symfony\Component\Console\Input\InputInterface;
5476 use Symfony\Component\Console\Output\OutputInterface;
5477
5478
5479
5480
5481 class ProhibitsCommand extends BaseDependencyCommand
5482 {
5483
5484
5485
5486 protected function configure()
5487 {
5488 parent::configure();
5489
5490 $this
5491 ->setName('prohibits')
5492 ->setAliases(array('why-not'))
5493 ->setDescription('Shows which packages prevent the given package from being installed.')
5494 ->setHelp(<<<EOT
5495 Displays detailed information about why a package cannot be installed.
5496
5497 <info>php composer.phar prohibits composer/composer</info>
5498
5499 EOT
5500 )
5501 ;
5502 }
5503
5504
5505
5506
5507
5508
5509
5510
5511 protected function execute(InputInterface $input, OutputInterface $output)
5512 {
5513 return parent::doExecute($input, $output, true);
5514 }
5515 }
5516 <?php
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528 namespace Composer\Command;
5529
5530 use Composer\Config\JsonConfigSource;
5531 use Composer\Installer;
5532 use Composer\Plugin\CommandEvent;
5533 use Composer\Plugin\PluginEvents;
5534 use Composer\Json\JsonFile;
5535 use Composer\Factory;
5536 use Symfony\Component\Console\Input\InputInterface;
5537 use Symfony\Component\Console\Input\InputOption;
5538 use Symfony\Component\Console\Input\InputArgument;
5539 use Symfony\Component\Console\Output\OutputInterface;
5540
5541
5542
5543
5544
5545 class RemoveCommand extends BaseCommand
5546 {
5547 protected function configure()
5548 {
5549 $this
5550 ->setName('remove')
5551 ->setDescription('Removes a package from the require or require-dev.')
5552 ->setDefinition(array(
5553 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'Packages that should be removed.'),
5554 new InputOption('dev', null, InputOption::VALUE_NONE, 'Removes a package from the require-dev section.'),
5555 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
5556 new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
5557 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
5558 new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
5559 new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies. (Deprecrated, is now default behavior)'),
5560 new InputOption('no-update-with-dependencies', null, InputOption::VALUE_NONE, 'Does not allow inherited dependencies to be updated with explicit dependencies.'),
5561 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
5562 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
5563 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
5564 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
5565 ))
5566 ->setHelp(<<<EOT
5567 The <info>remove</info> command removes a package from the current
5568 list of installed packages
5569
5570 <info>php composer.phar remove</info>
5571
5572 EOT
5573 )
5574 ;
5575 }
5576
5577 protected function execute(InputInterface $input, OutputInterface $output)
5578 {
5579 $packages = $input->getArgument('packages');
5580 $packages = array_map('strtolower', $packages);
5581
5582 $file = Factory::getComposerFile();
5583
5584 $jsonFile = new JsonFile($file);
5585 $composer = $jsonFile->read();
5586 $composerBackup = file_get_contents($jsonFile->getPath());
5587
5588 $json = new JsonConfigSource($jsonFile);
5589
5590 $type = $input->getOption('dev') ? 'require-dev' : 'require';
5591 $altType = !$input->getOption('dev') ? 'require-dev' : 'require';
5592 $io = $this->getIO();
5593
5594 if ($input->getOption('update-with-dependencies')) {
5595 $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>');
5596 }
5597
5598
5599  foreach (array('require', 'require-dev') as $linkType) {
5600 if (isset($composer[$linkType])) {
5601 foreach ($composer[$linkType] as $name => $version) {
5602 $composer[$linkType][strtolower($name)] = $name;
5603 }
5604 }
5605 }
5606
5607 foreach ($packages as $package) {
5608 if (isset($composer[$type][$package])) {
5609 $json->removeLink($type, $composer[$type][$package]);
5610 } elseif (isset($composer[$altType][$package])) {
5611 $io->writeError('<warning>'.$composer[$altType][$package].' could not be found in '.$type.' but it is present in '.$altType.'</warning>');
5612 if ($io->isInteractive()) {
5613 if ($io->askConfirmation('Do you want to remove it from '.$altType.' [<comment>yes</comment>]? ', true)) {
5614 $json->removeLink($altType, $composer[$altType][$package]);
5615 }
5616 }
5617 } else {
5618 $io->writeError('<warning>'.$package.' is not required in your composer.json and has not been removed</warning>');
5619 }
5620 }
5621
5622 if ($input->getOption('no-update')) {
5623 return 0;
5624 }
5625
5626
5627  $this->resetComposer();
5628 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
5629 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
5630
5631 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'remove', $input, $output);
5632 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5633
5634 $install = Installer::create($io, $composer);
5635
5636 $updateDevMode = !$input->getOption('update-no-dev');
5637 $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
5638 $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
5639 $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
5640
5641 $install
5642 ->setVerbose($input->getOption('verbose'))
5643 ->setDevMode($updateDevMode)
5644 ->setOptimizeAutoloader($optimize)
5645 ->setClassMapAuthoritative($authoritative)
5646 ->setApcuAutoloader($apcu)
5647 ->setUpdate(true)
5648 ->setUpdateWhitelist($packages)
5649 ->setWhitelistDependencies(!$input->getOption('no-update-with-dependencies'))
5650 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
5651 ->setRunScripts(!$input->getOption('no-scripts'))
5652 ;
5653
5654 $status = $install->run();
5655 if ($status !== 0) {
5656 $io->writeError("\n".'<error>Removal failed, reverting '.$file.' to its original content.</error>');
5657 file_put_contents($jsonFile->getPath(), $composerBackup);
5658 }
5659
5660 return $status;
5661 }
5662 }
5663 <?php
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
5674
5675 namespace Composer\Command;
5676
5677 use Symfony\Component\Console\Input\InputInterface;
5678 use Symfony\Component\Console\Input\InputArgument;
5679 use Symfony\Component\Console\Input\InputOption;
5680 use Symfony\Component\Console\Output\OutputInterface;
5681 use Composer\Factory;
5682 use Composer\Installer;
5683 use Composer\Json\JsonFile;
5684 use Composer\Json\JsonManipulator;
5685 use Composer\Package\Version\VersionParser;
5686 use Composer\Plugin\CommandEvent;
5687 use Composer\Plugin\PluginEvents;
5688 use Composer\Repository\CompositeRepository;
5689 use Composer\Repository\PlatformRepository;
5690
5691
5692
5693
5694
5695 class RequireCommand extends InitCommand
5696 {
5697 protected function configure()
5698 {
5699 $this
5700 ->setName('require')
5701 ->setDescription('Adds required packages to your composer.json and installs them.')
5702 ->setDefinition(array(
5703 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"'),
5704 new InputOption('dev', null, InputOption::VALUE_NONE, 'Add requirement to require-dev.'),
5705 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
5706 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
5707 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
5708 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
5709 new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
5710 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
5711 new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
5712 new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies.'),
5713 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
5714 new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
5715 new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
5716 new InputOption('sort-packages', null, InputOption::VALUE_NONE, 'Sorts packages when adding/updating a new dependency'),
5717 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
5718 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
5719 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
5720 ))
5721 ->setHelp(<<<EOT
5722 The require command adds required packages to your composer.json and installs them.
5723
5724 If you do not specify a version constraint, composer will choose a suitable one based on the available package versions.
5725
5726 If you do not want to install the new dependencies immediately you can call it with --no-update
5727
5728 EOT
5729 )
5730 ;
5731 }
5732
5733 protected function execute(InputInterface $input, OutputInterface $output)
5734 {
5735 $file = Factory::getComposerFile();
5736 $io = $this->getIO();
5737
5738 $newlyCreated = !file_exists($file);
5739 if ($newlyCreated && !file_put_contents($file, "{\n}\n")) {
5740 $io->writeError('<error>'.$file.' could not be created.</error>');
5741
5742 return 1;
5743 }
5744 if (!is_readable($file)) {
5745 $io->writeError('<error>'.$file.' is not readable.</error>');
5746
5747 return 1;
5748 }
5749 if (!is_writable($file)) {
5750 $io->writeError('<error>'.$file.' is not writable.</error>');
5751
5752 return 1;
5753 }
5754
5755 if (filesize($file) === 0) {
5756 file_put_contents($file, "{\n}\n");
5757 }
5758
5759 $json = new JsonFile($file);
5760 $composerBackup = file_get_contents($json->getPath());
5761
5762 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
5763 $repos = $composer->getRepositoryManager()->getRepositories();
5764
5765 $platformOverrides = $composer->getConfig()->get('platform') ?: array();
5766
5767  $this->repos = new CompositeRepository(array_merge(
5768 array(new PlatformRepository(array(), $platformOverrides)),
5769 $repos
5770 ));
5771
5772 if ($composer->getPackage()->getPreferStable()) {
5773 $preferredStability = 'stable';
5774 } else {
5775 $preferredStability = $composer->getPackage()->getMinimumStability();
5776 }
5777
5778 $phpVersion = $this->repos->findPackage('php', '*')->getVersion();
5779 $requirements = $this->determineRequirements($input, $output, $input->getArgument('packages'), $phpVersion, $preferredStability);
5780
5781 $requireKey = $input->getOption('dev') ? 'require-dev' : 'require';
5782 $removeKey = $input->getOption('dev') ? 'require' : 'require-dev';
5783 $requirements = $this->formatRequirements($requirements);
5784
5785
5786  $versionParser = new VersionParser();
5787 foreach ($requirements as $constraint) {
5788 $versionParser->parseConstraints($constraint);
5789 }
5790
5791 $sortPackages = $input->getOption('sort-packages') || $composer->getConfig()->get('sort-packages');
5792
5793 if (!$this->updateFileCleanly($json, $requirements, $requireKey, $removeKey, $sortPackages)) {
5794 $composerDefinition = $json->read();
5795 foreach ($requirements as $package => $version) {
5796 $composerDefinition[$requireKey][$package] = $version;
5797 unset($composerDefinition[$removeKey][$package]);
5798 }
5799 $json->write($composerDefinition);
5800 }
5801
5802 $io->writeError('<info>'.$file.' has been '.($newlyCreated ? 'created' : 'updated').'</info>');
5803
5804 if ($input->getOption('no-update')) {
5805 return 0;
5806 }
5807 $updateDevMode = !$input->getOption('update-no-dev');
5808 $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
5809 $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
5810 $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
5811
5812
5813  $this->resetComposer();
5814 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
5815 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
5816
5817 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'require', $input, $output);
5818 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5819
5820 $install = Installer::create($io, $composer);
5821
5822 $install
5823 ->setVerbose($input->getOption('verbose'))
5824 ->setPreferSource($input->getOption('prefer-source'))
5825 ->setPreferDist($input->getOption('prefer-dist'))
5826 ->setDevMode($updateDevMode)
5827 ->setRunScripts(!$input->getOption('no-scripts'))
5828 ->setSkipSuggest($input->getOption('no-suggest'))
5829 ->setOptimizeAutoloader($optimize)
5830 ->setClassMapAuthoritative($authoritative)
5831 ->setApcuAutoloader($apcu)
5832 ->setUpdate(true)
5833 ->setUpdateWhitelist(array_keys($requirements))
5834 ->setWhitelistDependencies($input->getOption('update-with-dependencies'))
5835 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
5836 ->setPreferStable($input->getOption('prefer-stable'))
5837 ->setPreferLowest($input->getOption('prefer-lowest'))
5838 ;
5839
5840 $status = $install->run();
5841 if ($status !== 0) {
5842 if ($newlyCreated) {
5843 $io->writeError("\n".'<error>Installation failed, deleting '.$file.'.</error>');
5844 unlink($json->getPath());
5845 } else {
5846 $io->writeError("\n".'<error>Installation failed, reverting '.$file.' to its original content.</error>');
5847 file_put_contents($json->getPath(), $composerBackup);
5848 }
5849 }
5850
5851 return $status;
5852 }
5853
5854 private function updateFileCleanly($json, array $new, $requireKey, $removeKey, $sortPackages)
5855 {
5856 $contents = file_get_contents($json->getPath());
5857
5858 $manipulator = new JsonManipulator($contents);
5859
5860 foreach ($new as $package => $constraint) {
5861 if (!$manipulator->addLink($requireKey, $package, $constraint, $sortPackages)) {
5862 return false;
5863 }
5864 if (!$manipulator->removeSubNode($removeKey, $package)) {
5865 return false;
5866 }
5867 }
5868
5869 file_put_contents($json->getPath(), $manipulator->getContents());
5870
5871 return true;
5872 }
5873
5874 protected function interact(InputInterface $input, OutputInterface $output)
5875 {
5876 return;
5877 }
5878 }
5879 <?php
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890
5891 namespace Composer\Command;
5892
5893 use Composer\Script\Event as ScriptEvent;
5894 use Composer\Script\ScriptEvents;
5895 use Composer\Util\ProcessExecutor;
5896 use Symfony\Component\Console\Input\InputInterface;
5897 use Symfony\Component\Console\Input\InputOption;
5898 use Symfony\Component\Console\Input\InputArgument;
5899 use Symfony\Component\Console\Output\OutputInterface;
5900
5901
5902
5903
5904 class RunScriptCommand extends BaseCommand
5905 {
5906
5907
5908
5909 protected $scriptEvents = array(
5910 ScriptEvents::PRE_INSTALL_CMD,
5911 ScriptEvents::POST_INSTALL_CMD,
5912 ScriptEvents::PRE_UPDATE_CMD,
5913 ScriptEvents::POST_UPDATE_CMD,
5914 ScriptEvents::PRE_STATUS_CMD,
5915 ScriptEvents::POST_STATUS_CMD,
5916 ScriptEvents::POST_ROOT_PACKAGE_INSTALL,
5917 ScriptEvents::POST_CREATE_PROJECT_CMD,
5918 ScriptEvents::PRE_ARCHIVE_CMD,
5919 ScriptEvents::POST_ARCHIVE_CMD,
5920 ScriptEvents::PRE_AUTOLOAD_DUMP,
5921 ScriptEvents::POST_AUTOLOAD_DUMP,
5922 );
5923
5924 protected function configure()
5925 {
5926 $this
5927 ->setName('run-script')
5928 ->setDescription('Runs the scripts defined in composer.json.')
5929 ->setDefinition(array(
5930 new InputArgument('script', InputArgument::OPTIONAL, 'Script name to run.'),
5931 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
5932 new InputOption('timeout', null, InputOption::VALUE_REQUIRED, 'Sets script timeout in seconds, or 0 for never.'),
5933 new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
5934 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
5935 new InputOption('list', 'l', InputOption::VALUE_NONE, 'List scripts.'),
5936 ))
5937 ->setHelp(<<<EOT
5938 The <info>run-script</info> command runs scripts defined in composer.json:
5939
5940 <info>php composer.phar run-script post-update-cmd</info>
5941 EOT
5942 )
5943 ;
5944 }
5945
5946 protected function execute(InputInterface $input, OutputInterface $output)
5947 {
5948 if ($input->getOption('list')) {
5949 return $this->listScripts();
5950 } elseif (!$input->getArgument('script')) {
5951 throw new \RuntimeException('Missing required argument "script"');
5952 }
5953
5954 $script = $input->getArgument('script');
5955 if (!in_array($script, $this->scriptEvents)) {
5956 if (defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
5957 throw new \InvalidArgumentException(sprintf('Script "%s" cannot be run with this command', $script));
5958 }
5959 }
5960
5961 $composer = $this->getComposer();
5962 $devMode = $input->getOption('dev') || !$input->getOption('no-dev');
5963 $event = new ScriptEvent($script, $composer, $this->getIO(), $devMode);
5964 $hasListeners = $composer->getEventDispatcher()->hasEventListeners($event);
5965 if (!$hasListeners) {
5966 throw new \InvalidArgumentException(sprintf('Script "%s" is not defined in this package', $script));
5967 }
5968
5969 $args = $input->getArgument('args');
5970
5971 if (!is_null($timeout = $input->getOption('timeout'))) {
5972 if (!ctype_digit($timeout)) {
5973 throw new \RuntimeException('Timeout value must be numeric and positive if defined, or 0 for forever');
5974 }
5975
5976  ProcessExecutor::setTimeout((int) $timeout);
5977 }
5978
5979 return $composer->getEventDispatcher()->dispatchScript($script, $devMode, $args);
5980 }
5981
5982 protected function listScripts()
5983 {
5984 $scripts = $this->getComposer()->getPackage()->getScripts();
5985
5986 if (!count($scripts)) {
5987 return 0;
5988 }
5989
5990 $io = $this->getIO();
5991 $io->writeError('<info>scripts:</info>');
5992 foreach ($scripts as $name => $script) {
5993 $io->write('  ' . $name);
5994 }
5995
5996 return 0;
5997 }
5998 }
5999 <?php
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010
6011 namespace Composer\Command;
6012
6013 use Symfony\Component\Console\Input\InputInterface;
6014 use Symfony\Component\Console\Input\InputOption;
6015 use Symfony\Component\Console\Input\InputArgument;
6016 use Symfony\Component\Console\Output\OutputInterface;
6017
6018
6019
6020
6021 class ScriptAliasCommand extends BaseCommand
6022 {
6023 private $script;
6024
6025 public function __construct($script)
6026 {
6027 $this->script = $script;
6028
6029 parent::__construct();
6030 }
6031
6032 protected function configure()
6033 {
6034 $this
6035 ->setName($this->script)
6036 ->setDescription('Runs the '.$this->script.' script as defined in composer.json.')
6037 ->setDefinition(array(
6038 new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
6039 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
6040 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
6041 ))
6042 ->setHelp(<<<EOT
6043 The <info>run-script</info> command runs scripts defined in composer.json:
6044
6045 <info>php composer.phar run-script post-update-cmd</info>
6046 EOT
6047 )
6048 ;
6049 }
6050
6051 protected function execute(InputInterface $input, OutputInterface $output)
6052 {
6053 $composer = $this->getComposer();
6054
6055 $args = $input->getArguments();
6056
6057 return $composer->getEventDispatcher()->dispatchScript($this->script, $input->getOption('dev') || !$input->getOption('no-dev'), $args['args']);
6058 }
6059 }
6060 <?php
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072 namespace Composer\Command;
6073
6074 use Composer\Factory;
6075 use Symfony\Component\Console\Input\InputInterface;
6076 use Symfony\Component\Console\Input\InputArgument;
6077 use Symfony\Component\Console\Input\InputOption;
6078 use Symfony\Component\Console\Output\OutputInterface;
6079 use Composer\Repository\CompositeRepository;
6080 use Composer\Repository\PlatformRepository;
6081 use Composer\Repository\RepositoryInterface;
6082 use Composer\Plugin\CommandEvent;
6083 use Composer\Plugin\PluginEvents;
6084
6085
6086
6087
6088 class SearchCommand extends BaseCommand
6089 {
6090 protected $matches;
6091 protected $lowMatches = array();
6092 protected $tokens;
6093 protected $output;
6094 protected $onlyName;
6095
6096 protected function configure()
6097 {
6098 $this
6099 ->setName('search')
6100 ->setDescription('Searches for packages.')
6101 ->setDefinition(array(
6102 new InputOption('only-name', 'N', InputOption::VALUE_NONE, 'Search only in name'),
6103 new InputOption('type', 't', InputOption::VALUE_REQUIRED, 'Search for a specific package type'),
6104 new InputArgument('tokens', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'tokens to search for'),
6105 ))
6106 ->setHelp(<<<EOT
6107 The search command searches for packages by its name
6108 <info>php composer.phar search symfony composer</info>
6109
6110 EOT
6111 )
6112 ;
6113 }
6114
6115 protected function execute(InputInterface $input, OutputInterface $output)
6116 {
6117
6118  $platformRepo = new PlatformRepository;
6119 $io = $this->getIO();
6120 if (!($composer = $this->getComposer(false))) {
6121 $composer = Factory::create($this->getIO(), array());
6122 }
6123 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
6124 $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
6125 $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
6126
6127 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'search', $input, $output);
6128 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6129
6130 $onlyName = $input->getOption('only-name');
6131 $type = $input->getOption('type') ?: null;
6132
6133 $flags = $onlyName ? RepositoryInterface::SEARCH_NAME : RepositoryInterface::SEARCH_FULLTEXT;
6134 $results = $repos->search(implode(' ', $input->getArgument('tokens')), $flags, $type);
6135
6136 foreach ($results as $result) {
6137 $io->write($result['name'] . (isset($result['description']) ? ' '. $result['description'] : ''));
6138 }
6139 }
6140 }
6141 <?php
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152
6153 namespace Composer\Command;
6154
6155 use Composer\Composer;
6156 use Composer\Factory;
6157 use Composer\Config;
6158 use Composer\Util\Filesystem;
6159 use Composer\SelfUpdate\Keys;
6160 use Composer\SelfUpdate\Versions;
6161 use Composer\IO\IOInterface;
6162 use Composer\Downloader\FilesystemException;
6163 use Symfony\Component\Console\Input\InputInterface;
6164 use Symfony\Component\Console\Input\InputOption;
6165 use Symfony\Component\Console\Input\InputArgument;
6166 use Symfony\Component\Console\Output\OutputInterface;
6167 use Symfony\Component\Finder\Finder;
6168
6169
6170
6171
6172
6173
6174 class SelfUpdateCommand extends BaseCommand
6175 {
6176 const HOMEPAGE = 'getcomposer.org';
6177 const OLD_INSTALL_EXT = '-old.phar';
6178
6179 protected function configure()
6180 {
6181 $this
6182 ->setName('self-update')
6183 ->setAliases(array('selfupdate'))
6184 ->setDescription('Updates composer.phar to the latest version.')
6185 ->setDefinition(array(
6186 new InputOption('rollback', 'r', InputOption::VALUE_NONE, 'Revert to an older installation of composer'),
6187 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'),
6188 new InputArgument('version', InputArgument::OPTIONAL, 'The version to update to'),
6189 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
6190 new InputOption('update-keys', null, InputOption::VALUE_NONE, 'Prompt user for a key update'),
6191 new InputOption('stable', null, InputOption::VALUE_NONE, 'Force an update to the stable channel'),
6192 new InputOption('preview', null, InputOption::VALUE_NONE, 'Force an update to the preview channel'),
6193 new InputOption('snapshot', null, InputOption::VALUE_NONE, 'Force an update to the snapshot channel'),
6194 new InputOption('set-channel-only', null, InputOption::VALUE_NONE, 'Only store the channel as the default one and then exit'),
6195 ))
6196 ->setHelp(<<<EOT
6197 The <info>self-update</info> command checks getcomposer.org for newer
6198 versions of composer and if found, installs the latest.
6199
6200 <info>php composer.phar self-update</info>
6201
6202 EOT
6203 )
6204 ;
6205 }
6206
6207 protected function execute(InputInterface $input, OutputInterface $output)
6208 {
6209 $config = Factory::createConfig();
6210
6211 if ($config->get('disable-tls') === true) {
6212 $baseUrl = 'http://' . self::HOMEPAGE;
6213 } else {
6214 $baseUrl = 'https://' . self::HOMEPAGE;
6215 }
6216
6217 $io = $this->getIO();
6218 $remoteFilesystem = Factory::createRemoteFilesystem($io, $config);
6219
6220 $versionsUtil = new Versions($config, $remoteFilesystem);
6221
6222
6223  foreach (array('stable', 'preview', 'snapshot') as $channel) {
6224 if ($input->getOption($channel)) {
6225 $versionsUtil->setChannel($channel);
6226 }
6227 }
6228
6229 if ($input->getOption('set-channel-only')) {
6230 return 0;
6231 }
6232
6233 $cacheDir = $config->get('cache-dir');
6234 $rollbackDir = $config->get('data-dir');
6235 $home = $config->get('home');
6236 $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0];
6237
6238 if ($input->getOption('update-keys')) {
6239 return $this->fetchKeys($io, $config);
6240 }
6241
6242
6243  $tmpDir = is_writable(dirname($localFilename)) ? dirname($localFilename) : $cacheDir;
6244
6245
6246  if (!is_writable($tmpDir)) {
6247 throw new FilesystemException('Composer update failed: the "'.$tmpDir.'" directory used to download the temp file could not be written');
6248 }
6249
6250 if ($input->getOption('rollback')) {
6251 return $this->rollback($output, $rollbackDir, $localFilename);
6252 }
6253
6254 $latest = $versionsUtil->getLatest();
6255 $latestVersion = $latest['version'];
6256 $updateVersion = $input->getArgument('version') ?: $latestVersion;
6257
6258 if (preg_match('{^[0-9a-f]{40}$}', $updateVersion) && $updateVersion !== $latestVersion) {
6259 $io->writeError('<error>You can not update to a specific SHA-1 as those phars are not available for download</error>');
6260
6261 return 1;
6262 }
6263
6264 if (Composer::VERSION === $updateVersion) {
6265 $io->writeError(sprintf('<info>You are already using composer version %s (%s channel).</info>', $updateVersion, $versionsUtil->getChannel()));
6266
6267
6268  if ($input->getOption('clean-backups')) {
6269 $this->cleanBackups($rollbackDir, $this->getLastBackupVersion($rollbackDir));
6270 }
6271
6272 return 0;
6273 }
6274
6275 $tempFilename = $tmpDir . '/' . basename($localFilename, '.phar').'-temp.phar';
6276 $backupFile = sprintf(
6277 '%s/%s-%s%s',
6278 $rollbackDir,
6279 strtr(Composer::RELEASE_DATE, ' :', '_-'),
6280 preg_replace('{^([0-9a-f]{7})[0-9a-f]{33}$}', '$1', Composer::VERSION),
6281 self::OLD_INSTALL_EXT
6282 );
6283
6284 $updatingToTag = !preg_match('{^[0-9a-f]{40}$}', $updateVersion);
6285
6286 $io->write(sprintf("Updating to version <info>%s</info> (%s channel).", $updateVersion, $versionsUtil->getChannel()));
6287 $remoteFilename = $baseUrl . ($updatingToTag ? "/download/{$updateVersion}/composer.phar" : '/composer.phar');
6288 $signature = $remoteFilesystem->getContents(self::HOMEPAGE, $remoteFilename.'.sig', false);
6289 $io->writeError('   ', false);
6290 $remoteFilesystem->copy(self::HOMEPAGE, $remoteFilename, $tempFilename, !$input->getOption('no-progress'));
6291 $io->writeError('');
6292
6293 if (!file_exists($tempFilename) || !$signature) {
6294 $io->writeError('<error>The download of the new composer version failed for an unexpected reason</error>');
6295
6296 return 1;
6297 }
6298
6299
6300  if (!extension_loaded('openssl') && $config->get('disable-tls')) {
6301 $io->writeError('<warning>Skipping phar signature verification as you have disabled OpenSSL via config.disable-tls</warning>');
6302 } else {
6303 if (!extension_loaded('openssl')) {
6304 throw new \RuntimeException('The openssl extension is required for phar signatures to be verified but it is not available. '
6305 . '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.');
6306 }
6307
6308 $sigFile = 'file://'.$home.'/' . ($updatingToTag ? 'keys.tags.pub' : 'keys.dev.pub');
6309 if (!file_exists($sigFile)) {
6310 file_put_contents($home.'/keys.dev.pub', <<<DEVPUBKEY
6311 -----BEGIN PUBLIC KEY-----
6312 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnBDHjZS6e0ZMoK3xTD7f
6313 FNCzlXjX/Aie2dit8QXA03pSrOTbaMnxON3hUL47Lz3g1SC6YJEMVHr0zYq4elWi
6314 i3ecFEgzLcj+pZM5X6qWu2Ozz4vWx3JYo1/a/HYdOuW9e3lwS8VtS0AVJA+U8X0A
6315 hZnBmGpltHhO8hPKHgkJtkTUxCheTcbqn4wGHl8Z2SediDcPTLwqezWKUfrYzu1f
6316 o/j3WFwFs6GtK4wdYtiXr+yspBZHO3y1udf8eFFGcb2V3EaLOrtfur6XQVizjOuk
6317 8lw5zzse1Qp/klHqbDRsjSzJ6iL6F4aynBc6Euqt/8ccNAIz0rLjLhOraeyj4eNn
6318 8iokwMKiXpcrQLTKH+RH1JCuOVxQ436bJwbSsp1VwiqftPQieN+tzqy+EiHJJmGf
6319 TBAbWcncicCk9q2md+AmhNbvHO4PWbbz9TzC7HJb460jyWeuMEvw3gNIpEo2jYa9
6320 pMV6cVqnSa+wOc0D7pC9a6bne0bvLcm3S+w6I5iDB3lZsb3A9UtRiSP7aGSo7D72
6321 8tC8+cIgZcI7k9vjvOqH+d7sdOU2yPCnRY6wFh62/g8bDnUpr56nZN1G89GwM4d4
6322 r/TU7BQQIzsZgAiqOGXvVklIgAMiV0iucgf3rNBLjjeNEwNSTTG9F0CtQ+7JLwaE
6323 wSEuAuRm+pRqi8BRnQ/GKUcCAwEAAQ==
6324 -----END PUBLIC KEY-----
6325 DEVPUBKEY
6326 );
6327 file_put_contents($home.'/keys.tags.pub', <<<TAGSPUBKEY
6328 -----BEGIN PUBLIC KEY-----
6329 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0Vi/2K6apCVj76nCnCl2
6330 MQUPdK+A9eqkYBacXo2wQBYmyVlXm2/n/ZsX6pCLYPQTHyr5jXbkQzBw8SKqPdlh
6331 vA7NpbMeNCz7wP/AobvUXM8xQuXKbMDTY2uZ4O7sM+PfGbptKPBGLe8Z8d2sUnTO
6332 bXtX6Lrj13wkRto7st/w/Yp33RHe9SlqkiiS4MsH1jBkcIkEHsRaveZzedUaxY0M
6333 mba0uPhGUInpPzEHwrYqBBEtWvP97t2vtfx8I5qv28kh0Y6t+jnjL1Urid2iuQZf
6334 noCMFIOu4vksK5HxJxxrN0GOmGmwVQjOOtxkwikNiotZGPR4KsVj8NnBrLX7oGuM
6335 nQvGciiu+KoC2r3HDBrpDeBVdOWxDzT5R4iI0KoLzFh2pKqwbY+obNPS2bj+2dgJ
6336 rV3V5Jjry42QOCBN3c88wU1PKftOLj2ECpewY6vnE478IipiEu7EAdK8Zwj2LmTr
6337 RKQUSa9k7ggBkYZWAeO/2Ag0ey3g2bg7eqk+sHEq5ynIXd5lhv6tC5PBdHlWipDK
6338 tl2IxiEnejnOmAzGVivE1YGduYBjN+mjxDVy8KGBrjnz1JPgAvgdwJ2dYw4Rsc/e
6339 TzCFWGk/HM6a4f0IzBWbJ5ot0PIi4amk07IotBXDWwqDiQTwyuGCym5EqWQ2BD95
6340 RGv89BPD+2DLnJysngsvVaUCAwEAAQ==
6341 -----END PUBLIC KEY-----
6342 TAGSPUBKEY
6343 );
6344 }
6345
6346 $pubkeyid = openssl_pkey_get_public($sigFile);
6347 $algo = defined('OPENSSL_ALGO_SHA384') ? OPENSSL_ALGO_SHA384 : 'SHA384';
6348 if (!in_array('SHA384', openssl_get_md_methods())) {
6349 throw new \RuntimeException('SHA384 is not supported by your openssl extension, could not verify the phar file integrity');
6350 }
6351 $signature = json_decode($signature, true);
6352 $signature = base64_decode($signature['sha384']);
6353 $verified = 1 === openssl_verify(file_get_contents($tempFilename), $signature, $pubkeyid, $algo);
6354 openssl_free_key($pubkeyid);
6355 if (!$verified) {
6356 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');
6357 }
6358 }
6359
6360
6361  if ($input->getOption('clean-backups')) {
6362 $this->cleanBackups($rollbackDir);
6363 }
6364
6365 if ($err = $this->setLocalPhar($localFilename, $tempFilename, $backupFile)) {
6366 @unlink($tempFilename);
6367 $io->writeError('<error>The file is corrupted ('.$err->getMessage().').</error>');
6368 $io->writeError('<error>Please re-run the self-update command to try again.</error>');
6369
6370 return 1;
6371 }
6372
6373 if (file_exists($backupFile)) {
6374 $io->writeError('Use <info>composer self-update --rollback</info> to return to version '.Composer::VERSION);
6375 } else {
6376 $io->writeError('<warning>A backup of the current version could not be written to '.$backupFile.', no rollback possible</warning>');
6377 }
6378 }
6379
6380 protected function fetchKeys(IOInterface $io, Config $config)
6381 {
6382 if (!$io->isInteractive()) {
6383 throw new \RuntimeException('Public keys can not be fetched in non-interactive mode, please run Composer interactively');
6384 }
6385
6386 $io->write('Open <info>https://composer.github.io/pubkeys.html</info> to find the latest keys');
6387
6388 $validator = function ($value) {
6389 if (!preg_match('{^-----BEGIN PUBLIC KEY-----$}', trim($value))) {
6390 throw new \UnexpectedValueException('Invalid input');
6391 }
6392
6393 return trim($value)."\n";
6394 };
6395
6396 $devKey = '';
6397 while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $devKey, $match)) {
6398 $devKey = $io->askAndValidate('Enter Dev / Snapshot Public Key (including lines with -----): ', $validator);
6399 while ($line = $io->ask('')) {
6400 $devKey .= trim($line)."\n";
6401 if (trim($line) === '-----END PUBLIC KEY-----') {
6402 break;
6403 }
6404 }
6405 }
6406 file_put_contents($keyPath = $config->get('home').'/keys.dev.pub', $match[0]);
6407 $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
6408
6409 $tagsKey = '';
6410 while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $tagsKey, $match)) {
6411 $tagsKey = $io->askAndValidate('Enter Tags Public Key (including lines with -----): ', $validator);
6412 while ($line = $io->ask('')) {
6413 $tagsKey .= trim($line)."\n";
6414 if (trim($line) === '-----END PUBLIC KEY-----') {
6415 break;
6416 }
6417 }
6418 }
6419 file_put_contents($keyPath = $config->get('home').'/keys.tags.pub', $match[0]);
6420 $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
6421
6422 $io->write('Public keys stored in '.$config->get('home'));
6423 }
6424
6425 protected function rollback(OutputInterface $output, $rollbackDir, $localFilename)
6426 {
6427 $rollbackVersion = $this->getLastBackupVersion($rollbackDir);
6428 if (!$rollbackVersion) {
6429 throw new \UnexpectedValueException('Composer rollback failed: no installation to roll back to in "'.$rollbackDir.'"');
6430 }
6431
6432 $oldFile = $rollbackDir . '/' . $rollbackVersion . self::OLD_INSTALL_EXT;
6433
6434 if (!is_file($oldFile)) {
6435 throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be found');
6436 }
6437 if (!is_readable($oldFile)) {
6438 throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be read');
6439 }
6440
6441 $io = $this->getIO();
6442 $io->writeError(sprintf("Rolling back to version <info>%s</info>.", $rollbackVersion));
6443 if ($err = $this->setLocalPhar($localFilename, $oldFile)) {
6444 $io->writeError('<error>The backup file was corrupted ('.$err->getMessage().').</error>');
6445
6446 return 1;
6447 }
6448
6449 return 0;
6450 }
6451
6452
6453
6454
6455
6456
6457
6458
6459 protected function setLocalPhar($localFilename, $newFilename, $backupTarget = null)
6460 {
6461 try {
6462 @chmod($newFilename, fileperms($localFilename));
6463 if (!ini_get('phar.readonly')) {
6464
6465  $phar = new \Phar($newFilename);
6466
6467  unset($phar);
6468 }
6469
6470
6471  if ($backupTarget && file_exists($localFilename)) {
6472 @copy($localFilename, $backupTarget);
6473 }
6474
6475 rename($newFilename, $localFilename);
6476
6477 return null;
6478 } catch (\Exception $e) {
6479 if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) {
6480 throw $e;
6481 }
6482
6483 return $e;
6484 }
6485 }
6486
6487 protected function cleanBackups($rollbackDir, $except = null)
6488 {
6489 $finder = $this->getOldInstallationFinder($rollbackDir);
6490 $io = $this->getIO();
6491 $fs = new Filesystem;
6492
6493 foreach ($finder as $file) {
6494 if ($except && $file->getBasename(self::OLD_INSTALL_EXT) === $except) {
6495 continue;
6496 }
6497 $file = (string) $file;
6498 $io->writeError('<info>Removing: '.$file.'</info>');
6499 $fs->remove($file);
6500 }
6501 }
6502
6503 protected function getLastBackupVersion($rollbackDir)
6504 {
6505 $finder = $this->getOldInstallationFinder($rollbackDir);
6506 $finder->sortByName();
6507 $files = iterator_to_array($finder);
6508
6509 if (count($files)) {
6510 return basename(end($files), self::OLD_INSTALL_EXT);
6511 }
6512
6513 return false;
6514 }
6515
6516 protected function getOldInstallationFinder($rollbackDir)
6517 {
6518 $finder = Finder::create()
6519 ->depth(0)
6520 ->files()
6521 ->name('*' . self::OLD_INSTALL_EXT)
6522 ->in($rollbackDir);
6523
6524 return $finder;
6525 }
6526 }
6527 <?php
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539 namespace Composer\Command;
6540
6541 use Composer\DependencyResolver\Pool;
6542 use Composer\DependencyResolver\DefaultPolicy;
6543 use Composer\Json\JsonFile;
6544 use Composer\Package\CompletePackageInterface;
6545 use Composer\Package\Version\VersionParser;
6546 use Composer\Package\BasePackage;
6547 use Composer\Package\Version\VersionSelector;
6548 use Composer\Plugin\CommandEvent;
6549 use Composer\Plugin\PluginEvents;
6550 use Composer\Package\PackageInterface;
6551 use Composer\Semver\Constraint\ConstraintInterface;
6552 use Composer\Util\Platform;
6553 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
6554 use Symfony\Component\Console\Input\InputInterface;
6555 use Symfony\Component\Console\Input\InputArgument;
6556 use Symfony\Component\Console\Input\InputOption;
6557 use Symfony\Component\Console\Output\OutputInterface;
6558 use Composer\Repository\ArrayRepository;
6559 use Composer\Repository\CompositeRepository;
6560 use Composer\Repository\ComposerRepository;
6561 use Composer\Repository\PlatformRepository;
6562 use Composer\Repository\RepositoryInterface;
6563 use Composer\Repository\RepositoryFactory;
6564 use Composer\Spdx\SpdxLicenses;
6565 use Composer\Composer;
6566 use Composer\Semver\Semver;
6567
6568
6569
6570
6571
6572
6573
6574 class ShowCommand extends BaseCommand
6575 {
6576
6577 protected $versionParser;
6578 protected $colors;
6579
6580
6581 private $pool;
6582
6583 protected function configure()
6584 {
6585 $this
6586 ->setName('show')
6587 ->setAliases(array('info'))
6588 ->setDescription('Shows information about packages.')
6589 ->setDefinition(array(
6590 new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
6591 new InputArgument('version', InputArgument::OPTIONAL, 'Version or version constraint to inspect'),
6592 new InputOption('all', null, InputOption::VALUE_NONE, 'List all packages'),
6593 new InputOption('installed', 'i', InputOption::VALUE_NONE, 'List installed packages only (enabled by default, only present for BC).'),
6594 new InputOption('platform', 'p', InputOption::VALUE_NONE, 'List platform packages only'),
6595 new InputOption('available', 'a', InputOption::VALUE_NONE, 'List available packages only'),
6596 new InputOption('self', 's', InputOption::VALUE_NONE, 'Show the root package information'),
6597 new InputOption('name-only', 'N', InputOption::VALUE_NONE, 'List package names only'),
6598 new InputOption('path', 'P', InputOption::VALUE_NONE, 'Show package paths'),
6599 new InputOption('tree', 't', InputOption::VALUE_NONE, 'List the dependencies as a tree'),
6600 new InputOption('latest', 'l', InputOption::VALUE_NONE, 'Show the latest version'),
6601 new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show the latest version but only for packages that are outdated'),
6602 new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
6603 new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
6604 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
6605 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
6606 ))
6607 ->setHelp(<<<EOT
6608 The show command displays detailed information about a package, or
6609 lists all packages available.
6610
6611 EOT
6612 )
6613 ;
6614 }
6615
6616 protected function execute(InputInterface $input, OutputInterface $output)
6617 {
6618 $this->versionParser = new VersionParser;
6619 if ($input->getOption('tree')) {
6620 $this->initStyles($output);
6621 }
6622
6623 $composer = $this->getComposer(false);
6624 $io = $this->getIO();
6625
6626 if ($input->getOption('installed')) {
6627 $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>');
6628 }
6629
6630 if ($input->getOption('outdated')) {
6631 $input->setOption('latest', true);
6632 }
6633
6634 if ($input->getOption('direct') && ($input->getOption('all') || $input->getOption('available') || $input->getOption('platform'))) {
6635 $io->writeError('The --direct (-D) option is not usable in combination with --all, --platform (-p) or --available (-a)');
6636
6637 return 1;
6638 }
6639
6640 if ($input->getOption('tree') && ($input->getOption('all') || $input->getOption('available'))) {
6641 $io->writeError('The --tree (-t) option is not usable in combination with --all or --available (-a)');
6642
6643 return 1;
6644 }
6645
6646 $format = $input->getOption('format');
6647 if (!in_array($format, array('text', 'json'))) {
6648 $io->writeError(sprintf('Unsupported format "%s". See help for supported formats.', $format));
6649
6650 return 1;
6651 }
6652
6653
6654  $platformOverrides = array();
6655 if ($composer) {
6656 $platformOverrides = $composer->getConfig()->get('platform') ?: array();
6657 }
6658 $platformRepo = new PlatformRepository(array(), $platformOverrides);
6659 $phpVersion = $platformRepo->findPackage('php', '*')->getVersion();
6660
6661 if ($input->getOption('self')) {
6662 $package = $this->getComposer()->getPackage();
6663 $repos = $installedRepo = new ArrayRepository(array($package));
6664 } elseif ($input->getOption('platform')) {
6665 $repos = $installedRepo = $platformRepo;
6666 } elseif ($input->getOption('available')) {
6667 $installedRepo = $platformRepo;
6668 if ($composer) {
6669 $repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
6670 } else {
6671 $defaultRepos = RepositoryFactory::defaultRepos($io);
6672 $repos = new CompositeRepository($defaultRepos);
6673 $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
6674 }
6675 } elseif ($input->getOption('all') && $composer) {
6676 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
6677 $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
6678 $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
6679 } elseif ($input->getOption('all')) {
6680 $defaultRepos = RepositoryFactory::defaultRepos($io);
6681 $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
6682 $installedRepo = $platformRepo;
6683 $repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos));
6684 } else {
6685 $repos = $installedRepo = $this->getComposer()->getRepositoryManager()->getLocalRepository();
6686 $rootPkg = $this->getComposer()->getPackage();
6687 if (!$installedRepo->getPackages() && ($rootPkg->getRequires() || $rootPkg->getDevRequires())) {
6688 $io->writeError('<warning>No dependencies installed. Try running composer install or update.</warning>');
6689 }
6690 }
6691
6692 if ($composer) {
6693 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'show', $input, $output);
6694 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6695 }
6696
6697 if ($input->getOption('latest') && null === $composer) {
6698 $io->writeError('No composer.json found in the current directory, disabling "latest" option');
6699 $input->setOption('latest', false);
6700 }
6701
6702 $packageFilter = $input->getArgument('package');
6703
6704
6705  if (($packageFilter && false === strpos($packageFilter, '*')) || !empty($package)) {
6706 if ('json' === $format) {
6707 $io->writeError('Format "json" is only supported for package listings, falling back to format "text"');
6708 }
6709 if (empty($package)) {
6710 list($package, $versions) = $this->getPackage($installedRepo, $repos, $input->getArgument('package'), $input->getArgument('version'));
6711
6712 if (empty($package)) {
6713 $options = $input->getOptions();
6714 if (!isset($options['working-dir']) || !file_exists('composer.json')) {
6715 throw new \InvalidArgumentException('Package ' . $packageFilter . ' not found');
6716 }
6717
6718 $io->writeError('Package ' . $packageFilter . ' not found in ' . $options['working-dir'] . '/composer.json');
6719
6720 return 1;
6721 }
6722 } else {
6723 $versions = array($package->getPrettyVersion() => $package->getVersion());
6724 }
6725
6726 if ($input->getOption('tree')) {
6727 $this->displayPackageTree($package, $installedRepo, $repos);
6728 } else {
6729 $latestPackage = null;
6730 $exitCode = 0;
6731 if ($input->getOption('latest')) {
6732 $latestPackage = $this->findLatestPackage($package, $composer, $phpVersion);
6733 }
6734 if ($input->getOption('outdated') && $input->getOption('strict') && $latestPackage && $latestPackage->getFullPrettyVersion() !== $package->getFullPrettyVersion() && !$latestPackage->isAbandoned()) {
6735 $exitCode = 1;
6736 }
6737 $this->printMeta($package, $versions, $installedRepo, $latestPackage ?: null);
6738 $this->printLinks($package, 'requires');
6739 $this->printLinks($package, 'devRequires', 'requires (dev)');
6740 if ($package->getSuggests()) {
6741 $io->write("\n<info>suggests</info>");
6742 foreach ($package->getSuggests() as $suggested => $reason) {
6743 $io->write($suggested . ' <comment>' . $reason . '</comment>');
6744 }
6745 }
6746 $this->printLinks($package, 'provides');
6747 $this->printLinks($package, 'conflicts');
6748 $this->printLinks($package, 'replaces');
6749 }
6750
6751 return $exitCode;
6752 }
6753
6754
6755  if ($input->getOption('tree')) {
6756 if ('json' === $format) {
6757 $io->writeError('Format "json" is only supported for package listings, falling back to format "text"');
6758 }
6759 $rootRequires = $this->getRootRequires();
6760 foreach ($installedRepo->getPackages() as $package) {
6761 if (in_array($package->getName(), $rootRequires, true)) {
6762 $this->displayPackageTree($package, $installedRepo, $repos);
6763 }
6764 }
6765
6766 return 0;
6767 }
6768
6769 if ($repos instanceof CompositeRepository) {
6770 $repos = $repos->getRepositories();
6771 } elseif (!is_array($repos)) {
6772 $repos = array($repos);
6773 }
6774
6775
6776  $packages = array();
6777 if (null !== $packageFilter) {
6778 $packageFilter = '{^'.str_replace('\\*', '.*?', preg_quote($packageFilter)).'$}i';
6779 }
6780
6781 $packageListFilter = array();
6782 if ($input->getOption('direct')) {
6783 $packageListFilter = $this->getRootRequires();
6784 }
6785
6786 list($width) = $this->getApplication()->getTerminalDimensions();
6787 if (null === $width) {
6788
6789  
6790  $width = PHP_INT_MAX;
6791 }
6792 if (Platform::isWindows()) {
6793 $width--;
6794 } else {
6795 $width = max(80, $width);
6796 }
6797
6798 if ($input->getOption('path') && null === $composer) {
6799 $io->writeError('No composer.json found in the current directory, disabling "path" option');
6800 $input->setOption('path', false);
6801 }
6802
6803 foreach ($repos as $repo) {
6804 if ($repo === $platformRepo) {
6805 $type = 'platform';
6806 } elseif (
6807 $repo === $installedRepo
6808 || ($installedRepo instanceof CompositeRepository && in_array($repo, $installedRepo->getRepositories(), true))
6809 ) {
6810 $type = 'installed';
6811 } else {
6812 $type = 'available';
6813 }
6814 if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
6815 foreach ($repo->getProviderNames() as $name) {
6816 if (!$packageFilter || preg_match($packageFilter, $name)) {
6817 $packages[$type][$name] = $name;
6818 }
6819 }
6820 } else {
6821 foreach ($repo->getPackages() as $package) {
6822 if (!isset($packages[$type][$package->getName()])
6823 || !is_object($packages[$type][$package->getName()])
6824 || version_compare($packages[$type][$package->getName()]->getVersion(), $package->getVersion(), '<')
6825 ) {
6826 if (!$packageFilter || preg_match($packageFilter, $package->getName())) {
6827 if (!$packageListFilter || in_array($package->getName(), $packageListFilter, true)) {
6828 $packages[$type][$package->getName()] = $package;
6829 }
6830 }
6831 }
6832 }
6833 }
6834 }
6835
6836 $showAllTypes = $input->getOption('all');
6837 $showLatest = $input->getOption('latest');
6838 $showMinorOnly = $input->getOption('minor-only');
6839 $indent = $showAllTypes ? '  ' : '';
6840 $latestPackages = array();
6841 $exitCode = 0;
6842 $viewData = array();
6843 $viewMetaData = array();
6844 foreach (array('platform' => true, 'available' => false, 'installed' => true) as $type => $showVersion) {
6845 if (isset($packages[$type])) {
6846 ksort($packages[$type]);
6847
6848 $nameLength = $versionLength = $latestLength = 0;
6849 foreach ($packages[$type] as $package) {
6850 if (is_object($package)) {
6851 $nameLength = max($nameLength, strlen($package->getPrettyName()));
6852 if ($showVersion) {
6853 $versionLength = max($versionLength, strlen($package->getFullPrettyVersion()));
6854 if ($showLatest) {
6855 $latestPackage = $this->findLatestPackage($package, $composer, $phpVersion, $showMinorOnly);
6856 if ($latestPackage === false) {
6857 continue;
6858 }
6859
6860 $latestPackages[$package->getPrettyName()] = $latestPackage;
6861 $latestLength = max($latestLength, strlen($latestPackage->getFullPrettyVersion()));
6862 }
6863 }
6864 } else {
6865 $nameLength = max($nameLength, strlen($package));
6866 }
6867 }
6868
6869 $writePath = !$input->getOption('name-only') && $input->getOption('path');
6870 $writeVersion = !$input->getOption('name-only') && !$input->getOption('path') && $showVersion;
6871 $writeLatest = $writeVersion && $showLatest;
6872 $writeDescription = !$input->getOption('name-only') && !$input->getOption('path');
6873
6874 $hasOutdatedPackages = false;
6875
6876 $viewData[$type] = array();
6877 $viewMetaData[$type] = array(
6878 'nameLength' => $nameLength,
6879 'versionLength' => $versionLength,
6880 'latestLength' => $latestLength,
6881 );
6882 foreach ($packages[$type] as $package) {
6883 $packageViewData = array();
6884 if (is_object($package)) {
6885 $latestPackage = null;
6886 if ($showLatest && isset($latestPackages[$package->getPrettyName()])) {
6887 $latestPackage = $latestPackages[$package->getPrettyName()];
6888 }
6889 if ($input->getOption('outdated') && $latestPackage && $latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion() && !$latestPackage->isAbandoned()) {
6890 continue;
6891 } elseif ($input->getOption('outdated') || $input->getOption('strict')) {
6892 $hasOutdatedPackages = true;
6893 }
6894
6895 $packageViewData['name'] = $package->getPrettyName();
6896 if ($writeVersion) {
6897 $packageViewData['version'] = $package->getFullPrettyVersion();
6898 }
6899 if ($writeLatest && $latestPackage) {
6900 $packageViewData['latest'] = $latestPackage->getFullPrettyVersion();
6901 $packageViewData['latest-status'] = $this->getUpdateStatus($latestPackage, $package);
6902 }
6903 if ($writeDescription) {
6904 $packageViewData['description'] = $package->getDescription();
6905 }
6906 if ($writePath) {
6907 $packageViewData['path'] = strtok(realpath($composer->getInstallationManager()->getInstallPath($package)), "\r\n");
6908 }
6909
6910 if ($latestPackage && $latestPackage->isAbandoned()) {
6911 $replacement = (is_string($latestPackage->getReplacementPackage()))
6912 ? 'Use ' . $latestPackage->getReplacementPackage() . ' instead'
6913 : 'No replacement was suggested';
6914 $packageWarning = sprintf(
6915 'Package %s is abandoned, you should avoid using it. %s.',
6916 $package->getPrettyName(),
6917 $replacement
6918 );
6919 $packageViewData['warning'] = $packageWarning;
6920 }
6921 } else {
6922 $packageViewData['name'] = $package;
6923 }
6924 $viewData[$type][] = $packageViewData;
6925 }
6926 if ($input->getOption('strict') && $hasOutdatedPackages) {
6927 $exitCode = 1;
6928 break;
6929 }
6930 }
6931 }
6932
6933 if ('json' === $format) {
6934 $io->write(JsonFile::encode($viewData));
6935 } else {
6936 foreach ($viewData as $type => $packages) {
6937 $nameLength = $viewMetaData[$type]['nameLength'];
6938 $versionLength = $viewMetaData[$type]['versionLength'];
6939 $latestLength = $viewMetaData[$type]['latestLength'];
6940
6941 $writeVersion = $nameLength + $versionLength + 3 <= $width;
6942 $writeLatest = $nameLength + $versionLength + $latestLength + 3 <= $width;
6943 $writeDescription = $nameLength + $versionLength + $latestLength + 24 <= $width;
6944
6945 if ($writeLatest && !$io->isDecorated()) {
6946 $latestLength += 2;
6947 }
6948
6949 if ($showAllTypes) {
6950 if ('available' === $type) {
6951 $io->write('<comment>' . $type . '</comment>:');
6952 } else {
6953 $io->write('<info>' . $type . '</info>:');
6954 }
6955 }
6956
6957 foreach ($packages as $package) {
6958 $io->write($indent . str_pad($package['name'], $nameLength, ' '), false);
6959 if (isset($package['version']) && $writeVersion) {
6960 $io->write(' ' . str_pad($package['version'], $versionLength, ' '), false);
6961 }
6962 if (isset($package['latest']) && $writeLatest) {
6963 $latestVersion = $package['latest'];
6964 $updateStatus = $package['latest-status'];
6965 $style = $this->updateStatusToVersionStyle($updateStatus);
6966 if (!$io->isDecorated()) {
6967 $latestVersion = str_replace(array('up-to-date', 'semver-safe-update', 'update-possible'), array('=', '!', '~'), $updateStatus) . ' ' . $latestVersion;
6968 }
6969 $io->write(' <' . $style . '>' . str_pad($latestVersion, $latestLength, ' ') . '</' . $style . '>', false);
6970 }
6971 if (isset($package['description']) && $writeDescription) {
6972 $description = strtok($package['description'], "\r\n");
6973 $remaining = $width - $nameLength - $versionLength - 4;
6974 if ($writeLatest) {
6975 $remaining -= $latestLength;
6976 }
6977 if (strlen($description) > $remaining) {
6978 $description = substr($description, 0, $remaining - 3) . '...';
6979 }
6980 $io->write(' ' . $description, false);
6981 }
6982 if (isset($package['path'])) {
6983 $io->write(' ' . $package['path'], false);
6984 }
6985 $io->write('');
6986 if (isset($package['warning'])) {
6987 $io->write('<warning>' . $package['warning'] . '</warning>');
6988 }
6989 }
6990
6991 if ($showAllTypes) {
6992 $io->write('');
6993 }
6994 }
6995 }
6996
6997 return $exitCode;
6998 }
6999
7000 protected function getRootRequires()
7001 {
7002 $rootPackage = $this->getComposer()->getPackage();
7003
7004 return array_map(
7005 'strtolower',
7006 array_keys(array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()))
7007 );
7008 }
7009
7010 protected function getVersionStyle(PackageInterface $latestPackage, PackageInterface $package)
7011 {
7012 return $this->updateStatusToVersionStyle($this->getUpdateStatus($latestPackage, $package));
7013 }
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025 protected function getPackage(RepositoryInterface $installedRepo, RepositoryInterface $repos, $name, $version = null)
7026 {
7027 $name = strtolower($name);
7028 $constraint = is_string($version) ? $this->versionParser->parseConstraints($version) : $version;
7029
7030 $policy = new DefaultPolicy();
7031 $pool = new Pool('dev');
7032 $pool->addRepository($repos);
7033
7034 $matchedPackage = null;
7035 $versions = array();
7036 $matches = $pool->whatProvides($name, $constraint);
7037 foreach ($matches as $index => $package) {
7038
7039  if ($package->getName() !== $name) {
7040 unset($matches[$index]);
7041 continue;
7042 }
7043
7044
7045  if (null === $version && $installedRepo->hasPackage($package)) {
7046 $matchedPackage = $package;
7047 }
7048
7049 $versions[$package->getPrettyVersion()] = $package->getVersion();
7050 $matches[$index] = $package->getId();
7051 }
7052
7053
7054  if (!$matchedPackage && $matches && $preferred = $policy->selectPreferredPackages($pool, array(), $matches)) {
7055 $matchedPackage = $pool->literalToPackage($preferred[0]);
7056 }
7057
7058 return array($matchedPackage, $versions);
7059 }
7060
7061
7062
7063
7064
7065
7066
7067
7068 protected function printMeta(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo, PackageInterface $latestPackage = null)
7069 {
7070 $io = $this->getIO();
7071 $io->write('<info>name</info>     : ' . $package->getPrettyName());
7072 $io->write('<info>descrip.</info> : ' . $package->getDescription());
7073 $io->write('<info>keywords</info> : ' . implode(', ', $package->getKeywords() ?: array()));
7074 $this->printVersions($package, $versions, $installedRepo);
7075 if ($latestPackage) {
7076 $style = $this->getVersionStyle($latestPackage, $package);
7077 $io->write('<info>latest</info>   : <'.$style.'>' . $latestPackage->getPrettyVersion() . '</'.$style.'>');
7078 } else {
7079 $latestPackage = $package;
7080 }
7081 $io->write('<info>type</info>     : ' . $package->getType());
7082 $this->printLicenses($package);
7083 $io->write('<info>source</info>   : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference()));
7084 $io->write('<info>dist</info>     : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference()));
7085 $io->write('<info>names</info>    : ' . implode(', ', $package->getNames()));
7086
7087 if ($latestPackage->isAbandoned()) {
7088 $replacement = ($latestPackage->getReplacementPackage() !== null)
7089 ? ' The author suggests using the ' . $latestPackage->getReplacementPackage(). ' package instead.'
7090 : null;
7091
7092 $io->writeError(
7093 sprintf('<warning>Attention: This package is abandoned and no longer maintained.%s</warning>', $replacement)
7094 );
7095 }
7096
7097 if ($package->getSupport()) {
7098 $io->write("\n<info>support</info>");
7099 foreach ($package->getSupport() as $type => $value) {
7100 $io->write('<comment>' . $type . '</comment> : '.$value);
7101 }
7102 }
7103
7104 if ($package->getAutoload()) {
7105 $io->write("\n<info>autoload</info>");
7106 foreach ($package->getAutoload() as $type => $autoloads) {
7107 $io->write('<comment>' . $type . '</comment>');
7108
7109 if ($type === 'psr-0') {
7110 foreach ($autoloads as $name => $path) {
7111 $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
7112 }
7113 } elseif ($type === 'psr-4') {
7114 foreach ($autoloads as $name => $path) {
7115 $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
7116 }
7117 } elseif ($type === 'classmap') {
7118 $io->write(implode(', ', $autoloads));
7119 }
7120 }
7121 if ($package->getIncludePaths()) {
7122 $io->write('<comment>include-path</comment>');
7123 $io->write(implode(', ', $package->getIncludePaths()));
7124 }
7125 }
7126 }
7127
7128
7129
7130
7131
7132
7133
7134
7135 protected function printVersions(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo)
7136 {
7137 uasort($versions, 'version_compare');
7138 $versions = array_keys(array_reverse($versions));
7139
7140
7141  if ($installedRepo->hasPackage($package)) {
7142 $installedVersion = $package->getPrettyVersion();
7143 $key = array_search($installedVersion, $versions);
7144 if (false !== $key) {
7145 $versions[$key] = '<info>* ' . $installedVersion . '</info>';
7146 }
7147 }
7148
7149 $versions = implode(', ', $versions);
7150
7151 $this->getIO()->write('<info>versions</info> : ' . $versions);
7152 }
7153
7154
7155
7156
7157
7158
7159
7160
7161 protected function printLinks(CompletePackageInterface $package, $linkType, $title = null)
7162 {
7163 $title = $title ?: $linkType;
7164 $io = $this->getIO();
7165 if ($links = $package->{'get'.ucfirst($linkType)}()) {
7166 $io->write("\n<info>" . $title . "</info>");
7167
7168 foreach ($links as $link) {
7169 $io->write($link->getTarget() . ' <comment>' . $link->getPrettyConstraint() . '</comment>');
7170 }
7171 }
7172 }
7173
7174
7175
7176
7177
7178
7179 protected function printLicenses(CompletePackageInterface $package)
7180 {
7181 $spdxLicenses = new SpdxLicenses();
7182
7183 $licenses = $package->getLicense();
7184 $io = $this->getIO();
7185
7186 foreach ($licenses as $licenseId) {
7187 $license = $spdxLicenses->getLicenseByIdentifier($licenseId); 
7188
7189 if (!$license) {
7190 $out = $licenseId;
7191 } else {
7192
7193  if ($license[1] === true) {
7194 $out = sprintf('%s (%s) (OSI approved) %s', $license[0], $licenseId, $license[2]);
7195 } else {
7196 $out = sprintf('%s (%s) %s', $license[0], $licenseId, $license[2]);
7197 }
7198 }
7199
7200 $io->write('<info>license</info>  : ' . $out);
7201 }
7202 }
7203
7204
7205
7206
7207
7208
7209 protected function initStyles(OutputInterface $output)
7210 {
7211 $this->colors = array(
7212 'green',
7213 'yellow',
7214 'cyan',
7215 'magenta',
7216 'blue',
7217 );
7218
7219 foreach ($this->colors as $color) {
7220 $style = new OutputFormatterStyle($color);
7221 $output->getFormatter()->setStyle($color, $style);
7222 }
7223 }
7224
7225
7226
7227
7228
7229
7230
7231
7232 protected function displayPackageTree(PackageInterface $package, RepositoryInterface $installedRepo, RepositoryInterface $distantRepos)
7233 {
7234 $io = $this->getIO();
7235 $io->write(sprintf('<info>%s</info>', $package->getPrettyName()), false);
7236 $io->write(' ' . $package->getPrettyVersion(), false);
7237 $io->write(' ' . strtok($package->getDescription(), "\r\n"));
7238
7239 if (is_object($package)) {
7240 $requires = $package->getRequires();
7241 $treeBar = '├';
7242 $j = 0;
7243 $total = count($requires);
7244 foreach ($requires as $requireName => $require) {
7245 $j++;
7246 if ($j == 0) {
7247 $this->writeTreeLine($treeBar);
7248 }
7249 if ($j == $total) {
7250 $treeBar = '└';
7251 }
7252 $level = 1;
7253 $color = $this->colors[$level];
7254 $info = sprintf('%s──<%s>%s</%s> %s', $treeBar, $color, $requireName, $color, $require->getPrettyConstraint());
7255 $this->writeTreeLine($info);
7256
7257 $treeBar = str_replace('└', ' ', $treeBar);
7258 $packagesInTree = array($package->getName(), $requireName);
7259
7260 $this->displayTree($requireName, $require, $installedRepo, $distantRepos, $packagesInTree, $treeBar, $level + 1);
7261 }
7262 }
7263 }
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276 protected function displayTree($name, $package, RepositoryInterface $installedRepo, RepositoryInterface $distantRepos, array $packagesInTree, $previousTreeBar = '├', $level = 1)
7277 {
7278 $previousTreeBar = str_replace('├', '│', $previousTreeBar);
7279 list($package, $versions) = $this->getPackage($installedRepo, $distantRepos, $name, $package->getPrettyConstraint() === 'self.version' ? $package->getConstraint() : $package->getPrettyConstraint());
7280 if (is_object($package)) {
7281 $requires = $package->getRequires();
7282 $treeBar = $previousTreeBar . '  ├';
7283 $i = 0;
7284 $total = count($requires);
7285 foreach ($requires as $requireName => $require) {
7286 $currentTree = $packagesInTree;
7287 $i++;
7288 if ($i == $total) {
7289 $treeBar = $previousTreeBar . '  └';
7290 }
7291 $colorIdent = $level % count($this->colors);
7292 $color = $this->colors[$colorIdent];
7293
7294 $circularWarn = in_array($requireName, $currentTree) ? '(circular dependency aborted here)' : '';
7295 $info = rtrim(sprintf('%s──<%s>%s</%s> %s %s', $treeBar, $color, $requireName, $color, $require->getPrettyConstraint(), $circularWarn));
7296 $this->writeTreeLine($info);
7297
7298 $treeBar = str_replace('└', ' ', $treeBar);
7299 if (!in_array($requireName, $currentTree)) {
7300 $currentTree[] = $requireName;
7301 $this->displayTree($requireName, $require, $installedRepo, $distantRepos, $currentTree, $treeBar, $level + 1);
7302 }
7303 }
7304 }
7305 }
7306
7307 private function updateStatusToVersionStyle($updateStatus)
7308 {
7309
7310  
7311  
7312  return str_replace(array('up-to-date', 'semver-safe-update', 'update-possible'), array('info', 'highlight', 'comment'), $updateStatus);
7313 }
7314
7315 private function getUpdateStatus(PackageInterface $latestPackage, PackageInterface $package)
7316 {
7317 if ($latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion()) {
7318 return 'up-to-date';
7319 }
7320
7321 $constraint = $package->getVersion();
7322 if (0 !== strpos($constraint, 'dev-')) {
7323 $constraint = '^'.$constraint;
7324 }
7325 if ($latestPackage->getVersion() && Semver::satisfies($latestPackage->getVersion(), $constraint)) {
7326
7327  return 'semver-safe-update';
7328 }
7329
7330
7331  return 'update-possible';
7332 }
7333
7334 private function writeTreeLine($line)
7335 {
7336 $io = $this->getIO();
7337 if (!$io->isDecorated()) {
7338 $line = str_replace(array('└', '├', '──', '│'), array('`-', '|-', '-', '|'), $line);
7339 }
7340
7341 $io->write($line);
7342 }
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354 private function findLatestPackage(PackageInterface $package, Composer $composer, $phpVersion, $minorOnly = false)
7355 {
7356
7357  $name = $package->getName();
7358 $versionSelector = new VersionSelector($this->getPool($composer));
7359 $stability = $composer->getPackage()->getMinimumStability();
7360 $flags = $composer->getPackage()->getStabilityFlags();
7361 if (isset($flags[$name])) {
7362 $stability = array_search($flags[$name], BasePackage::$stabilities, true);
7363 }
7364
7365 $bestStability = $stability;
7366 if ($composer->getPackage()->getPreferStable()) {
7367 $bestStability = $package->getStability();
7368 }
7369
7370 $targetVersion = null;
7371 if (0 === strpos($package->getVersion(), 'dev-')) {
7372 $targetVersion = $package->getVersion();
7373 }
7374
7375 if ($targetVersion === null && $minorOnly) {
7376 $targetVersion = '^' . $package->getVersion();
7377 }
7378
7379 return $versionSelector->findBestCandidate($name, $targetVersion, $phpVersion, $bestStability);
7380 }
7381
7382 private function getPool(Composer $composer)
7383 {
7384 if (!$this->pool) {
7385 $this->pool = new Pool($composer->getPackage()->getMinimumStability(), $composer->getPackage()->getStabilityFlags());
7386 $this->pool->addRepository(new CompositeRepository($composer->getRepositoryManager()->getRepositories()));
7387 }
7388
7389 return $this->pool;
7390 }
7391 }
7392 <?php
7393
7394
7395
7396
7397
7398
7399
7400
7401
7402
7403
7404 namespace Composer\Command;
7405
7406 use Symfony\Component\Console\Input\InputInterface;
7407 use Symfony\Component\Console\Input\InputOption;
7408 use Symfony\Component\Console\Output\OutputInterface;
7409 use Composer\Downloader\ChangeReportInterface;
7410 use Composer\Downloader\DvcsDownloaderInterface;
7411 use Composer\Downloader\VcsCapableDownloaderInterface;
7412 use Composer\Package\Dumper\ArrayDumper;
7413 use Composer\Package\Version\VersionGuesser;
7414 use Composer\Package\Version\VersionParser;
7415 use Composer\Plugin\CommandEvent;
7416 use Composer\Plugin\PluginEvents;
7417 use Composer\Script\ScriptEvents;
7418 use Composer\Util\ProcessExecutor;
7419
7420
7421
7422
7423
7424 class StatusCommand extends BaseCommand
7425 {
7426 const EXIT_CODE_ERRORS = 1;
7427 const EXIT_CODE_UNPUSHED_CHANGES = 2;
7428 const EXIT_CODE_VERSION_CHANGES = 4;
7429
7430 protected function configure()
7431 {
7432 $this
7433 ->setName('status')
7434 ->setDescription('Shows a list of locally modified packages.')
7435 ->setDefinition(array(
7436 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Show modified files for each directory that contains changes.'),
7437 ))
7438 ->setHelp(<<<EOT
7439 The status command displays a list of dependencies that have
7440 been modified locally.
7441
7442 EOT
7443 )
7444 ;
7445 }
7446
7447 protected function execute(InputInterface $input, OutputInterface $output)
7448 {
7449
7450  $composer = $this->getComposer();
7451
7452 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'status', $input, $output);
7453 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
7454
7455 $installedRepo = $composer->getRepositoryManager()->getLocalRepository();
7456
7457 $dm = $composer->getDownloadManager();
7458 $im = $composer->getInstallationManager();
7459
7460
7461  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::PRE_STATUS_CMD, true);
7462
7463 $errors = array();
7464 $io = $this->getIO();
7465 $unpushedChanges = array();
7466 $vcsVersionChanges = array();
7467
7468 $parser = new VersionParser;
7469 $guesser = new VersionGuesser($composer->getConfig(), new ProcessExecutor($io), $parser);
7470 $dumper = new ArrayDumper;
7471
7472
7473  foreach ($installedRepo->getCanonicalPackages() as $package) {
7474 $downloader = $dm->getDownloaderForInstalledPackage($package);
7475 $targetDir = $im->getInstallPath($package);
7476
7477 if ($downloader instanceof ChangeReportInterface) {
7478 if (is_link($targetDir)) {
7479 $errors[$targetDir] = $targetDir . ' is a symbolic link.';
7480 }
7481
7482 if ($changes = $downloader->getLocalChanges($package, $targetDir)) {
7483 $errors[$targetDir] = $changes;
7484 }
7485 }
7486
7487 if ($downloader instanceof VcsCapableDownloaderInterface) {
7488 if ($currentRef = $downloader->getVcsReference($package, $targetDir)) {
7489 switch ($package->getInstallationSource()) {
7490 case 'source':
7491 $previousRef = $package->getSourceReference();
7492 break;
7493 case 'dist':
7494 $previousRef = $package->getDistReference();
7495 break;
7496 default:
7497 $previousRef = null;
7498 }
7499
7500 $currentVersion = $guesser->guessVersion($dumper->dump($package), $targetDir);
7501
7502 if ($previousRef && $currentVersion && $currentVersion['commit'] !== $previousRef) {
7503 $vcsVersionChanges[$targetDir] = array(
7504 'previous' => array(
7505 'version' => $package->getPrettyVersion(),
7506 'ref' => $previousRef,
7507 ),
7508 'current' => array(
7509 'version' => $currentVersion['pretty_version'],
7510 'ref' => $currentVersion['commit'],
7511 ),
7512 );
7513 }
7514 }
7515 }
7516
7517 if ($downloader instanceof DvcsDownloaderInterface) {
7518 if ($unpushed = $downloader->getUnpushedChanges($package, $targetDir)) {
7519 $unpushedChanges[$targetDir] = $unpushed;
7520 }
7521 }
7522 }
7523
7524
7525  if (!$errors && !$unpushedChanges && !$vcsVersionChanges) {
7526 $io->writeError('<info>No local changes</info>');
7527
7528 return 0;
7529 }
7530
7531 if ($errors) {
7532 $io->writeError('<error>You have changes in the following dependencies:</error>');
7533
7534 foreach ($errors as $path => $changes) {
7535 if ($input->getOption('verbose')) {
7536 $indentedChanges = implode("\n", array_map(function ($line) {
7537 return '    ' . ltrim($line);
7538 }, explode("\n", $changes)));
7539 $io->write('<info>'.$path.'</info>:');
7540 $io->write($indentedChanges);
7541 } else {
7542 $io->write($path);
7543 }
7544 }
7545 }
7546
7547 if ($unpushedChanges) {
7548 $io->writeError('<warning>You have unpushed changes on the current branch in the following dependencies:</warning>');
7549
7550 foreach ($unpushedChanges as $path => $changes) {
7551 if ($input->getOption('verbose')) {
7552 $indentedChanges = implode("\n", array_map(function ($line) {
7553 return '    ' . ltrim($line);
7554 }, explode("\n", $changes)));
7555 $io->write('<info>'.$path.'</info>:');
7556 $io->write($indentedChanges);
7557 } else {
7558 $io->write($path);
7559 }
7560 }
7561 }
7562
7563 if ($vcsVersionChanges) {
7564 $io->writeError('<warning>You have version variations in the following dependencies:</warning>');
7565
7566 foreach ($vcsVersionChanges as $path => $changes) {
7567 if ($input->getOption('verbose')) {
7568
7569  $currentVersion = $changes['current']['version'] ?: $changes['current']['ref'];
7570 $previousVersion = $changes['previous']['version'] ?: $changes['previous']['ref'];
7571
7572 if ($io->isVeryVerbose()) {
7573
7574  $currentVersion .= sprintf(' (%s)', $changes['current']['ref']);
7575 $previousVersion .= sprintf(' (%s)', $changes['previous']['ref']);
7576 }
7577
7578 $io->write('<info>'.$path.'</info>:');
7579 $io->write(sprintf('    From <comment>%s</comment> to <comment>%s</comment>', $previousVersion, $currentVersion));
7580 } else {
7581 $io->write($path);
7582 }
7583 }
7584 }
7585
7586 if (($errors || $unpushedChanges || $vcsVersionChanges) && !$input->getOption('verbose')) {
7587 $io->writeError('Use --verbose (-v) to see a list of files');
7588 }
7589
7590
7591  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_STATUS_CMD, true);
7592
7593 return ($errors ? self::EXIT_CODE_ERRORS : 0) + ($unpushedChanges ? self::EXIT_CODE_UNPUSHED_CHANGES : 0) + ($vcsVersionChanges ? self::EXIT_CODE_VERSION_CHANGES : 0);
7594 }
7595 }
7596 <?php
7597
7598
7599
7600
7601
7602
7603
7604
7605
7606
7607
7608 namespace Composer\Command;
7609
7610 use Composer\Repository\PlatformRepository;
7611 use Symfony\Component\Console\Input\InputArgument;
7612 use Symfony\Component\Console\Input\InputInterface;
7613 use Symfony\Component\Console\Input\InputOption;
7614 use Symfony\Component\Console\Output\OutputInterface;
7615
7616 class SuggestsCommand extends BaseCommand
7617 {
7618 protected function configure()
7619 {
7620 $this
7621 ->setName('suggests')
7622 ->setDescription('Shows package suggestions.')
7623 ->setDefinition(array(
7624 new InputOption('by-package', null, InputOption::VALUE_NONE, 'Groups output by suggesting package'),
7625 new InputOption('by-suggestion', null, InputOption::VALUE_NONE, 'Groups output by suggested package'),
7626 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Exclude suggestions from require-dev packages'),
7627 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that you want to list suggestions from.'),
7628 ))
7629 ->setHelp(<<<EOT
7630
7631 The <info>%command.name%</info> command shows a sorted list of suggested packages.
7632
7633 Enabling <info>-v</info> implies <info>--by-package --by-suggestion</info>, showing both lists.
7634
7635 EOT
7636 )
7637 ;
7638 }
7639
7640 protected function execute(InputInterface $input, OutputInterface $output)
7641 {
7642 $lock = $this->getComposer()->getLocker()->getLockData();
7643
7644 if (empty($lock)) {
7645 throw new \RuntimeException('Lockfile seems to be empty?');
7646 }
7647
7648 $packages = $lock['packages'];
7649
7650 if (!$input->getOption('no-dev')) {
7651 $packages += $lock['packages-dev'];
7652 }
7653
7654 $filter = $input->getArgument('packages');
7655
7656
7657  $installed = array();
7658 foreach ($packages as $package) {
7659 $installed[] = $package['name'];
7660
7661 if (!empty($package['provide'])) {
7662 $installed = array_merge($installed, array_keys($package['provide']));
7663 }
7664
7665 if (!empty($package['replace'])) {
7666 $installed = array_merge($installed, array_keys($package['replace']));
7667 }
7668 }
7669
7670
7671  $installed = array_flip($installed);
7672 ksort($installed);
7673
7674
7675  $platform = new PlatformRepository(array(), $this->getComposer()->getConfig()->get('platform') ?: array());
7676
7677
7678  $suggesters = array();
7679 $suggested = array();
7680 foreach ($packages as $package) {
7681 $packageName = $package['name'];
7682 if ((!empty($filter) && !in_array($packageName, $filter)) || empty($package['suggest'])) {
7683 continue;
7684 }
7685 foreach ($package['suggest'] as $suggestion => $reason) {
7686 if (false === strpos('/', $suggestion) && !is_null($platform->findPackage($suggestion, '*'))) {
7687 continue;
7688 }
7689 if (!isset($installed[$suggestion])) {
7690 $suggesters[$packageName][$suggestion] = $reason;
7691 $suggested[$suggestion][$packageName] = $reason;
7692 }
7693 }
7694 }
7695 ksort($suggesters);
7696 ksort($suggested);
7697
7698
7699  $mode = 0;
7700 $io = $this->getIO();
7701 if ($input->getOption('by-package') || $io->isVerbose()) {
7702 $mode |= 1;
7703 }
7704 if ($input->getOption('by-suggestion')) {
7705 $mode |= 2;
7706 }
7707
7708
7709  if ($mode === 0) {
7710 foreach (array_keys($suggested) as $suggestion) {
7711 $io->write(sprintf('<info>%s</info>', $suggestion));
7712 }
7713
7714 return;
7715 }
7716
7717
7718  if ($mode & 1) {
7719 foreach ($suggesters as $suggester => $suggestions) {
7720 $io->write(sprintf('<comment>%s</comment> suggests:', $suggester));
7721
7722 foreach ($suggestions as $suggestion => $reason) {
7723 $io->write(sprintf(' - <info>%s</info>: %s', $suggestion, $reason ?: '*'));
7724 }
7725 $io->write('');
7726 }
7727 }
7728
7729
7730  if ($mode & 2) {
7731
7732  if ($mode & 1) {
7733 $io->write(str_repeat('-', 78));
7734 }
7735 foreach ($suggested as $suggestion => $suggesters) {
7736 $io->write(sprintf('<comment>%s</comment> is suggested by:', $suggestion));
7737
7738 foreach ($suggesters as $suggester => $reason) {
7739 $io->write(sprintf(' - <info>%s</info>: %s', $suggester, $reason ?: '*'));
7740 }
7741 $io->write('');
7742 }
7743 }
7744 }
7745 }
7746 <?php
7747
7748
7749
7750
7751
7752
7753
7754
7755
7756
7757
7758 namespace Composer\Command;
7759
7760 use Composer\Composer;
7761 use Composer\Installer;
7762 use Composer\IO\IOInterface;
7763 use Composer\Plugin\CommandEvent;
7764 use Composer\Plugin\PluginEvents;
7765 use Symfony\Component\Console\Helper\Table;
7766 use Symfony\Component\Console\Input\InputInterface;
7767 use Symfony\Component\Console\Input\InputOption;
7768 use Symfony\Component\Console\Input\InputArgument;
7769 use Symfony\Component\Console\Output\OutputInterface;
7770 use Symfony\Component\Console\Question\Question;
7771
7772
7773
7774
7775
7776 class UpdateCommand extends BaseCommand
7777 {
7778 protected function configure()
7779 {
7780 $this
7781 ->setName('update')
7782 ->setAliases(array('upgrade'))
7783 ->setDescription('Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.')
7784 ->setDefinition(array(
7785 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that should be updated, if not provided all packages are.'),
7786 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
7787 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
7788 new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
7789 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
7790 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
7791 new InputOption('lock', null, InputOption::VALUE_NONE, 'Only updates the lock file hash to suppress warning about the lock file being out of date.'),
7792 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
7793 new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
7794 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
7795 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
7796 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
7797 new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Add also all dependencies of whitelisted packages to the whitelist.'),
7798 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
7799 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump.'),
7800 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
7801 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
7802 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
7803 new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
7804 new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
7805 new InputOption('interactive', 'i', InputOption::VALUE_NONE, 'Interactive interface with autocompletion to select the packages to update.'),
7806 new InputOption('root-reqs', null, InputOption::VALUE_NONE, 'Restricts the update to your first degree dependencies.'),
7807 ))
7808 ->setHelp(<<<EOT
7809 The <info>update</info> command reads the composer.json file from the
7810 current directory, processes it, and updates, removes or installs all the
7811 dependencies.
7812
7813 <info>php composer.phar update</info>
7814
7815 To limit the update operation to a few packages, you can list the package(s)
7816 you want to update as such:
7817
7818 <info>php composer.phar update vendor/package1 foo/mypackage [...]</info>
7819
7820 You may also use an asterisk (*) pattern to limit the update operation to package(s)
7821 from a specific vendor:
7822
7823 <info>php composer.phar update vendor/package1 foo/* [...]</info>
7824
7825 To select packages names interactively with auto-completion use <info>-i</info>.
7826
7827 EOT
7828 )
7829 ;
7830 }
7831
7832 protected function execute(InputInterface $input, OutputInterface $output)
7833 {
7834 $io = $this->getIO();
7835 if ($input->getOption('no-custom-installers')) {
7836 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
7837 $input->setOption('no-plugins', true);
7838 }
7839
7840 if ($input->getOption('dev')) {
7841 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
7842 }
7843
7844 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
7845
7846 $packages = $input->getArgument('packages');
7847
7848 if ($input->getOption('interactive')) {
7849 $packages = $this->getPackagesInteractively($io, $input, $output, $composer, $packages);
7850 }
7851
7852 if ($input->getOption('root-reqs')) {
7853 $require = array_keys($composer->getPackage()->getRequires());
7854 if (!$input->getOption('no-dev')) {
7855 $requireDev = array_keys($composer->getPackage()->getDevRequires());
7856 $require = array_merge($require, $requireDev);
7857 }
7858
7859 if (!empty($packages)) {
7860 $packages = array_intersect($packages, $require);
7861 } else {
7862 $packages = $require;
7863 }
7864 }
7865
7866 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
7867
7868 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'update', $input, $output);
7869 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
7870
7871 $install = Installer::create($io, $composer);
7872
7873 $config = $composer->getConfig();
7874 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
7875
7876 $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
7877 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
7878 $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
7879
7880 $install
7881 ->setDryRun($input->getOption('dry-run'))
7882 ->setVerbose($input->getOption('verbose'))
7883 ->setPreferSource($preferSource)
7884 ->setPreferDist($preferDist)
7885 ->setDevMode(!$input->getOption('no-dev'))
7886 ->setDumpAutoloader(!$input->getOption('no-autoloader'))
7887 ->setRunScripts(!$input->getOption('no-scripts'))
7888 ->setSkipSuggest($input->getOption('no-suggest'))
7889 ->setOptimizeAutoloader($optimize)
7890 ->setClassMapAuthoritative($authoritative)
7891 ->setApcuAutoloader($apcu)
7892 ->setUpdate(true)
7893 ->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $packages)
7894 ->setWhitelistDependencies($input->getOption('with-dependencies'))
7895 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
7896 ->setPreferStable($input->getOption('prefer-stable'))
7897 ->setPreferLowest($input->getOption('prefer-lowest'))
7898 ;
7899
7900 if ($input->getOption('no-plugins')) {
7901 $install->disablePlugins();
7902 }
7903
7904 return $install->run();
7905 }
7906
7907 private function getPackagesInteractively(IOInterface $io, InputInterface $input, OutputInterface $output, Composer $composer, array $packages)
7908 {
7909 if (!$input->isInteractive()) {
7910 throw new \InvalidArgumentException('--interactive cannot be used in non-interactive terminals.');
7911 }
7912
7913 $requires = array_merge(
7914 $composer->getPackage()->getRequires(),
7915 $composer->getPackage()->getDevRequires()
7916 );
7917 $autocompleterValues = array();
7918 foreach ($requires as $require) {
7919 $autocompleterValues[strtolower($require->getTarget())] = $require->getTarget();
7920 }
7921
7922 $installedPackages = $composer->getRepositoryManager()->getLocalRepository()->getPackages();
7923 foreach ($installedPackages as $package) {
7924 $autocompleterValues[$package->getName()] = $package->getPrettyName();
7925 }
7926
7927 $helper = $this->getHelper('question');
7928 $question = new Question('<comment>Enter package name: </comment>', null);
7929
7930 $io->writeError('<info>Press enter without value to end submission</info>');
7931
7932 do {
7933 $autocompleterValues = array_diff($autocompleterValues, $packages);
7934 $question->setAutocompleterValues($autocompleterValues);
7935 $addedPackage = $helper->ask($input, $output, $question);
7936
7937 if (!is_string($addedPackage) || empty($addedPackage)) {
7938 break;
7939 }
7940
7941 $addedPackage = strtolower($addedPackage);
7942 if (!in_array($addedPackage, $packages)) {
7943 $packages[] = $addedPackage;
7944 }
7945 } while (true);
7946
7947 $packages = array_filter($packages);
7948 if (!$packages) {
7949 throw new \InvalidArgumentException('You must enter minimum one package.');
7950 }
7951
7952 $table = new Table($output);
7953 $table->setHeaders(array('Selected packages'));
7954 foreach ($packages as $package) {
7955 $table->addRow(array($package));
7956 }
7957 $table->render();
7958
7959 if ($io->askConfirmation(sprintf(
7960 'Would you like to continue and update the above package%s [<comment>yes</comment>]? ',
7961 1 === count($packages) ? '' : 's'
7962 ), true)) {
7963 return $packages;
7964 }
7965
7966 throw new \RuntimeException('Installation aborted.');
7967 }
7968 }
7969 <?php
7970
7971
7972
7973
7974
7975
7976
7977
7978
7979
7980
7981 namespace Composer\Command;
7982
7983 use Composer\Factory;
7984 use Composer\Package\Loader\ValidatingArrayLoader;
7985 use Composer\Plugin\CommandEvent;
7986 use Composer\Plugin\PluginEvents;
7987 use Composer\Util\ConfigValidator;
7988 use Symfony\Component\Console\Input\InputArgument;
7989 use Symfony\Component\Console\Input\InputInterface;
7990 use Symfony\Component\Console\Input\InputOption;
7991 use Symfony\Component\Console\Output\OutputInterface;
7992
7993
7994
7995
7996
7997
7998
7999 class ValidateCommand extends BaseCommand
8000 {
8001
8002
8003
8004 protected function configure()
8005 {
8006 $this
8007 ->setName('validate')
8008 ->setDescription('Validates a composer.json and composer.lock.')
8009 ->setDefinition(array(
8010 new InputOption('no-check-all', null, InputOption::VALUE_NONE, 'Do not make a complete validation'),
8011 new InputOption('no-check-lock', null, InputOption::VALUE_NONE, 'Do not check if lock file is up to date'),
8012 new InputOption('no-check-publish', null, InputOption::VALUE_NONE, 'Do not check for publish errors'),
8013 new InputOption('with-dependencies', 'A', InputOption::VALUE_NONE, 'Also validate the composer.json of all installed dependencies'),
8014 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code for warnings as well as errors'),
8015 new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file', './composer.json'),
8016 ))
8017 ->setHelp(<<<EOT
8018 The validate command validates a given composer.json and composer.lock
8019
8020 Exit codes in case of errors are:
8021 1 validation warning(s), only when --strict is given
8022 2 validation error(s)
8023 3 file unreadable or missing
8024
8025 EOT
8026 );
8027 }
8028
8029
8030
8031
8032
8033
8034
8035 protected function execute(InputInterface $input, OutputInterface $output)
8036 {
8037 $file = $input->getArgument('file');
8038 $io = $this->getIO();
8039
8040 if (!file_exists($file)) {
8041 $io->writeError('<error>' . $file . ' not found.</error>');
8042
8043 return 3;
8044 }
8045 if (!is_readable($file)) {
8046 $io->writeError('<error>' . $file . ' is not readable.</error>');
8047
8048 return 3;
8049 }
8050
8051 $validator = new ConfigValidator($io);
8052 $checkAll = $input->getOption('no-check-all') ? 0 : ValidatingArrayLoader::CHECK_ALL;
8053 $checkPublish = !$input->getOption('no-check-publish');
8054 $checkLock = !$input->getOption('no-check-lock');
8055 $isStrict = $input->getOption('strict');
8056 list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
8057
8058 $lockErrors = array();
8059 $composer = Factory::create($io, $file);
8060 $locker = $composer->getLocker();
8061 if ($locker->isLocked() && !$locker->isFresh()) {
8062 $lockErrors[] = 'The lock file is not up to date with the latest changes in composer.json, it is recommended that you run `composer update`.';
8063 }
8064
8065 $this->outputResult($io, $file, $errors, $warnings, $checkPublish, $publishErrors, $checkLock, $lockErrors, true);
8066
8067 $exitCode = $errors || ($publishErrors && $checkPublish) || ($lockErrors && $checkLock) ? 2 : ($isStrict && $warnings ? 1 : 0);
8068
8069 if ($input->getOption('with-dependencies')) {
8070 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
8071 foreach ($localRepo->getPackages() as $package) {
8072 $path = $composer->getInstallationManager()->getInstallPath($package);
8073 $file = $path . '/composer.json';
8074 if (is_dir($path) && file_exists($file)) {
8075 list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
8076 $this->outputResult($io, $package->getPrettyName(), $errors, $warnings, $checkPublish, $publishErrors);
8077
8078 $depCode = $errors || ($publishErrors && $checkPublish) ? 2 : ($isStrict && $warnings ? 1 : 0);
8079 $exitCode = max($depCode, $exitCode);
8080 }
8081 }
8082 }
8083
8084 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'validate', $input, $output);
8085 $eventCode = $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
8086 $exitCode = max($eventCode, $exitCode);
8087
8088 return $exitCode;
8089 }
8090
8091 private function outputResult($io, $name, &$errors, &$warnings, $checkPublish = false, $publishErrors = array(), $checkLock = false, $lockErrors = array(), $printSchemaUrl = false)
8092 {
8093 if (!$errors && !$publishErrors && !$warnings) {
8094 $io->write('<info>' . $name . ' is valid</info>');
8095 } elseif (!$errors && !$publishErrors) {
8096 $io->writeError('<info>' . $name . ' is valid, but with a few warnings</info>');
8097 if ($printSchemaUrl) {
8098 $io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
8099 }
8100 } elseif (!$errors) {
8101 $io->writeError('<info>' . $name . ' is valid for simple usage with composer but has</info>');
8102 $io->writeError('<info>strict errors that make it unable to be published as a package:</info>');
8103 if ($printSchemaUrl) {
8104 $io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
8105 }
8106 } else {
8107 $io->writeError('<error>' . $name . ' is invalid, the following errors/warnings were found:</error>');
8108 }
8109
8110
8111  if ($checkPublish) {
8112 $errors = array_merge($errors, $publishErrors);
8113 } else {
8114 $warnings = array_merge($warnings, $publishErrors);
8115 }
8116
8117
8118  if ($checkLock) {
8119 $errors = array_merge($errors, $lockErrors);
8120 } else {
8121 $warnings = array_merge($warnings, $lockErrors);
8122 }
8123
8124 $messages = array(
8125 'error' => $errors,
8126 'warning' => $warnings,
8127 );
8128
8129 foreach ($messages as $style => $msgs) {
8130 foreach ($msgs as $msg) {
8131 $io->writeError('<' . $style . '>' . $msg . '</' . $style . '>');
8132 }
8133 }
8134 }
8135 }
8136 <?php
8137
8138
8139
8140
8141
8142
8143
8144
8145
8146
8147
8148 namespace Composer;
8149
8150 use Composer\Package\RootPackageInterface;
8151 use Composer\Package\Locker;
8152 use Composer\Repository\RepositoryManager;
8153 use Composer\Installer\InstallationManager;
8154 use Composer\Plugin\PluginManager;
8155 use Composer\Downloader\DownloadManager;
8156 use Composer\EventDispatcher\EventDispatcher;
8157 use Composer\Autoload\AutoloadGenerator;
8158 use Composer\Package\Archiver\ArchiveManager;
8159
8160
8161
8162
8163
8164
8165 class Composer
8166 {
8167 const VERSION = '1.5.5';
8168 const BRANCH_ALIAS_VERSION = '';
8169 const RELEASE_DATE = '2017-12-01 14:42:57';
8170
8171
8172
8173
8174 private $package;
8175
8176
8177
8178
8179 private $locker;
8180
8181
8182
8183
8184 private $repositoryManager;
8185
8186
8187
8188
8189 private $downloadManager;
8190
8191
8192
8193
8194 private $installationManager;
8195
8196
8197
8198
8199 private $pluginManager;
8200
8201
8202
8203
8204 private $config;
8205
8206
8207
8208
8209 private $eventDispatcher;
8210
8211
8212
8213
8214 private $autoloadGenerator;
8215
8216
8217
8218
8219 private $archiveManager;
8220
8221
8222
8223
8224
8225 public function setPackage(RootPackageInterface $package)
8226 {
8227 $this->package = $package;
8228 }
8229
8230
8231
8232
8233 public function getPackage()
8234 {
8235 return $this->package;
8236 }
8237
8238
8239
8240
8241 public function setConfig(Config $config)
8242 {
8243 $this->config = $config;
8244 }
8245
8246
8247
8248
8249 public function getConfig()
8250 {
8251 return $this->config;
8252 }
8253
8254
8255
8256
8257 public function setLocker(Locker $locker)
8258 {
8259 $this->locker = $locker;
8260 }
8261
8262
8263
8264
8265 public function getLocker()
8266 {
8267 return $this->locker;
8268 }
8269
8270
8271
8272
8273 public function setRepositoryManager(RepositoryManager $manager)
8274 {
8275 $this->repositoryManager = $manager;
8276 }
8277
8278
8279
8280
8281 public function getRepositoryManager()
8282 {
8283 return $this->repositoryManager;
8284 }
8285
8286
8287
8288
8289 public function setDownloadManager(DownloadManager $manager)
8290 {
8291 $this->downloadManager = $manager;
8292 }
8293
8294
8295
8296
8297 public function getDownloadManager()
8298 {
8299 return $this->downloadManager;
8300 }
8301
8302
8303
8304
8305 public function setArchiveManager(ArchiveManager $manager)
8306 {
8307 $this->archiveManager = $manager;
8308 }
8309
8310
8311
8312
8313 public function getArchiveManager()
8314 {
8315 return $this->archiveManager;
8316 }
8317
8318
8319
8320
8321 public function setInstallationManager(InstallationManager $manager)
8322 {
8323 $this->installationManager = $manager;
8324 }
8325
8326
8327
8328
8329 public function getInstallationManager()
8330 {
8331 return $this->installationManager;
8332 }
8333
8334
8335
8336
8337 public function setPluginManager(PluginManager $manager)
8338 {
8339 $this->pluginManager = $manager;
8340 }
8341
8342
8343
8344
8345 public function getPluginManager()
8346 {
8347 return $this->pluginManager;
8348 }
8349
8350
8351
8352
8353 public function setEventDispatcher(EventDispatcher $eventDispatcher)
8354 {
8355 $this->eventDispatcher = $eventDispatcher;
8356 }
8357
8358
8359
8360
8361 public function getEventDispatcher()
8362 {
8363 return $this->eventDispatcher;
8364 }
8365
8366
8367
8368
8369 public function setAutoloadGenerator(AutoloadGenerator $autoloadGenerator)
8370 {
8371 $this->autoloadGenerator = $autoloadGenerator;
8372 }
8373
8374
8375
8376
8377 public function getAutoloadGenerator()
8378 {
8379 return $this->autoloadGenerator;
8380 }
8381 }
8382 <?php
8383
8384
8385
8386
8387
8388
8389
8390
8391
8392
8393
8394 namespace Composer;
8395
8396 use Composer\Config\ConfigSourceInterface;
8397 use Composer\Downloader\TransportException;
8398 use Composer\IO\IOInterface;
8399 use Composer\Util\Platform;
8400
8401
8402
8403
8404 class Config
8405 {
8406 const RELATIVE_PATHS = 1;
8407
8408 public static $defaultConfig = array(
8409 'process-timeout' => 300,
8410 'use-include-path' => false,
8411 'preferred-install' => 'auto',
8412 'notify-on-install' => true,
8413 'github-protocols' => array('https', 'ssh', 'git'),
8414 'vendor-dir' => 'vendor',
8415 'bin-dir' => '{$vendor-dir}/bin',
8416 'cache-dir' => '{$home}/cache',
8417 'data-dir' => '{$home}',
8418 'cache-files-dir' => '{$cache-dir}/files',
8419 'cache-repo-dir' => '{$cache-dir}/repo',
8420 'cache-vcs-dir' => '{$cache-dir}/vcs',
8421 'cache-ttl' => 15552000, 
8422  'cache-files-ttl' => null, 
8423  'cache-files-maxsize' => '300MiB',
8424 'bin-compat' => 'auto',
8425 'discard-changes' => false,
8426 'autoloader-suffix' => null,
8427 'sort-packages' => false,
8428 'optimize-autoloader' => false,
8429 'classmap-authoritative' => false,
8430 'apcu-autoloader' => false,
8431 'prepend-autoloader' => true,
8432 'github-domains' => array('github.com'),
8433 'bitbucket-expose-hostname' => true,
8434 'disable-tls' => false,
8435 'secure-http' => true,
8436 'cafile' => null,
8437 'capath' => null,
8438 'github-expose-hostname' => true,
8439 'gitlab-domains' => array('gitlab.com'),
8440 'store-auths' => 'prompt',
8441 'platform' => array(),
8442 'archive-format' => 'tar',
8443 'archive-dir' => '.',
8444 'htaccess-protect' => true,
8445
8446  
8447  
8448  
8449  
8450  
8451  );
8452
8453 public static $defaultRepositories = array(
8454 'packagist.org' => array(
8455 'type' => 'composer',
8456 'url' => 'https?://packagist.org',
8457 'allow_ssl_downgrade' => true,
8458 ),
8459 );
8460
8461 private $config;
8462 private $baseDir;
8463 private $repositories;
8464
8465 private $configSource;
8466
8467 private $authConfigSource;
8468 private $useEnvironment;
8469 private $warnedHosts = array();
8470
8471
8472
8473
8474
8475 public function __construct($useEnvironment = true, $baseDir = null)
8476 {
8477
8478  $this->config = static::$defaultConfig;
8479 $this->repositories = static::$defaultRepositories;
8480 $this->useEnvironment = (bool) $useEnvironment;
8481 $this->baseDir = $baseDir;
8482 }
8483
8484 public function setConfigSource(ConfigSourceInterface $source)
8485 {
8486 $this->configSource = $source;
8487 }
8488
8489 public function getConfigSource()
8490 {
8491 return $this->configSource;
8492 }
8493
8494 public function setAuthConfigSource(ConfigSourceInterface $source)
8495 {
8496 $this->authConfigSource = $source;
8497 }
8498
8499 public function getAuthConfigSource()
8500 {
8501 return $this->authConfigSource;
8502 }
8503
8504
8505
8506
8507
8508
8509 public function merge($config)
8510 {
8511
8512  if (!empty($config['config']) && is_array($config['config'])) {
8513 foreach ($config['config'] as $key => $val) {
8514 if (in_array($key, array('bitbucket-oauth', 'github-oauth', 'gitlab-oauth', 'gitlab-token', 'http-basic')) && isset($this->config[$key])) {
8515 $this->config[$key] = array_merge($this->config[$key], $val);
8516 } elseif ('preferred-install' === $key && isset($this->config[$key])) {
8517 if (is_array($val) || is_array($this->config[$key])) {
8518 if (is_string($val)) {
8519 $val = array('*' => $val);
8520 }
8521 if (is_string($this->config[$key])) {
8522 $this->config[$key] = array('*' => $this->config[$key]);
8523 }
8524 $this->config[$key] = array_merge($this->config[$key], $val);
8525
8526  if (isset($this->config[$key]['*'])) {
8527 $wildcard = $this->config[$key]['*'];
8528 unset($this->config[$key]['*']);
8529 $this->config[$key]['*'] = $wildcard;
8530 }
8531 } else {
8532 $this->config[$key] = $val;
8533 }
8534 } else {
8535 $this->config[$key] = $val;
8536 }
8537 }
8538 }
8539
8540 if (!empty($config['repositories']) && is_array($config['repositories'])) {
8541 $this->repositories = array_reverse($this->repositories, true);
8542 $newRepos = array_reverse($config['repositories'], true);
8543 foreach ($newRepos as $name => $repository) {
8544
8545  if (false === $repository) {
8546 $this->disableRepoByName($name);
8547 continue;
8548 }
8549
8550
8551  if (is_array($repository) && 1 === count($repository) && false === current($repository)) {
8552 $this->disableRepoByName(key($repository));
8553 continue;
8554 }
8555
8556
8557  if (is_int($name)) {
8558 $this->repositories[] = $repository;
8559 } else {
8560 if ($name === 'packagist') { 
8561  $this->repositories[$name . '.org'] = $repository;
8562 } else {
8563 $this->repositories[$name] = $repository;
8564 }
8565 }
8566 }
8567 $this->repositories = array_reverse($this->repositories, true);
8568 }
8569 }
8570
8571
8572
8573
8574 public function getRepositories()
8575 {
8576 return $this->repositories;
8577 }
8578
8579
8580
8581
8582
8583
8584
8585
8586
8587 public function get($key, $flags = 0)
8588 {
8589 switch ($key) {
8590 case 'vendor-dir':
8591 case 'bin-dir':
8592 case 'process-timeout':
8593 case 'data-dir':
8594 case 'cache-dir':
8595 case 'cache-files-dir':
8596 case 'cache-repo-dir':
8597 case 'cache-vcs-dir':
8598 case 'cafile':
8599 case 'capath':
8600 case 'htaccess-protect':
8601
8602  $env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_'));
8603
8604 $val = $this->getComposerEnv($env);
8605 $val = rtrim((string) $this->process(false !== $val ? $val : $this->config[$key], $flags), '/\\');
8606 $val = Platform::expandPath($val);
8607
8608 if (substr($key, -4) !== '-dir') {
8609 return $val;
8610 }
8611
8612 return (($flags & self::RELATIVE_PATHS) == self::RELATIVE_PATHS) ? $val : $this->realpath($val);
8613
8614 case 'cache-ttl':
8615 return (int) $this->config[$key];
8616
8617 case 'cache-files-maxsize':
8618 if (!preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $this->config[$key], $matches)) {
8619 throw new \RuntimeException(
8620 "Could not parse the value of 'cache-files-maxsize': {$this->config[$key]}"
8621 );
8622 }
8623 $size = $matches[1];
8624 if (isset($matches[2])) {
8625 switch (strtolower($matches[2])) {
8626 case 'g':
8627 $size *= 1024;
8628
8629  case 'm':
8630 $size *= 1024;
8631
8632  case 'k':
8633 $size *= 1024;
8634 break;
8635 }
8636 }
8637
8638 return $size;
8639
8640 case 'cache-files-ttl':
8641 if (isset($this->config[$key])) {
8642 return (int) $this->config[$key];
8643 }
8644
8645 return (int) $this->config['cache-ttl'];
8646
8647 case 'home':
8648 $val = preg_replace('#^(\$HOME|~)(/|$)#', rtrim(getenv('HOME') ?: getenv('USERPROFILE'), '/\\') . '/', $this->config[$key]);
8649
8650 return rtrim($this->process($val, $flags), '/\\');
8651
8652 case 'bin-compat':
8653 $value = $this->getComposerEnv('COMPOSER_BIN_COMPAT') ?: $this->config[$key];
8654
8655 if (!in_array($value, array('auto', 'full'))) {
8656 throw new \RuntimeException(
8657 "Invalid value for 'bin-compat': {$value}. Expected auto, full"
8658 );
8659 }
8660
8661 return $value;
8662
8663 case 'discard-changes':
8664 if ($env = $this->getComposerEnv('COMPOSER_DISCARD_CHANGES')) {
8665 if (!in_array($env, array('stash', 'true', 'false', '1', '0'), true)) {
8666 throw new \RuntimeException(
8667 "Invalid value for COMPOSER_DISCARD_CHANGES: {$env}. Expected 1, 0, true, false or stash"
8668 );
8669 }
8670 if ('stash' === $env) {
8671 return 'stash';
8672 }
8673
8674
8675  return $env !== 'false' && (bool) $env;
8676 }
8677
8678 if (!in_array($this->config[$key], array(true, false, 'stash'), true)) {
8679 throw new \RuntimeException(
8680 "Invalid value for 'discard-changes': {$this->config[$key]}. Expected true, false or stash"
8681 );
8682 }
8683
8684 return $this->config[$key];
8685
8686 case 'github-protocols':
8687 $protos = $this->config['github-protocols'];
8688 if ($this->config['secure-http'] && false !== ($index = array_search('git', $protos))) {
8689 unset($protos[$index]);
8690 }
8691 if (reset($protos) === 'http') {
8692 throw new \RuntimeException('The http protocol for github is not available anymore, update your config\'s github-protocols to use "https", "git" or "ssh"');
8693 }
8694
8695 return $protos;
8696
8697 case 'disable-tls':
8698 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
8699
8700 case 'secure-http':
8701 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
8702
8703 default:
8704 if (!isset($this->config[$key])) {
8705 return null;
8706 }
8707
8708 return $this->process($this->config[$key], $flags);
8709 }
8710 }
8711
8712 public function all($flags = 0)
8713 {
8714 $all = array(
8715 'repositories' => $this->getRepositories(),
8716 );
8717 foreach (array_keys($this->config) as $key) {
8718 $all['config'][$key] = $this->get($key, $flags);
8719 }
8720
8721 return $all;
8722 }
8723
8724 public function raw()
8725 {
8726 return array(
8727 'repositories' => $this->getRepositories(),
8728 'config' => $this->config,
8729 );
8730 }
8731
8732
8733
8734
8735
8736
8737
8738 public function has($key)
8739 {
8740 return array_key_exists($key, $this->config);
8741 }
8742
8743
8744
8745
8746
8747
8748
8749
8750 private function process($value, $flags)
8751 {
8752 $config = $this;
8753
8754 if (!is_string($value)) {
8755 return $value;
8756 }
8757
8758 return preg_replace_callback('#\{\$(.+)\}#', function ($match) use ($config, $flags) {
8759 return $config->get($match[1], $flags);
8760 }, $value);
8761 }
8762
8763
8764
8765
8766
8767
8768
8769
8770
8771 private function realpath($path)
8772 {
8773 if (preg_match('{^(?:/|[a-z]:|[a-z0-9.]+://)}i', $path)) {
8774 return $path;
8775 }
8776
8777 return $this->baseDir . '/' . $path;
8778 }
8779
8780
8781
8782
8783
8784
8785
8786
8787
8788
8789 private function getComposerEnv($var)
8790 {
8791 if ($this->useEnvironment) {
8792 return getenv($var);
8793 }
8794
8795 return false;
8796 }
8797
8798 private function disableRepoByName($name)
8799 {
8800 if (isset($this->repositories[$name])) {
8801 unset($this->repositories[$name]);
8802 } elseif ($name === 'packagist') { 
8803  unset($this->repositories['packagist.org']);
8804 }
8805 }
8806
8807
8808
8809
8810
8811
8812
8813 public function prohibitUrlByConfig($url, IOInterface $io = null)
8814 {
8815
8816  if (false === filter_var($url, FILTER_VALIDATE_URL)) {
8817 return;
8818 }
8819
8820
8821  $scheme = parse_url($url, PHP_URL_SCHEME);
8822 if (in_array($scheme, array('http', 'git', 'ftp', 'svn'))) {
8823 if ($this->get('secure-http')) {
8824 throw new TransportException("Your configuration does not allow connections to $url. See https://getcomposer.org/doc/06-config.md#secure-http for details.");
8825 } elseif ($io) {
8826 $host = parse_url($url, PHP_URL_HOST);
8827 if (!isset($this->warnedHosts[$host])) {
8828 $io->writeError("<warning>Warning: Accessing $host over $scheme which is an insecure protocol.</warning>");
8829 }
8830 $this->warnedHosts[$host] = true;
8831 }
8832 }
8833 }
8834 }
8835 <?php
8836
8837
8838
8839
8840
8841
8842
8843
8844
8845
8846
8847 namespace Composer\Config;
8848
8849
8850
8851
8852
8853
8854
8855 interface ConfigSourceInterface
8856 {
8857
8858
8859
8860
8861
8862
8863 public function addRepository($name, $config);
8864
8865
8866
8867
8868
8869
8870 public function removeRepository($name);
8871
8872
8873
8874
8875
8876
8877
8878 public function addConfigSetting($name, $value);
8879
8880
8881
8882
8883
8884
8885 public function removeConfigSetting($name);
8886
8887
8888
8889
8890
8891
8892
8893 public function addProperty($name, $value);
8894
8895
8896
8897
8898
8899
8900 public function removeProperty($name);
8901
8902
8903
8904
8905
8906
8907
8908
8909 public function addLink($type, $name, $value);
8910
8911
8912
8913
8914
8915
8916
8917 public function removeLink($type, $name);
8918
8919
8920
8921
8922
8923
8924 public function getName();
8925 }
8926 <?php
8927
8928
8929
8930
8931
8932
8933
8934
8935
8936
8937
8938 namespace Composer\Config;
8939
8940 use Composer\Json\JsonFile;
8941 use Composer\Json\JsonManipulator;
8942 use Composer\Util\Silencer;
8943
8944
8945
8946
8947
8948
8949
8950 class JsonConfigSource implements ConfigSourceInterface
8951 {
8952
8953
8954
8955 private $file;
8956
8957
8958
8959
8960 private $authConfig;
8961
8962
8963
8964
8965
8966
8967
8968 public function __construct(JsonFile $file, $authConfig = false)
8969 {
8970 $this->file = $file;
8971 $this->authConfig = $authConfig;
8972 }
8973
8974
8975
8976
8977 public function getName()
8978 {
8979 return $this->file->getPath();
8980 }
8981
8982
8983
8984
8985 public function addRepository($name, $config)
8986 {
8987 $this->manipulateJson('addRepository', $name, $config, function (&$config, $repo, $repoConfig) {
8988
8989  
8990  if (isset($config['repositories'])) {
8991 foreach ($config['repositories'] as $index => $val) {
8992 if ($index === $repo) {
8993 continue;
8994 }
8995 if (is_numeric($index) && ($val === array('packagist' => false) || $val === array('packagist.org' => false))) {
8996 unset($config['repositories'][$index]);
8997 $config['repositories']['packagist.org'] = false;
8998 break;
8999 }
9000 }
9001 }
9002
9003 $config['repositories'][$repo] = $repoConfig;
9004 });
9005 }
9006
9007
9008
9009
9010 public function removeRepository($name)
9011 {
9012 $this->manipulateJson('removeRepository', $name, function (&$config, $repo) {
9013 unset($config['repositories'][$repo]);
9014 });
9015 }
9016
9017
9018
9019
9020 public function addConfigSetting($name, $value)
9021 {
9022 $authConfig = $this->authConfig;
9023 $this->manipulateJson('addConfigSetting', $name, $value, function (&$config, $key, $val) use ($authConfig) {
9024 if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|platform)\.}', $key)) {
9025 list($key, $host) = explode('.', $key, 2);
9026 if ($authConfig) {
9027 $config[$key][$host] = $val;
9028 } else {
9029 $config['config'][$key][$host] = $val;
9030 }
9031 } else {
9032 $config['config'][$key] = $val;
9033 }
9034 });
9035 }
9036
9037
9038
9039
9040 public function removeConfigSetting($name)
9041 {
9042 $authConfig = $this->authConfig;
9043 $this->manipulateJson('removeConfigSetting', $name, function (&$config, $key) use ($authConfig) {
9044 if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|platform)\.}', $key)) {
9045 list($key, $host) = explode('.', $key, 2);
9046 if ($authConfig) {
9047 unset($config[$key][$host]);
9048 } else {
9049 unset($config['config'][$key][$host]);
9050 }
9051 } else {
9052 unset($config['config'][$key]);
9053 }
9054 });
9055 }
9056
9057
9058
9059
9060 public function addProperty($name, $value)
9061 {
9062 $this->manipulateJson('addProperty', $name, $value, function (&$config, $key, $val) {
9063 if (substr($key, 0, 6) === 'extra.') {
9064 $bits = explode('.', $key);
9065 $last = array_pop($bits);
9066 $arr = &$config['extra'];
9067 foreach ($bits as $bit) {
9068 if (!isset($arr[$bit])) {
9069 $arr[$bit] = array();
9070 }
9071 $arr = &$arr[$bit];
9072 }
9073 $arr[$last] = $val;
9074 } else {
9075 $config[$key] = $val;
9076 }
9077 });
9078 }
9079
9080
9081
9082
9083 public function removeProperty($name)
9084 {
9085 $authConfig = $this->authConfig;
9086 $this->manipulateJson('removeProperty', $name, function (&$config, $key) {
9087 if (substr($key, 0, 6) === 'extra.') {
9088 $bits = explode('.', $key);
9089 $last = array_pop($bits);
9090 $arr = &$config['extra'];
9091 foreach ($bits as $bit) {
9092 if (!isset($arr[$bit])) {
9093 return;
9094 }
9095 $arr = &$arr[$bit];
9096 }
9097 unset($arr[$last]);
9098 } else {
9099 unset($config[$key]);
9100 }
9101 });
9102 }
9103
9104
9105
9106
9107 public function addLink($type, $name, $value)
9108 {
9109 $this->manipulateJson('addLink', $type, $name, $value, function (&$config, $type, $name, $value) {
9110 $config[$type][$name] = $value;
9111 });
9112 }
9113
9114
9115
9116
9117 public function removeLink($type, $name)
9118 {
9119 $this->manipulateJson('removeSubNode', $type, $name, function (&$config, $type, $name) {
9120 unset($config[$type][$name]);
9121 });
9122 }
9123
9124 protected function manipulateJson($method, $args, $fallback)
9125 {
9126 $args = func_get_args();
9127
9128  array_shift($args);
9129 $fallback = array_pop($args);
9130
9131 if ($this->file->exists()) {
9132 if (!is_writable($this->file->getPath())) {
9133 throw new \RuntimeException(sprintf('The file "%s" is not writable.', $this->file->getPath()));
9134 }
9135
9136 if (!is_readable($this->file->getPath())) {
9137 throw new \RuntimeException(sprintf('The file "%s" is not readable.', $this->file->getPath()));
9138 }
9139
9140 $contents = file_get_contents($this->file->getPath());
9141 } elseif ($this->authConfig) {
9142 $contents = "{\n}\n";
9143 } else {
9144 $contents = "{\n    \"config\": {\n    }\n}\n";
9145 }
9146
9147 $manipulator = new JsonManipulator($contents);
9148
9149 $newFile = !$this->file->exists();
9150
9151
9152  if ($this->authConfig && $method === 'addConfigSetting') {
9153 $method = 'addSubNode';
9154 list($mainNode, $name) = explode('.', $args[0], 2);
9155 $args = array($mainNode, $name, $args[1]);
9156 } elseif ($this->authConfig && $method === 'removeConfigSetting') {
9157 $method = 'removeSubNode';
9158 list($mainNode, $name) = explode('.', $args[0], 2);
9159 $args = array($mainNode, $name);
9160 }
9161
9162
9163  if (call_user_func_array(array($manipulator, $method), $args)) {
9164 file_put_contents($this->file->getPath(), $manipulator->getContents());
9165 } else {
9166
9167  $config = $this->file->read();
9168 $this->arrayUnshiftRef($args, $config);
9169 call_user_func_array($fallback, $args);
9170 $this->file->write($config);
9171 }
9172
9173 if ($newFile) {
9174 Silencer::call('chmod', $this->file->getPath(), 0600);
9175 }
9176 }
9177
9178
9179
9180
9181
9182
9183
9184
9185 private function arrayUnshiftRef(&$array, &$value)
9186 {
9187 $return = array_unshift($array, '');
9188 $array[0] = &$value;
9189
9190 return $return;
9191 }
9192 }
9193 <?php
9194
9195
9196
9197
9198
9199
9200
9201
9202
9203
9204
9205 namespace Composer\Console;
9206
9207 use Composer\Util\Platform;
9208 use Composer\Util\Silencer;
9209 use Symfony\Component\Console\Application as BaseApplication;
9210 use Symfony\Component\Console\Input\InputInterface;
9211 use Symfony\Component\Console\Input\InputOption;
9212 use Symfony\Component\Console\Output\OutputInterface;
9213 use Composer\Command;
9214 use Composer\Composer;
9215 use Composer\Factory;
9216 use Composer\IO\IOInterface;
9217 use Composer\IO\ConsoleIO;
9218 use Composer\Json\JsonValidationException;
9219 use Composer\Util\ErrorHandler;
9220 use Composer\EventDispatcher\ScriptExecutionException;
9221 use Composer\Exception\NoSslException;
9222
9223
9224
9225
9226
9227
9228
9229
9230 class Application extends BaseApplication
9231 {
9232
9233
9234
9235 protected $composer;
9236
9237
9238
9239
9240 protected $io;
9241
9242 private static $logo = '   ______
9243   / ____/___  ____ ___  ____  ____  ________  _____
9244  / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
9245 / /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
9246 \____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
9247                     /_/
9248 ';
9249
9250 private $hasPluginCommands = false;
9251 private $disablePluginsByDefault = false;
9252
9253 public function __construct()
9254 {
9255 static $shutdownRegistered = false;
9256
9257 if (function_exists('ini_set') && extension_loaded('xdebug')) {
9258 ini_set('xdebug.show_exception_trace', false);
9259 ini_set('xdebug.scream', false);
9260 }
9261
9262 if (function_exists('date_default_timezone_set') && function_exists('date_default_timezone_get')) {
9263 date_default_timezone_set(Silencer::call('date_default_timezone_get'));
9264 }
9265
9266 if (!$shutdownRegistered) {
9267 $shutdownRegistered = true;
9268
9269 register_shutdown_function(function () {
9270 $lastError = error_get_last();
9271
9272 if ($lastError && $lastError['message'] &&
9273 (strpos($lastError['message'], 'Allowed memory') !== false  ||
9274 strpos($lastError['message'], 'exceeded memory') !== false )) {
9275 echo "\n". 'Check https://getcomposer.org/doc/articles/troubleshooting.md#memory-limit-errors for more info on how to handle out of memory errors.';
9276 }
9277 });
9278 }
9279
9280 parent::__construct('Composer', Composer::VERSION);
9281 }
9282
9283
9284
9285
9286 public function run(InputInterface $input = null, OutputInterface $output = null)
9287 {
9288 if (null === $output) {
9289 $output = Factory::createOutput();
9290 }
9291
9292 return parent::run($input, $output);
9293 }
9294
9295
9296
9297
9298 public function doRun(InputInterface $input, OutputInterface $output)
9299 {
9300 $this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins');
9301
9302 $io = $this->io = new ConsoleIO($input, $output, $this->getHelperSet());
9303 ErrorHandler::register($io);
9304
9305
9306  if ($newWorkDir = $this->getNewWorkingDir($input)) {
9307 $oldWorkingDir = getcwd();
9308 chdir($newWorkDir);
9309 $io->writeError('Changed CWD to ' . getcwd(), true, IOInterface::DEBUG);
9310 }
9311
9312
9313  $commandName = '';
9314 if ($name = $this->getCommandName($input)) {
9315 try {
9316 $commandName = $this->find($name)->getName();
9317 } catch (\InvalidArgumentException $e) {
9318 }
9319 }
9320
9321
9322  if ($io->isInteractive() && !$newWorkDir && !in_array($commandName, array('', 'list', 'init', 'about', 'help', 'diagnose', 'self-update', 'global', 'create-project'), true) && !file_exists(Factory::getComposerFile())) {
9323 $dir = dirname(getcwd());
9324 $home = realpath(getenv('HOME') ?: getenv('USERPROFILE') ?: '/');
9325
9326
9327  while (dirname($dir) !== $dir && $dir !== $home) {
9328 if (file_exists($dir.'/'.Factory::getComposerFile())) {
9329 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)) {
9330 $oldWorkingDir = getcwd();
9331 chdir($dir);
9332 }
9333 break;
9334 }
9335 $dir = dirname($dir);
9336 }
9337 }
9338
9339 if (!$this->disablePluginsByDefault && !$this->hasPluginCommands && 'global' !== $commandName) {
9340 try {
9341 foreach ($this->getPluginCommands() as $command) {
9342 if ($this->has($command->getName())) {
9343 $io->writeError('<warning>Plugin command '.$command->getName().' ('.get_class($command).') would override a Composer command and has been skipped</warning>');
9344 } else {
9345 $this->add($command);
9346 }
9347 }
9348 } catch (NoSslException $e) {
9349
9350  }
9351
9352 $this->hasPluginCommands = true;
9353 }
9354
9355
9356  $isProxyCommand = false;
9357 if ($name = $this->getCommandName($input)) {
9358 try {
9359 $command = $this->find($name);
9360 $commandName = $command->getName();
9361 $isProxyCommand = ($command instanceof Command\BaseCommand && $command->isProxyCommand());
9362 } catch (\InvalidArgumentException $e) {
9363 }
9364 }
9365
9366 if (!$isProxyCommand) {
9367 $io->writeError(sprintf(
9368 'Running %s (%s) with %s on %s',
9369 Composer::VERSION,
9370 Composer::RELEASE_DATE,
9371 defined('HHVM_VERSION') ? 'HHVM '.HHVM_VERSION : 'PHP '.PHP_VERSION,
9372 function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknown OS'
9373 ), true, IOInterface::DEBUG);
9374
9375 if (PHP_VERSION_ID < 50302) {
9376 $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>');
9377 }
9378
9379 if (extension_loaded('xdebug') && !getenv('COMPOSER_DISABLE_XDEBUG_WARN')) {
9380 $io->writeError('<warning>You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug</warning>');
9381 }
9382
9383 if (defined('COMPOSER_DEV_WARNING_TIME') && $commandName !== 'self-update' && $commandName !== 'selfupdate' && time() > COMPOSER_DEV_WARNING_TIME) {
9384 $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']));
9385 }
9386
9387 if (getenv('COMPOSER_NO_INTERACTION')) {
9388 $input->setInteractive(false);
9389 }
9390
9391 if (!Platform::isWindows() && function_exists('exec') && !getenv('COMPOSER_ALLOW_SUPERUSER')) {
9392 if (function_exists('posix_getuid') && posix_getuid() === 0) {
9393 if ($commandName !== 'self-update' && $commandName !== 'selfupdate') {
9394 $io->writeError('<warning>Do not run Composer as root/super user! See https://getcomposer.org/root for details</warning>');
9395 }
9396 if ($uid = (int) getenv('SUDO_UID')) {
9397
9398  
9399  Silencer::call('exec', "sudo -u \\#{$uid} sudo -K > /dev/null 2>&1");
9400 }
9401 }
9402
9403  Silencer::call('exec', 'sudo -K > /dev/null 2>&1');
9404 }
9405
9406
9407  Silencer::call(function () use ($io) {
9408 $tempfile = sys_get_temp_dir() . '/temp-' . md5(microtime());
9409 if (!(file_put_contents($tempfile, __FILE__) && (file_get_contents($tempfile) == __FILE__) && unlink($tempfile) && !file_exists($tempfile))) {
9410 $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()));
9411 }
9412 });
9413
9414
9415  $file = Factory::getComposerFile();
9416 if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
9417 if (isset($composer['scripts']) && is_array($composer['scripts'])) {
9418 foreach ($composer['scripts'] as $script => $dummy) {
9419 if (!defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
9420 if ($this->has($script)) {
9421 $io->writeError('<warning>A script named '.$script.' would override a Composer command and has been skipped</warning>');
9422 } else {
9423 $this->add(new Command\ScriptAliasCommand($script));
9424 }
9425 }
9426 }
9427 }
9428 }
9429 }
9430
9431 try {
9432 if ($input->hasParameterOption('--profile')) {
9433 $startTime = microtime(true);
9434 $this->io->enableDebugging($startTime);
9435 }
9436
9437 $result = parent::doRun($input, $output);
9438
9439 if (isset($oldWorkingDir)) {
9440 chdir($oldWorkingDir);
9441 }
9442
9443 if (isset($startTime)) {
9444 $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');
9445 }
9446
9447 restore_error_handler();
9448
9449 return $result;
9450 } catch (ScriptExecutionException $e) {
9451 return $e->getCode();
9452 } catch (\Exception $e) {
9453 $this->hintCommonErrors($e);
9454 restore_error_handler();
9455 throw $e;
9456 }
9457 }
9458
9459
9460
9461
9462
9463
9464 private function getNewWorkingDir(InputInterface $input)
9465 {
9466 $workingDir = $input->getParameterOption(array('--working-dir', '-d'));
9467 if (false !== $workingDir && !is_dir($workingDir)) {
9468 throw new \RuntimeException('Invalid working directory specified, '.$workingDir.' does not exist.');
9469 }
9470
9471 return $workingDir;
9472 }
9473
9474
9475
9476
9477 private function hintCommonErrors($exception)
9478 {
9479 $io = $this->getIO();
9480
9481 Silencer::suppress();
9482 try {
9483 $composer = $this->getComposer(false, true);
9484 if ($composer) {
9485 $config = $composer->getConfig();
9486
9487 $minSpaceFree = 1024 * 1024;
9488 if ((($df = disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
9489 || (($df = disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
9490 || (($df = disk_free_space($dir = sys_get_temp_dir())) !== false && $df < $minSpaceFree)
9491 ) {
9492 $io->writeError('<error>The disk hosting '.$dir.' is full, this may be the cause of the following exception</error>', true, IOInterface::QUIET);
9493 }
9494 }
9495 } catch (\Exception $e) {
9496 }
9497 Silencer::restore();
9498
9499 if (Platform::isWindows() && false !== strpos($exception->getMessage(), 'The system cannot find the path specified')) {
9500 $io->writeError('<error>The following exception may be caused by a stale entry in your cmd.exe AutoRun</error>', true, IOInterface::QUIET);
9501 $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);
9502 }
9503
9504 if (false !== strpos($exception->getMessage(), 'fork failed - Cannot allocate memory')) {
9505 $io->writeError('<error>The following exception is caused by a lack of memory or swap, or not having swap configured</error>', true, IOInterface::QUIET);
9506 $io->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors for details</error>', true, IOInterface::QUIET);
9507 }
9508 }
9509
9510
9511
9512
9513
9514
9515
9516 public function getComposer($required = true, $disablePlugins = null)
9517 {
9518 if (null === $disablePlugins) {
9519 $disablePlugins = $this->disablePluginsByDefault;
9520 }
9521
9522 if (null === $this->composer) {
9523 try {
9524 $this->composer = Factory::create($this->io, null, $disablePlugins);
9525 } catch (\InvalidArgumentException $e) {
9526 if ($required) {
9527 $this->io->writeError($e->getMessage());
9528 exit(1);
9529 }
9530 } catch (JsonValidationException $e) {
9531 $errors = ' - ' . implode(PHP_EOL . ' - ', $e->getErrors());
9532 $message = $e->getMessage() . ':' . PHP_EOL . $errors;
9533 throw new JsonValidationException($message);
9534 }
9535 }
9536
9537 return $this->composer;
9538 }
9539
9540
9541
9542
9543 public function resetComposer()
9544 {
9545 $this->composer = null;
9546 }
9547
9548
9549
9550
9551 public function getIO()
9552 {
9553 return $this->io;
9554 }
9555
9556 public function getHelp()
9557 {
9558 return self::$logo . parent::getHelp();
9559 }
9560
9561
9562
9563
9564 protected function getDefaultCommands()
9565 {
9566 $commands = array_merge(parent::getDefaultCommands(), array(
9567 new Command\AboutCommand(),
9568 new Command\ConfigCommand(),
9569 new Command\DependsCommand(),
9570 new Command\ProhibitsCommand(),
9571 new Command\InitCommand(),
9572 new Command\InstallCommand(),
9573 new Command\CreateProjectCommand(),
9574 new Command\UpdateCommand(),
9575 new Command\SearchCommand(),
9576 new Command\ValidateCommand(),
9577 new Command\ShowCommand(),
9578 new Command\SuggestsCommand(),
9579 new Command\RequireCommand(),
9580 new Command\DumpAutoloadCommand(),
9581 new Command\StatusCommand(),
9582 new Command\ArchiveCommand(),
9583 new Command\DiagnoseCommand(),
9584 new Command\RunScriptCommand(),
9585 new Command\LicensesCommand(),
9586 new Command\GlobalCommand(),
9587 new Command\ClearCacheCommand(),
9588 new Command\RemoveCommand(),
9589 new Command\HomeCommand(),
9590 new Command\ExecCommand(),
9591 new Command\OutdatedCommand(),
9592 ));
9593
9594 if ('phar:' === substr(__FILE__, 0, 5)) {
9595 $commands[] = new Command\SelfUpdateCommand();
9596 }
9597
9598 return $commands;
9599 }
9600
9601
9602
9603
9604 public function getLongVersion()
9605 {
9606 if (Composer::BRANCH_ALIAS_VERSION) {
9607 return sprintf(
9608 '<info>%s</info> version <comment>%s (%s)</comment> %s',
9609 $this->getName(),
9610 Composer::BRANCH_ALIAS_VERSION,
9611 $this->getVersion(),
9612 Composer::RELEASE_DATE
9613 );
9614 }
9615
9616 return parent::getLongVersion() . ' ' . Composer::RELEASE_DATE;
9617 }
9618
9619
9620
9621
9622 protected function getDefaultInputDefinition()
9623 {
9624 $definition = parent::getDefaultInputDefinition();
9625 $definition->addOption(new InputOption('--profile', null, InputOption::VALUE_NONE, 'Display timing and memory usage information'));
9626 $definition->addOption(new InputOption('--no-plugins', null, InputOption::VALUE_NONE, 'Whether to disable plugins.'));
9627 $definition->addOption(new InputOption('--working-dir', '-d', InputOption::VALUE_REQUIRED, 'If specified, use the given directory as working directory.'));
9628
9629 return $definition;
9630 }
9631
9632 private function getPluginCommands()
9633 {
9634 $commands = array();
9635
9636 $composer = $this->getComposer(false, false);
9637 if (null === $composer) {
9638 $composer = Factory::createGlobal($this->io, false);
9639 }
9640
9641 if (null !== $composer) {
9642 $pm = $composer->getPluginManager();
9643 foreach ($pm->getPluginCapabilities('Composer\Plugin\Capability\CommandProvider', array('composer' => $composer, 'io' => $this->io)) as $capability) {
9644 $newCommands = $capability->getCommands();
9645 if (!is_array($newCommands)) {
9646 throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' failed to return an array from getCommands');
9647 }
9648 foreach ($newCommands as $command) {
9649 if (!$command instanceof Command\BaseCommand) {
9650 throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' returned an invalid value, we expected an array of Composer\Command\BaseCommand objects');
9651 }
9652 }
9653 $commands = array_merge($commands, $newCommands);
9654 }
9655 }
9656
9657 return $commands;
9658 }
9659 }
9660 <?php
9661
9662
9663
9664
9665
9666
9667
9668
9669
9670
9671
9672 namespace Composer\Console;
9673
9674 use Symfony\Component\Console\Formatter\OutputFormatter;
9675
9676
9677
9678
9679 class HtmlOutputFormatter extends OutputFormatter
9680 {
9681 private static $availableForegroundColors = array(
9682 30 => 'black',
9683 31 => 'red',
9684 32 => 'green',
9685 33 => 'yellow',
9686 34 => 'blue',
9687 35 => 'magenta',
9688 36 => 'cyan',
9689 37 => 'white',
9690 );
9691 private static $availableBackgroundColors = array(
9692 40 => 'black',
9693 41 => 'red',
9694 42 => 'green',
9695 43 => 'yellow',
9696 44 => 'blue',
9697 45 => 'magenta',
9698 46 => 'cyan',
9699 47 => 'white',
9700 );
9701 private static $availableOptions = array(
9702 1 => 'bold',
9703 4 => 'underscore',
9704
9705  
9706  
9707  );
9708
9709
9710
9711
9712 public function __construct(array $styles = array())
9713 {
9714 parent::__construct(true, $styles);
9715 }
9716
9717 public function format($message)
9718 {
9719 $formatted = parent::format($message);
9720
9721 $clearEscapeCodes = '(?:39|49|0|22|24|25|27|28)';
9722
9723 return preg_replace_callback("{\033\[([0-9;]+)m(.*?)\033\[(?:".$clearEscapeCodes.";)*?".$clearEscapeCodes."m}s", array($this, 'formatHtml'), $formatted);
9724 }
9725
9726 private function formatHtml($matches)
9727 {
9728 $out = '<span style="';
9729 foreach (explode(';', $matches[1]) as $code) {
9730 if (isset(self::$availableForegroundColors[$code])) {
9731 $out .= 'color:'.self::$availableForegroundColors[$code].';';
9732 } elseif (isset(self::$availableBackgroundColors[$code])) {
9733 $out .= 'background-color:'.self::$availableBackgroundColors[$code].';';
9734 } elseif (isset(self::$availableOptions[$code])) {
9735 switch (self::$availableOptions[$code]) {
9736 case 'bold':
9737 $out .= 'font-weight:bold;';
9738 break;
9739
9740 case 'underscore':
9741 $out .= 'text-decoration:underline;';
9742 break;
9743 }
9744 }
9745 }
9746
9747 return $out.'">'.$matches[2].'</span>';
9748 }
9749 }
9750 <?php
9751
9752
9753
9754
9755
9756
9757
9758
9759
9760
9761
9762 namespace Composer\DependencyResolver;
9763
9764
9765
9766
9767
9768
9769 class Decisions implements \Iterator, \Countable
9770 {
9771 const DECISION_LITERAL = 0;
9772 const DECISION_REASON = 1;
9773
9774 protected $pool;
9775 protected $decisionMap;
9776 protected $decisionQueue = array();
9777
9778 public function __construct($pool)
9779 {
9780 $this->pool = $pool;
9781 $this->decisionMap = array();
9782 }
9783
9784 public function decide($literal, $level, $why)
9785 {
9786 $this->addDecision($literal, $level);
9787 $this->decisionQueue[] = array(
9788 self::DECISION_LITERAL => $literal,
9789 self::DECISION_REASON => $why,
9790 );
9791 }
9792
9793 public function satisfy($literal)
9794 {
9795 $packageId = abs($literal);
9796
9797 return (
9798 $literal > 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 ||
9799 $literal < 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0
9800 );
9801 }
9802
9803 public function conflict($literal)
9804 {
9805 $packageId = abs($literal);
9806
9807 return (
9808 (isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 && $literal < 0) ||
9809 (isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0 && $literal > 0)
9810 );
9811 }
9812
9813 public function decided($literalOrPackageId)
9814 {
9815 return !empty($this->decisionMap[abs($literalOrPackageId)]);
9816 }
9817
9818 public function undecided($literalOrPackageId)
9819 {
9820 return empty($this->decisionMap[abs($literalOrPackageId)]);
9821 }
9822
9823 public function decidedInstall($literalOrPackageId)
9824 {
9825 $packageId = abs($literalOrPackageId);
9826
9827 return isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0;
9828 }
9829
9830 public function decisionLevel($literalOrPackageId)
9831 {
9832 $packageId = abs($literalOrPackageId);
9833 if (isset($this->decisionMap[$packageId])) {
9834 return abs($this->decisionMap[$packageId]);
9835 }
9836
9837 return 0;
9838 }
9839
9840 public function decisionRule($literalOrPackageId)
9841 {
9842 $packageId = abs($literalOrPackageId);
9843
9844 foreach ($this->decisionQueue as $i => $decision) {
9845 if ($packageId === abs($decision[self::DECISION_LITERAL])) {
9846 return $decision[self::DECISION_REASON];
9847 }
9848 }
9849
9850 return null;
9851 }
9852
9853 public function atOffset($queueOffset)
9854 {
9855 return $this->decisionQueue[$queueOffset];
9856 }
9857
9858 public function validOffset($queueOffset)
9859 {
9860 return $queueOffset >= 0 && $queueOffset < count($this->decisionQueue);
9861 }
9862
9863 public function lastReason()
9864 {
9865 return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_REASON];
9866 }
9867
9868 public function lastLiteral()
9869 {
9870 return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_LITERAL];
9871 }
9872
9873 public function reset()
9874 {
9875 while ($decision = array_pop($this->decisionQueue)) {
9876 $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
9877 }
9878 }
9879
9880 public function resetToOffset($offset)
9881 {
9882 while (count($this->decisionQueue) > $offset + 1) {
9883 $decision = array_pop($this->decisionQueue);
9884 $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
9885 }
9886 }
9887
9888 public function revertLast()
9889 {
9890 $this->decisionMap[abs($this->lastLiteral())] = 0;
9891 array_pop($this->decisionQueue);
9892 }
9893
9894 public function count()
9895 {
9896 return count($this->decisionQueue);
9897 }
9898
9899 public function rewind()
9900 {
9901 end($this->decisionQueue);
9902 }
9903
9904 public function current()
9905 {
9906 return current($this->decisionQueue);
9907 }
9908
9909 public function key()
9910 {
9911 return key($this->decisionQueue);
9912 }
9913
9914 public function next()
9915 {
9916 return prev($this->decisionQueue);
9917 }
9918
9919 public function valid()
9920 {
9921 return false !== current($this->decisionQueue);
9922 }
9923
9924 public function isEmpty()
9925 {
9926 return count($this->decisionQueue) === 0;
9927 }
9928
9929 protected function addDecision($literal, $level)
9930 {
9931 $packageId = abs($literal);
9932
9933 $previousDecision = isset($this->decisionMap[$packageId]) ? $this->decisionMap[$packageId] : null;
9934 if ($previousDecision != 0) {
9935 $literalString = $this->pool->literalToString($literal);
9936 $package = $this->pool->literalToPackage($literal);
9937 throw new SolverBugException(
9938 "Trying to decide $literalString on level $level, even though $package was previously decided as ".(int) $previousDecision."."
9939 );
9940 }
9941
9942 if ($literal > 0) {
9943 $this->decisionMap[$packageId] = $level;
9944 } else {
9945 $this->decisionMap[$packageId] = -$level;
9946 }
9947 }
9948 }
9949 <?php
9950
9951
9952
9953
9954
9955
9956
9957
9958
9959
9960
9961 namespace Composer\DependencyResolver;
9962
9963 use Composer\Package\PackageInterface;
9964 use Composer\Package\AliasPackage;
9965 use Composer\Package\BasePackage;
9966 use Composer\Semver\Constraint\Constraint;
9967
9968
9969
9970
9971
9972 class DefaultPolicy implements PolicyInterface
9973 {
9974 private $preferStable;
9975 private $preferLowest;
9976
9977 public function __construct($preferStable = false, $preferLowest = false)
9978 {
9979 $this->preferStable = $preferStable;
9980 $this->preferLowest = $preferLowest;
9981 }
9982
9983 public function versionCompare(PackageInterface $a, PackageInterface $b, $operator)
9984 {
9985 if ($this->preferStable && ($stabA = $a->getStability()) !== ($stabB = $b->getStability())) {
9986 return BasePackage::$stabilities[$stabA] < BasePackage::$stabilities[$stabB];
9987 }
9988
9989 $constraint = new Constraint($operator, $b->getVersion());
9990 $version = new Constraint('==', $a->getVersion());
9991
9992 return $constraint->matchSpecific($version, true);
9993 }
9994
9995 public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package, $mustMatchName = false)
9996 {
9997 $packages = array();
9998
9999 foreach ($pool->whatProvides($package->getName(), null, $mustMatchName) as $candidate) {
10000 if ($candidate !== $package) {
10001 $packages[] = $candidate;
10002 }
10003 }
10004
10005 return $packages;
10006 }
10007
10008 public function getPriority(Pool $pool, PackageInterface $package)
10009 {
10010 return $pool->getPriority($package->getRepository());
10011 }
10012
10013 public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null)
10014 {
10015 $packages = $this->groupLiteralsByNamePreferInstalled($pool, $installedMap, $literals);
10016
10017 foreach ($packages as &$literals) {
10018 $policy = $this;
10019 usort($literals, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
10020 return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage, true);
10021 });
10022 }
10023
10024 foreach ($packages as &$literals) {
10025 $literals = $this->pruneToHighestPriorityOrInstalled($pool, $installedMap, $literals);
10026
10027 $literals = $this->pruneToBestVersion($pool, $literals);
10028
10029 $literals = $this->pruneRemoteAliases($pool, $literals);
10030 }
10031
10032 $selected = call_user_func_array('array_merge', $packages);
10033
10034
10035  usort($selected, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
10036 return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage);
10037 });
10038
10039 return $selected;
10040 }
10041
10042 protected function groupLiteralsByNamePreferInstalled(Pool $pool, array $installedMap, $literals)
10043 {
10044 $packages = array();
10045 foreach ($literals as $literal) {
10046 $packageName = $pool->literalToPackage($literal)->getName();
10047
10048 if (!isset($packages[$packageName])) {
10049 $packages[$packageName] = array();
10050 }
10051
10052 if (isset($installedMap[abs($literal)])) {
10053 array_unshift($packages[$packageName], $literal);
10054 } else {
10055 $packages[$packageName][] = $literal;
10056 }
10057 }
10058
10059 return $packages;
10060 }
10061
10062
10063
10064
10065 public function compareByPriorityPreferInstalled(Pool $pool, array $installedMap, PackageInterface $a, PackageInterface $b, $requiredPackage = null, $ignoreReplace = false)
10066 {
10067 if ($a->getRepository() === $b->getRepository()) {
10068
10069  if ($a->getName() === $b->getName()) {
10070 $aAliased = $a instanceof AliasPackage;
10071 $bAliased = $b instanceof AliasPackage;
10072 if ($aAliased && !$bAliased) {
10073 return -1; 
10074  }
10075 if (!$aAliased && $bAliased) {
10076 return 1; 
10077  }
10078 }
10079
10080 if (!$ignoreReplace) {
10081
10082  if ($this->replaces($a, $b)) {
10083 return 1; 
10084  }
10085 if ($this->replaces($b, $a)) {
10086 return -1; 
10087  }
10088
10089
10090  
10091  if ($requiredPackage && false !== ($pos = strpos($requiredPackage, '/'))) {
10092 $requiredVendor = substr($requiredPackage, 0, $pos);
10093
10094 $aIsSameVendor = substr($a->getName(), 0, $pos) === $requiredVendor;
10095 $bIsSameVendor = substr($b->getName(), 0, $pos) === $requiredVendor;
10096
10097 if ($bIsSameVendor !== $aIsSameVendor) {
10098 return $aIsSameVendor ? -1 : 1;
10099 }
10100 }
10101 }
10102
10103
10104  if ($a->id === $b->id) {
10105 return 0;
10106 }
10107
10108 return ($a->id < $b->id) ? -1 : 1;
10109 }
10110
10111 if (isset($installedMap[$a->id])) {
10112 return -1;
10113 }
10114
10115 if (isset($installedMap[$b->id])) {
10116 return 1;
10117 }
10118
10119 return ($this->getPriority($pool, $a) > $this->getPriority($pool, $b)) ? -1 : 1;
10120 }
10121
10122
10123
10124
10125
10126
10127
10128
10129
10130
10131
10132 protected function replaces(PackageInterface $source, PackageInterface $target)
10133 {
10134 foreach ($source->getReplaces() as $link) {
10135 if ($link->getTarget() === $target->getName()
10136
10137
10138  ) {
10139 return true;
10140 }
10141 }
10142
10143 return false;
10144 }
10145
10146 protected function pruneToBestVersion(Pool $pool, $literals)
10147 {
10148 $operator = $this->preferLowest ? '<' : '>';
10149 $bestLiterals = array($literals[0]);
10150 $bestPackage = $pool->literalToPackage($literals[0]);
10151 foreach ($literals as $i => $literal) {
10152 if (0 === $i) {
10153 continue;
10154 }
10155
10156 $package = $pool->literalToPackage($literal);
10157
10158 if ($this->versionCompare($package, $bestPackage, $operator)) {
10159 $bestPackage = $package;
10160 $bestLiterals = array($literal);
10161 } elseif ($this->versionCompare($package, $bestPackage, '==')) {
10162 $bestLiterals[] = $literal;
10163 }
10164 }
10165
10166 return $bestLiterals;
10167 }
10168
10169
10170
10171
10172 protected function pruneToHighestPriorityOrInstalled(Pool $pool, array $installedMap, array $literals)
10173 {
10174 $selected = array();
10175
10176 $priority = null;
10177
10178 foreach ($literals as $literal) {
10179 $package = $pool->literalToPackage($literal);
10180
10181 if (isset($installedMap[$package->id])) {
10182 $selected[] = $literal;
10183 continue;
10184 }
10185
10186 if (null === $priority) {
10187 $priority = $this->getPriority($pool, $package);
10188 }
10189
10190 if ($this->getPriority($pool, $package) != $priority) {
10191 break;
10192 }
10193
10194 $selected[] = $literal;
10195 }
10196
10197 return $selected;
10198 }
10199
10200
10201
10202
10203
10204
10205 protected function pruneRemoteAliases(Pool $pool, array $literals)
10206 {
10207 $hasLocalAlias = false;
10208
10209 foreach ($literals as $literal) {
10210 $package = $pool->literalToPackage($literal);
10211
10212 if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
10213 $hasLocalAlias = true;
10214 break;
10215 }
10216 }
10217
10218 if (!$hasLocalAlias) {
10219 return $literals;
10220 }
10221
10222 $selected = array();
10223 foreach ($literals as $literal) {
10224 $package = $pool->literalToPackage($literal);
10225
10226 if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
10227 $selected[] = $literal;
10228 }
10229 }
10230
10231 return $selected;
10232 }
10233 }
10234 <?php
10235
10236
10237
10238
10239
10240
10241
10242
10243
10244
10245
10246 namespace Composer\DependencyResolver;
10247
10248 use Composer\Package\PackageInterface;
10249 use Composer\Package\Link;
10250
10251
10252
10253
10254 class GenericRule extends Rule
10255 {
10256 protected $literals;
10257
10258
10259
10260
10261
10262
10263
10264 public function __construct(array $literals, $reason, $reasonData, $job = null)
10265 {
10266 parent::__construct($reason, $reasonData, $job);
10267
10268
10269  sort($literals);
10270
10271 $this->literals = $literals;
10272 }
10273
10274 public function getLiterals()
10275 {
10276 return $this->literals;
10277 }
10278
10279 public function getHash()
10280 {
10281 $data = unpack('ihash', md5(implode(',', $this->literals), true));
10282
10283 return $data['hash'];
10284 }
10285
10286
10287
10288
10289
10290
10291
10292
10293
10294 public function equals(Rule $rule)
10295 {
10296 return $this->literals === $rule->getLiterals();
10297 }
10298
10299 public function isAssertion()
10300 {
10301 return 1 === count($this->literals);
10302 }
10303
10304
10305
10306
10307
10308
10309 public function __toString()
10310 {
10311 $result = ($this->isDisabled()) ? 'disabled(' : '(';
10312
10313 foreach ($this->literals as $i => $literal) {
10314 if ($i != 0) {
10315 $result .= '|';
10316 }
10317 $result .= $literal;
10318 }
10319
10320 $result .= ')';
10321
10322 return $result;
10323 }
10324 }
10325 <?php
10326
10327
10328
10329
10330
10331
10332
10333
10334
10335
10336
10337 namespace Composer\DependencyResolver\Operation;
10338
10339 use Composer\Package\PackageInterface;
10340
10341
10342
10343
10344
10345
10346 class InstallOperation extends SolverOperation
10347 {
10348 protected $package;
10349
10350
10351
10352
10353
10354
10355
10356 public function __construct(PackageInterface $package, $reason = null)
10357 {
10358 parent::__construct($reason);
10359
10360 $this->package = $package;
10361 }
10362
10363
10364
10365
10366
10367
10368 public function getPackage()
10369 {
10370 return $this->package;
10371 }
10372
10373
10374
10375
10376
10377
10378 public function getJobType()
10379 {
10380 return 'install';
10381 }
10382
10383
10384
10385
10386 public function __toString()
10387 {
10388 return 'Installing '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
10389 }
10390 }
10391 <?php
10392
10393
10394
10395
10396
10397
10398
10399
10400
10401
10402
10403 namespace Composer\DependencyResolver\Operation;
10404
10405 use Composer\Package\AliasPackage;
10406 use Composer\Package\PackageInterface;
10407
10408
10409
10410
10411
10412
10413 class MarkAliasInstalledOperation extends SolverOperation
10414 {
10415 protected $package;
10416
10417
10418
10419
10420
10421
10422
10423 public function __construct(AliasPackage $package, $reason = null)
10424 {
10425 parent::__construct($reason);
10426
10427 $this->package = $package;
10428 }
10429
10430
10431
10432
10433
10434
10435 public function getPackage()
10436 {
10437 return $this->package;
10438 }
10439
10440
10441
10442
10443
10444
10445 public function getJobType()
10446 {
10447 return 'markAliasInstalled';
10448 }
10449
10450
10451
10452
10453 public function __toString()
10454 {
10455 return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as installed, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
10456 }
10457 }
10458 <?php
10459
10460
10461
10462
10463
10464
10465
10466
10467
10468
10469
10470 namespace Composer\DependencyResolver\Operation;
10471
10472 use Composer\Package\AliasPackage;
10473 use Composer\Package\PackageInterface;
10474
10475
10476
10477
10478
10479
10480 class MarkAliasUninstalledOperation extends SolverOperation
10481 {
10482 protected $package;
10483
10484
10485
10486
10487
10488
10489
10490 public function __construct(AliasPackage $package, $reason = null)
10491 {
10492 parent::__construct($reason);
10493
10494 $this->package = $package;
10495 }
10496
10497
10498
10499
10500
10501
10502 public function getPackage()
10503 {
10504 return $this->package;
10505 }
10506
10507
10508
10509
10510
10511
10512 public function getJobType()
10513 {
10514 return 'markAliasUninstalled';
10515 }
10516
10517
10518
10519
10520 public function __toString()
10521 {
10522 return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as uninstalled, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
10523 }
10524 }
10525 <?php
10526
10527
10528
10529
10530
10531
10532
10533
10534
10535
10536
10537 namespace Composer\DependencyResolver\Operation;
10538
10539
10540
10541
10542
10543
10544 interface OperationInterface
10545 {
10546
10547
10548
10549
10550
10551 public function getJobType();
10552
10553
10554
10555
10556
10557
10558 public function getReason();
10559
10560
10561
10562
10563
10564
10565 public function __toString();
10566 }
10567 <?php
10568
10569
10570
10571
10572
10573
10574
10575
10576
10577
10578
10579 namespace Composer\DependencyResolver\Operation;
10580
10581 use Composer\Package\PackageInterface;
10582
10583
10584
10585
10586
10587
10588 abstract class SolverOperation implements OperationInterface
10589 {
10590 protected $reason;
10591
10592
10593
10594
10595
10596
10597 public function __construct($reason = null)
10598 {
10599 $this->reason = $reason;
10600 }
10601
10602
10603
10604
10605
10606
10607 public function getReason()
10608 {
10609 return $this->reason;
10610 }
10611
10612 protected function formatVersion(PackageInterface $package)
10613 {
10614 return $package->getFullPrettyVersion();
10615 }
10616 }
10617 <?php
10618
10619
10620
10621
10622
10623
10624
10625
10626
10627
10628
10629 namespace Composer\DependencyResolver\Operation;
10630
10631 use Composer\Package\PackageInterface;
10632
10633
10634
10635
10636
10637
10638 class UninstallOperation extends SolverOperation
10639 {
10640 protected $package;
10641
10642
10643
10644
10645
10646
10647
10648 public function __construct(PackageInterface $package, $reason = null)
10649 {
10650 parent::__construct($reason);
10651
10652 $this->package = $package;
10653 }
10654
10655
10656
10657
10658
10659
10660 public function getPackage()
10661 {
10662 return $this->package;
10663 }
10664
10665
10666
10667
10668
10669
10670 public function getJobType()
10671 {
10672 return 'uninstall';
10673 }
10674
10675
10676
10677
10678 public function __toString()
10679 {
10680 return 'Uninstalling '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
10681 }
10682 }
10683 <?php
10684
10685
10686
10687
10688
10689
10690
10691
10692
10693
10694
10695 namespace Composer\DependencyResolver\Operation;
10696
10697 use Composer\Package\PackageInterface;
10698
10699
10700
10701
10702
10703
10704 class UpdateOperation extends SolverOperation
10705 {
10706 protected $initialPackage;
10707 protected $targetPackage;
10708
10709
10710
10711
10712
10713
10714
10715
10716 public function __construct(PackageInterface $initial, PackageInterface $target, $reason = null)
10717 {
10718 parent::__construct($reason);
10719
10720 $this->initialPackage = $initial;
10721 $this->targetPackage = $target;
10722 }
10723
10724
10725
10726
10727
10728
10729 public function getInitialPackage()
10730 {
10731 return $this->initialPackage;
10732 }
10733
10734
10735
10736
10737
10738
10739 public function getTargetPackage()
10740 {
10741 return $this->targetPackage;
10742 }
10743
10744
10745
10746
10747
10748
10749 public function getJobType()
10750 {
10751 return 'update';
10752 }
10753
10754
10755
10756
10757 public function __toString()
10758 {
10759 return 'Updating '.$this->initialPackage->getPrettyName().' ('.$this->formatVersion($this->initialPackage).') to '.
10760 $this->targetPackage->getPrettyName(). ' ('.$this->formatVersion($this->targetPackage).')';
10761 }
10762 }
10763 <?php
10764
10765
10766
10767
10768
10769
10770
10771
10772
10773
10774
10775 namespace Composer\DependencyResolver;
10776
10777 use Composer\Package\PackageInterface;
10778
10779
10780
10781
10782 interface PolicyInterface
10783 {
10784 public function versionCompare(PackageInterface $a, PackageInterface $b, $operator);
10785
10786 public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package);
10787
10788 public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null);
10789 }
10790 <?php
10791
10792
10793
10794
10795
10796
10797
10798
10799
10800
10801
10802 namespace Composer\DependencyResolver;
10803
10804 use Composer\Package\BasePackage;
10805 use Composer\Package\AliasPackage;
10806 use Composer\Package\Version\VersionParser;
10807 use Composer\Semver\Constraint\ConstraintInterface;
10808 use Composer\Semver\Constraint\Constraint;
10809 use Composer\Semver\Constraint\EmptyConstraint;
10810 use Composer\Repository\RepositoryInterface;
10811 use Composer\Repository\CompositeRepository;
10812 use Composer\Repository\ComposerRepository;
10813 use Composer\Repository\InstalledRepositoryInterface;
10814 use Composer\Repository\PlatformRepository;
10815 use Composer\Package\PackageInterface;
10816
10817
10818
10819
10820
10821
10822
10823 class Pool implements \Countable
10824 {
10825 const MATCH_NAME = -1;
10826 const MATCH_NONE = 0;
10827 const MATCH = 1;
10828 const MATCH_PROVIDE = 2;
10829 const MATCH_REPLACE = 3;
10830 const MATCH_FILTERED = 4;
10831
10832 protected $repositories = array();
10833 protected $providerRepos = array();
10834 protected $packages = array();
10835 protected $packageByName = array();
10836 protected $packageByExactName = array();
10837 protected $acceptableStabilities;
10838 protected $stabilityFlags;
10839 protected $versionParser;
10840 protected $providerCache = array();
10841 protected $filterRequires;
10842 protected $whitelist = null;
10843 protected $id = 1;
10844
10845 public function __construct($minimumStability = 'stable', array $stabilityFlags = array(), array $filterRequires = array())
10846 {
10847 $this->versionParser = new VersionParser;
10848 $this->acceptableStabilities = array();
10849 foreach (BasePackage::$stabilities as $stability => $value) {
10850 if ($value <= BasePackage::$stabilities[$minimumStability]) {
10851 $this->acceptableStabilities[$stability] = $value;
10852 }
10853 }
10854 $this->stabilityFlags = $stabilityFlags;
10855 $this->filterRequires = $filterRequires;
10856 foreach ($filterRequires as $name => $constraint) {
10857 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name)) {
10858 unset($this->filterRequires[$name]);
10859 }
10860 }
10861 }
10862
10863 public function setWhitelist($whitelist)
10864 {
10865 $this->whitelist = $whitelist;
10866 $this->providerCache = array();
10867 }
10868
10869
10870
10871
10872
10873
10874
10875 public function addRepository(RepositoryInterface $repo, $rootAliases = array())
10876 {
10877 if ($repo instanceof CompositeRepository) {
10878 $repos = $repo->getRepositories();
10879 } else {
10880 $repos = array($repo);
10881 }
10882
10883 foreach ($repos as $repo) {
10884 $this->repositories[] = $repo;
10885
10886 $exempt = $repo instanceof PlatformRepository || $repo instanceof InstalledRepositoryInterface;
10887
10888 if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
10889 $this->providerRepos[] = $repo;
10890 $repo->setRootAliases($rootAliases);
10891 $repo->resetPackageIds();
10892 } else {
10893 foreach ($repo->getPackages() as $package) {
10894 $names = $package->getNames();
10895 $stability = $package->getStability();
10896 if ($exempt || $this->isPackageAcceptable($names, $stability)) {
10897 $package->setId($this->id++);
10898 $this->packages[] = $package;
10899 $this->packageByExactName[$package->getName()][$package->id] = $package;
10900
10901 foreach ($names as $provided) {
10902 $this->packageByName[$provided][] = $package;
10903 }
10904
10905
10906  $name = $package->getName();
10907 if (isset($rootAliases[$name][$package->getVersion()])) {
10908 $alias = $rootAliases[$name][$package->getVersion()];
10909 if ($package instanceof AliasPackage) {
10910 $package = $package->getAliasOf();
10911 }
10912 $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
10913 $aliasPackage->setRootPackageAlias(true);
10914 $aliasPackage->setId($this->id++);
10915
10916 $package->getRepository()->addPackage($aliasPackage);
10917 $this->packages[] = $aliasPackage;
10918 $this->packageByExactName[$aliasPackage->getName()][$aliasPackage->id] = $aliasPackage;
10919
10920 foreach ($aliasPackage->getNames() as $name) {
10921 $this->packageByName[$name][] = $aliasPackage;
10922 }
10923 }
10924 }
10925 }
10926 }
10927 }
10928 }
10929
10930 public function getPriority(RepositoryInterface $repo)
10931 {
10932 $priority = array_search($repo, $this->repositories, true);
10933
10934 if (false === $priority) {
10935 throw new \RuntimeException("Could not determine repository priority. The repository was not registered in the pool.");
10936 }
10937
10938 return -$priority;
10939 }
10940
10941
10942
10943
10944
10945
10946
10947 public function packageById($id)
10948 {
10949 return $this->packages[$id - 1];
10950 }
10951
10952
10953
10954
10955 public function count()
10956 {
10957 return count($this->packages);
10958 }
10959
10960
10961
10962
10963
10964
10965
10966
10967
10968
10969
10970
10971 public function whatProvides($name, ConstraintInterface $constraint = null, $mustMatchName = false, $bypassFilters = false)
10972 {
10973 if ($bypassFilters) {
10974 return $this->computeWhatProvides($name, $constraint, $mustMatchName, true);
10975 }
10976
10977 $key = ((int) $mustMatchName).$constraint;
10978 if (isset($this->providerCache[$name][$key])) {
10979 return $this->providerCache[$name][$key];
10980 }
10981
10982 return $this->providerCache[$name][$key] = $this->computeWhatProvides($name, $constraint, $mustMatchName, $bypassFilters);
10983 }
10984
10985
10986
10987
10988 private function computeWhatProvides($name, $constraint, $mustMatchName = false, $bypassFilters = false)
10989 {
10990 $candidates = array();
10991
10992 foreach ($this->providerRepos as $repo) {
10993 foreach ($repo->whatProvides($this, $name, $bypassFilters) as $candidate) {
10994 $candidates[] = $candidate;
10995 if ($candidate->id < 1) {
10996 $candidate->setId($this->id++);
10997 $this->packages[$this->id - 2] = $candidate;
10998 }
10999 }
11000 }
11001
11002 if ($mustMatchName) {
11003 $candidates = array_filter($candidates, function ($candidate) use ($name) {
11004 return $candidate->getName() == $name;
11005 });
11006 if (isset($this->packageByExactName[$name])) {
11007 $candidates = array_merge($candidates, $this->packageByExactName[$name]);
11008 }
11009 } elseif (isset($this->packageByName[$name])) {
11010 $candidates = array_merge($candidates, $this->packageByName[$name]);
11011 }
11012
11013 $matches = $provideMatches = array();
11014 $nameMatch = false;
11015
11016 foreach ($candidates as $candidate) {
11017 $aliasOfCandidate = null;
11018
11019
11020  
11021  if ($candidate instanceof AliasPackage) {
11022 $aliasOfCandidate = $candidate->getAliasOf();
11023 }
11024
11025 if ($this->whitelist !== null && !$bypassFilters && (
11026 (!($candidate instanceof AliasPackage) && !isset($this->whitelist[$candidate->id])) ||
11027 ($candidate instanceof AliasPackage && !isset($this->whitelist[$aliasOfCandidate->id]))
11028 )) {
11029 continue;
11030 }
11031 switch ($this->match($candidate, $name, $constraint, $bypassFilters)) {
11032 case self::MATCH_NONE:
11033 break;
11034
11035 case self::MATCH_NAME:
11036 $nameMatch = true;
11037 break;
11038
11039 case self::MATCH:
11040 $nameMatch = true;
11041 $matches[] = $candidate;
11042 break;
11043
11044 case self::MATCH_PROVIDE:
11045 $provideMatches[] = $candidate;
11046 break;
11047
11048 case self::MATCH_REPLACE:
11049 $matches[] = $candidate;
11050 break;
11051
11052 case self::MATCH_FILTERED:
11053 break;
11054
11055 default:
11056 throw new \UnexpectedValueException('Unexpected match type');
11057 }
11058 }
11059
11060
11061  if ($nameMatch) {
11062 return $matches;
11063 }
11064
11065 return array_merge($matches, $provideMatches);
11066 }
11067
11068 public function literalToPackage($literal)
11069 {
11070 $packageId = abs($literal);
11071
11072 return $this->packageById($packageId);
11073 }
11074
11075 public function literalToPrettyString($literal, $installedMap)
11076 {
11077 $package = $this->literalToPackage($literal);
11078
11079 if (isset($installedMap[$package->id])) {
11080 $prefix = ($literal > 0 ? 'keep' : 'remove');
11081 } else {
11082 $prefix = ($literal > 0 ? 'install' : 'don\'t install');
11083 }
11084
11085 return $prefix.' '.$package->getPrettyString();
11086 }
11087
11088 public function isPackageAcceptable($name, $stability)
11089 {
11090 foreach ((array) $name as $n) {
11091
11092  if (!isset($this->stabilityFlags[$n]) && isset($this->acceptableStabilities[$stability])) {
11093 return true;
11094 }
11095
11096
11097  if (isset($this->stabilityFlags[$n]) && BasePackage::$stabilities[$stability] <= $this->stabilityFlags[$n]) {
11098 return true;
11099 }
11100 }
11101
11102 return false;
11103 }
11104
11105
11106
11107
11108
11109
11110
11111
11112
11113
11114 private function match($candidate, $name, ConstraintInterface $constraint = null, $bypassFilters)
11115 {
11116 $candidateName = $candidate->getName();
11117 $candidateVersion = $candidate->getVersion();
11118 $isDev = $candidate->getStability() === 'dev';
11119 $isAlias = $candidate instanceof AliasPackage;
11120
11121 if (!$bypassFilters && !$isDev && !$isAlias && isset($this->filterRequires[$name])) {
11122 $requireFilter = $this->filterRequires[$name];
11123 } else {
11124 $requireFilter = new EmptyConstraint;
11125 }
11126
11127 if ($candidateName === $name) {
11128 $pkgConstraint = new Constraint('==', $candidateVersion);
11129
11130 if ($constraint === null || $constraint->matches($pkgConstraint)) {
11131 return $requireFilter->matches($pkgConstraint) ? self::MATCH : self::MATCH_FILTERED;
11132 }
11133
11134 return self::MATCH_NAME;
11135 }
11136
11137 $provides = $candidate->getProvides();
11138 $replaces = $candidate->getReplaces();
11139
11140
11141  if (isset($replaces[0]) || isset($provides[0])) {
11142 foreach ($provides as $link) {
11143 if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
11144 return $requireFilter->matches($link->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
11145 }
11146 }
11147
11148 foreach ($replaces as $link) {
11149 if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
11150 return $requireFilter->matches($link->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
11151 }
11152 }
11153
11154 return self::MATCH_NONE;
11155 }
11156
11157 if (isset($provides[$name]) && ($constraint === null || $constraint->matches($provides[$name]->getConstraint()))) {
11158 return $requireFilter->matches($provides[$name]->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
11159 }
11160
11161 if (isset($replaces[$name]) && ($constraint === null || $constraint->matches($replaces[$name]->getConstraint()))) {
11162 return $requireFilter->matches($replaces[$name]->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
11163 }
11164
11165 return self::MATCH_NONE;
11166 }
11167 }
11168 <?php
11169
11170
11171
11172
11173
11174
11175
11176
11177
11178
11179
11180 namespace Composer\DependencyResolver;
11181
11182
11183
11184
11185
11186
11187 class Problem
11188 {
11189
11190
11191
11192
11193 protected $reasonSeen;
11194
11195
11196
11197
11198
11199 protected $reasons = array();
11200
11201 protected $section = 0;
11202
11203 protected $pool;
11204
11205 public function __construct(Pool $pool)
11206 {
11207 $this->pool = $pool;
11208 }
11209
11210
11211
11212
11213
11214
11215 public function addRule(Rule $rule)
11216 {
11217 $this->addReason(spl_object_hash($rule), array(
11218 'rule' => $rule,
11219 'job' => $rule->getJob(),
11220 ));
11221 }
11222
11223
11224
11225
11226
11227
11228 public function getReasons()
11229 {
11230 return $this->reasons;
11231 }
11232
11233
11234
11235
11236
11237
11238
11239 public function getPrettyString(array $installedMap = array())
11240 {
11241 $reasons = call_user_func_array('array_merge', array_reverse($this->reasons));
11242
11243 if (count($reasons) === 1) {
11244 reset($reasons);
11245 $reason = current($reasons);
11246
11247 $rule = $reason['rule'];
11248 $job = $reason['job'];
11249
11250 if (isset($job['constraint'])) {
11251 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
11252 } else {
11253 $packages = array();
11254 }
11255
11256 if ($job && $job['cmd'] === 'install' && empty($packages)) {
11257
11258
11259  if ($job['packageName'] === 'php' || $job['packageName'] === 'php-64bit' || $job['packageName'] === 'hhvm') {
11260 $available = $this->pool->whatProvides($job['packageName']);
11261 $version = count($available) ? $available[0]->getPrettyVersion() : phpversion();
11262
11263 $msg = "\n    - This package requires ".$job['packageName'].$this->constraintToText($job['constraint']).' but ';
11264
11265 if (defined('HHVM_VERSION')) {
11266 return $msg . 'your HHVM version does not satisfy that requirement.';
11267 }
11268
11269 if ($job['packageName'] === 'hhvm') {
11270 return $msg . 'you are running this with PHP and not HHVM.';
11271 }
11272
11273 return $msg . 'your PHP version ('. $version .') does not satisfy that requirement.';
11274 }
11275
11276
11277  if (0 === stripos($job['packageName'], 'ext-')) {
11278 $ext = substr($job['packageName'], 4);
11279 $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
11280
11281 return "\n    - The requested PHP extension ".$job['packageName'].$this->constraintToText($job['constraint']).' '.$error.'. Install or enable PHP\'s '.$ext.' extension.';
11282 }
11283
11284
11285  if (0 === stripos($job['packageName'], 'lib-')) {
11286 if (strtolower($job['packageName']) === 'lib-icu') {
11287 $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.';
11288
11289 return "\n    - The requested linked library ".$job['packageName'].$this->constraintToText($job['constraint']).' '.$error;
11290 }
11291
11292 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.';
11293 }
11294
11295 if (!preg_match('{^[A-Za-z0-9_./-]+$}', $job['packageName'])) {
11296 $illegalChars = preg_replace('{[A-Za-z0-9_./-]+}', '', $job['packageName']);
11297
11298 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.';
11299 }
11300
11301 if ($providers = $this->pool->whatProvides($job['packageName'], $job['constraint'], true, true)) {
11302 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.';
11303 }
11304
11305 if ($providers = $this->pool->whatProvides($job['packageName'], null, true, true)) {
11306 return "\n    - The requested package ".$job['packageName'].$this->constraintToText($job['constraint']).' exists as '.$this->getPackageList($providers).' but these are rejected by your constraint.';
11307 }
11308
11309 return "\n    - The requested package ".$job['packageName'].' could not be found in any version, there may be a typo in the package name.';
11310 }
11311 }
11312
11313 $messages = array();
11314
11315 foreach ($reasons as $reason) {
11316 $rule = $reason['rule'];
11317 $job = $reason['job'];
11318
11319 if ($job) {
11320 $messages[] = $this->jobToText($job);
11321 } elseif ($rule) {
11322 if ($rule instanceof Rule) {
11323 $messages[] = $rule->getPrettyString($this->pool, $installedMap);
11324 }
11325 }
11326 }
11327
11328 return "\n    - ".implode("\n    - ", $messages);
11329 }
11330
11331
11332
11333
11334
11335
11336
11337 protected function addReason($id, $reason)
11338 {
11339 if (!isset($this->reasonSeen[$id])) {
11340 $this->reasonSeen[$id] = true;
11341 $this->reasons[$this->section][] = $reason;
11342 }
11343 }
11344
11345 public function nextSection()
11346 {
11347 $this->section++;
11348 }
11349
11350
11351
11352
11353
11354
11355
11356 protected function jobToText($job)
11357 {
11358 switch ($job['cmd']) {
11359 case 'install':
11360 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
11361 if (!$packages) {
11362 return 'No package found to satisfy install request for '.$job['packageName'].$this->constraintToText($job['constraint']);
11363 }
11364
11365 return 'Installation request for '.$job['packageName'].$this->constraintToText($job['constraint']).' -> satisfiable by '.$this->getPackageList($packages).'.';
11366 case 'update':
11367 return 'Update request for '.$job['packageName'].$this->constraintToText($job['constraint']).'.';
11368 case 'remove':
11369 return 'Removal request for '.$job['packageName'].$this->constraintToText($job['constraint']).'';
11370 }
11371
11372 if (isset($job['constraint'])) {
11373 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
11374 } else {
11375 $packages = array();
11376 }
11377
11378 return 'Job(cmd='.$job['cmd'].', target='.$job['packageName'].', packages=['.$this->getPackageList($packages).'])';
11379 }
11380
11381 protected function getPackageList($packages)
11382 {
11383 $prepared = array();
11384 foreach ($packages as $package) {
11385 $prepared[$package->getName()]['name'] = $package->getPrettyName();
11386 $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
11387 }
11388 foreach ($prepared as $name => $package) {
11389 $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
11390 }
11391
11392 return implode(', ', $prepared);
11393 }
11394
11395
11396
11397
11398
11399
11400
11401 protected function constraintToText($constraint)
11402 {
11403 return ($constraint) ? ' '.$constraint->getPrettyString() : '';
11404 }
11405 }
11406 <?php
11407
11408
11409
11410
11411
11412
11413
11414
11415
11416
11417
11418 namespace Composer\DependencyResolver;
11419
11420 use Composer\Semver\Constraint\ConstraintInterface;
11421
11422
11423
11424
11425 class Request
11426 {
11427 protected $jobs;
11428
11429 public function __construct()
11430 {
11431 $this->jobs = array();
11432 }
11433
11434 public function install($packageName, ConstraintInterface $constraint = null)
11435 {
11436 $this->addJob($packageName, 'install', $constraint);
11437 }
11438
11439 public function update($packageName, ConstraintInterface $constraint = null)
11440 {
11441 $this->addJob($packageName, 'update', $constraint);
11442 }
11443
11444 public function remove($packageName, ConstraintInterface $constraint = null)
11445 {
11446 $this->addJob($packageName, 'remove', $constraint);
11447 }
11448
11449
11450
11451
11452
11453
11454
11455
11456
11457 public function fix($packageName, ConstraintInterface $constraint = null)
11458 {
11459 $this->addJob($packageName, 'install', $constraint, true);
11460 }
11461
11462 protected function addJob($packageName, $cmd, ConstraintInterface $constraint = null, $fixed = false)
11463 {
11464 $packageName = strtolower($packageName);
11465
11466 $this->jobs[] = array(
11467 'cmd' => $cmd,
11468 'packageName' => $packageName,
11469 'constraint' => $constraint,
11470 'fixed' => $fixed,
11471 );
11472 }
11473
11474 public function updateAll()
11475 {
11476 $this->jobs[] = array('cmd' => 'update-all');
11477 }
11478
11479 public function getJobs()
11480 {
11481 return $this->jobs;
11482 }
11483 }
11484 <?php
11485
11486
11487
11488
11489
11490
11491
11492
11493
11494
11495
11496 namespace Composer\DependencyResolver;
11497
11498 use Composer\Package\CompletePackage;
11499 use Composer\Package\Link;
11500 use Composer\Package\PackageInterface;
11501
11502
11503
11504
11505
11506 abstract class Rule
11507 {
11508
11509  const RULE_INTERNAL_ALLOW_UPDATE = 1;
11510 const RULE_JOB_INSTALL = 2;
11511 const RULE_JOB_REMOVE = 3;
11512 const RULE_PACKAGE_CONFLICT = 6;
11513 const RULE_PACKAGE_REQUIRES = 7;
11514 const RULE_PACKAGE_OBSOLETES = 8;
11515 const RULE_INSTALLED_PACKAGE_OBSOLETES = 9;
11516 const RULE_PACKAGE_SAME_NAME = 10;
11517 const RULE_PACKAGE_IMPLICIT_OBSOLETES = 11;
11518 const RULE_LEARNED = 12;
11519 const RULE_PACKAGE_ALIAS = 13;
11520
11521
11522  const BITFIELD_TYPE = 0;
11523 const BITFIELD_REASON = 8;
11524 const BITFIELD_DISABLED = 16;
11525
11526 protected $bitfield;
11527 protected $reasonData;
11528
11529
11530
11531
11532
11533
11534 public function __construct($reason, $reasonData, $job = null)
11535 {
11536 $this->reasonData = $reasonData;
11537
11538 if ($job) {
11539 $this->job = $job;
11540 }
11541
11542 $this->bitfield = (0 << self::BITFIELD_DISABLED) |
11543 ($reason << self::BITFIELD_REASON) |
11544 (255 << self::BITFIELD_TYPE);
11545 }
11546
11547 abstract public function getLiterals();
11548
11549 abstract public function getHash();
11550
11551 public function getJob()
11552 {
11553 return isset($this->job) ? $this->job : null;
11554 }
11555
11556 abstract public function equals(Rule $rule);
11557
11558 public function getReason()
11559 {
11560 return ($this->bitfield & (255 << self::BITFIELD_REASON)) >> self::BITFIELD_REASON;
11561 }
11562
11563 public function getReasonData()
11564 {
11565 return $this->reasonData;
11566 }
11567
11568 public function getRequiredPackage()
11569 {
11570 if ($this->getReason() === self::RULE_JOB_INSTALL) {
11571 return $this->reasonData;
11572 }
11573
11574 if ($this->getReason() === self::RULE_PACKAGE_REQUIRES) {
11575 return $this->reasonData->getTarget();
11576 }
11577 }
11578
11579 public function setType($type)
11580 {
11581 $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_TYPE)) | ((255 & $type) << self::BITFIELD_TYPE);
11582 }
11583
11584 public function getType()
11585 {
11586 return ($this->bitfield & (255 << self::BITFIELD_TYPE)) >> self::BITFIELD_TYPE;
11587 }
11588
11589 public function disable()
11590 {
11591 $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_DISABLED)) | (1 << self::BITFIELD_DISABLED);
11592 }
11593
11594 public function enable()
11595 {
11596 $this->bitfield = $this->bitfield & ~(255 << self::BITFIELD_DISABLED);
11597 }
11598
11599 public function isDisabled()
11600 {
11601 return (bool) (($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
11602 }
11603
11604 public function isEnabled()
11605 {
11606 return !(($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
11607 }
11608
11609 abstract public function isAssertion();
11610
11611 public function getPrettyString(Pool $pool, array $installedMap = array())
11612 {
11613 $literals = $this->getLiterals();
11614
11615 $ruleText = '';
11616 foreach ($literals as $i => $literal) {
11617 if ($i != 0) {
11618 $ruleText .= '|';
11619 }
11620 $ruleText .= $pool->literalToPrettyString($literal, $installedMap);
11621 }
11622
11623 switch ($this->getReason()) {
11624 case self::RULE_INTERNAL_ALLOW_UPDATE:
11625 return $ruleText;
11626
11627 case self::RULE_JOB_INSTALL:
11628 return "Install command rule ($ruleText)";
11629
11630 case self::RULE_JOB_REMOVE:
11631 return "Remove command rule ($ruleText)";
11632
11633 case self::RULE_PACKAGE_CONFLICT:
11634 $package1 = $pool->literalToPackage($literals[0]);
11635 $package2 = $pool->literalToPackage($literals[1]);
11636
11637 return $package1->getPrettyString().' conflicts with '.$this->formatPackagesUnique($pool, array($package2)).'.';
11638
11639 case self::RULE_PACKAGE_REQUIRES:
11640 $sourceLiteral = array_shift($literals);
11641 $sourcePackage = $pool->literalToPackage($sourceLiteral);
11642
11643 $requires = array();
11644 foreach ($literals as $literal) {
11645 $requires[] = $pool->literalToPackage($literal);
11646 }
11647
11648 $text = $this->reasonData->getPrettyString($sourcePackage);
11649 if ($requires) {
11650 $text .= ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $requires) . '.';
11651 } else {
11652 $targetName = $this->reasonData->getTarget();
11653
11654 if ($targetName === 'php' || $targetName === 'php-64bit' || $targetName === 'hhvm') {
11655
11656  if (defined('HHVM_VERSION')) {
11657 return $text . ' -> your HHVM version does not satisfy that requirement.';
11658 }
11659
11660 if ($targetName === 'hhvm') {
11661 return $text . ' -> you are running this with PHP and not HHVM.';
11662 }
11663
11664 $packages = $pool->whatProvides($targetName);
11665 $package = count($packages) ? current($packages) : phpversion();
11666
11667 if (!($package instanceof CompletePackage)) {
11668 return $text . ' -> your PHP version ('.phpversion().') does not satisfy that requirement.';
11669 }
11670
11671 $extra = $package->getExtra();
11672
11673 if (!empty($extra['config.platform'])) {
11674 $text .= ' -> your PHP version ('.phpversion().') overridden by "config.platform.php" version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
11675 } else {
11676 $text .= ' -> your PHP version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
11677 }
11678
11679 return $text;
11680 }
11681
11682 if (0 === strpos($targetName, 'ext-')) {
11683
11684  $ext = substr($targetName, 4);
11685 $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
11686
11687 return $text . ' -> the requested PHP extension '.$ext.' '.$error.'.';
11688 }
11689
11690 if (0 === strpos($targetName, 'lib-')) {
11691
11692  $lib = substr($targetName, 4);
11693
11694 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.';
11695 }
11696
11697 if ($providers = $pool->whatProvides($targetName, $this->reasonData->getConstraint(), true, true)) {
11698 return $text . ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $providers) .' but these conflict with your requirements or minimum-stability.';
11699 }
11700
11701 return $text . ' -> no matching package found.';
11702 }
11703
11704 return $text;
11705
11706 case self::RULE_PACKAGE_OBSOLETES:
11707 return $ruleText;
11708 case self::RULE_INSTALLED_PACKAGE_OBSOLETES:
11709 return $ruleText;
11710 case self::RULE_PACKAGE_SAME_NAME:
11711 return 'Can only install one of: ' . $this->formatPackagesUnique($pool, $literals) . '.';
11712 case self::RULE_PACKAGE_IMPLICIT_OBSOLETES:
11713 return $ruleText;
11714 case self::RULE_LEARNED:
11715 return 'Conclusion: '.$ruleText;
11716 case self::RULE_PACKAGE_ALIAS:
11717 return $ruleText;
11718 default:
11719 return '('.$ruleText.')';
11720 }
11721 }
11722
11723
11724
11725
11726
11727
11728
11729 protected function formatPackagesUnique($pool, array $packages)
11730 {
11731 $prepared = array();
11732 foreach ($packages as $package) {
11733 if (!is_object($package)) {
11734 $package = $pool->literalToPackage($package);
11735 }
11736 $prepared[$package->getName()]['name'] = $package->getPrettyName();
11737 $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
11738 }
11739 foreach ($prepared as $name => $package) {
11740 $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
11741 }
11742
11743 return implode(', ', $prepared);
11744 }
11745 }
11746 <?php
11747
11748
11749
11750
11751
11752
11753
11754
11755
11756
11757
11758 namespace Composer\DependencyResolver;
11759
11760 use Composer\Package\PackageInterface;
11761 use Composer\Package\Link;
11762
11763
11764
11765
11766 class Rule2Literals extends Rule
11767 {
11768 protected $literal1;
11769 protected $literal2;
11770
11771
11772
11773
11774
11775
11776
11777
11778 public function __construct($literal1, $literal2, $reason, $reasonData, $job = null)
11779 {
11780 parent::__construct($reason, $reasonData, $job);
11781
11782 if ($literal1 < $literal2) {
11783 $this->literal1 = $literal1;
11784 $this->literal2 = $literal2;
11785 } else {
11786 $this->literal1 = $literal2;
11787 $this->literal2 = $literal1;
11788 }
11789 }
11790
11791 public function getLiterals()
11792 {
11793 return array($this->literal1, $this->literal2);
11794 }
11795
11796 public function getHash()
11797 {
11798 $data = unpack('ihash', md5($this->literal1.','.$this->literal2, true));
11799
11800 return $data['hash'];
11801 }
11802
11803
11804
11805
11806
11807
11808
11809
11810
11811 public function equals(Rule $rule)
11812 {
11813 $literals = $rule->getLiterals();
11814 if (2 != count($literals)) {
11815 return false;
11816 }
11817
11818 if ($this->literal1 !== $literals[0]) {
11819 return false;
11820 }
11821
11822 if ($this->literal2 !== $literals[1]) {
11823 return false;
11824 }
11825
11826 return true;
11827 }
11828
11829 public function isAssertion()
11830 {
11831 return false;
11832 }
11833
11834
11835
11836
11837
11838
11839 public function __toString()
11840 {
11841 $result = ($this->isDisabled()) ? 'disabled(' : '(';
11842
11843 $result .= $this->literal1 . '|' . $this->literal2 . ')';
11844
11845 return $result;
11846 }
11847 }
11848 <?php
11849
11850
11851
11852
11853
11854
11855
11856
11857
11858
11859
11860 namespace Composer\DependencyResolver;
11861
11862
11863
11864
11865 class RuleSet implements \IteratorAggregate, \Countable
11866 {
11867
11868  const TYPE_PACKAGE = 0;
11869 const TYPE_JOB = 1;
11870 const TYPE_LEARNED = 4;
11871
11872
11873
11874
11875
11876
11877 public $ruleById;
11878
11879 protected static $types = array(
11880 255 => 'UNKNOWN',
11881 self::TYPE_PACKAGE => 'PACKAGE',
11882 self::TYPE_JOB => 'JOB',
11883 self::TYPE_LEARNED => 'LEARNED',
11884 );
11885
11886 protected $rules;
11887 protected $nextRuleId;
11888
11889 protected $rulesByHash;
11890
11891 public function __construct()
11892 {
11893 $this->nextRuleId = 0;
11894
11895 foreach ($this->getTypes() as $type) {
11896 $this->rules[$type] = array();
11897 }
11898
11899 $this->rulesByHash = array();
11900 }
11901
11902 public function add(Rule $rule, $type)
11903 {
11904 if (!isset(self::$types[$type])) {
11905 throw new \OutOfBoundsException('Unknown rule type: ' . $type);
11906 }
11907
11908 $hash = $rule->getHash();
11909
11910
11911  if (isset($this->rulesByHash[$hash])) {
11912 $potentialDuplicates = $this->rulesByHash[$hash];
11913 if (is_array($potentialDuplicates)) {
11914 foreach ($potentialDuplicates as $potentialDuplicate) {
11915 if ($rule->equals($potentialDuplicate)) {
11916 return;
11917 }
11918 }
11919 } else {
11920 if ($rule->equals($potentialDuplicates)) {
11921 return;
11922 }
11923 }
11924 }
11925
11926 if (!isset($this->rules[$type])) {
11927 $this->rules[$type] = array();
11928 }
11929
11930 $this->rules[$type][] = $rule;
11931 $this->ruleById[$this->nextRuleId] = $rule;
11932 $rule->setType($type);
11933
11934 $this->nextRuleId++;
11935
11936 if (!isset($this->rulesByHash[$hash])) {
11937 $this->rulesByHash[$hash] = $rule;
11938 } elseif (is_array($this->rulesByHash[$hash])) {
11939 $this->rulesByHash[$hash][] = $rule;
11940 } else {
11941 $originalRule = $this->rulesByHash[$hash];
11942 $this->rulesByHash[$hash] = array($originalRule, $rule);
11943 }
11944 }
11945
11946 public function count()
11947 {
11948 return $this->nextRuleId;
11949 }
11950
11951 public function ruleById($id)
11952 {
11953 return $this->ruleById[$id];
11954 }
11955
11956 public function getRules()
11957 {
11958 return $this->rules;
11959 }
11960
11961 public function getIterator()
11962 {
11963 return new RuleSetIterator($this->getRules());
11964 }
11965
11966 public function getIteratorFor($types)
11967 {
11968 if (!is_array($types)) {
11969 $types = array($types);
11970 }
11971
11972 $allRules = $this->getRules();
11973 $rules = array();
11974
11975 foreach ($types as $type) {
11976 $rules[$type] = $allRules[$type];
11977 }
11978
11979 return new RuleSetIterator($rules);
11980 }
11981
11982 public function getIteratorWithout($types)
11983 {
11984 if (!is_array($types)) {
11985 $types = array($types);
11986 }
11987
11988 $rules = $this->getRules();
11989
11990 foreach ($types as $type) {
11991 unset($rules[$type]);
11992 }
11993
11994 return new RuleSetIterator($rules);
11995 }
11996
11997 public function getTypes()
11998 {
11999 $types = self::$types;
12000 unset($types[255]);
12001
12002 return array_keys($types);
12003 }
12004
12005 public function getPrettyString(Pool $pool = null)
12006 {
12007 $string = "\n";
12008 foreach ($this->rules as $type => $rules) {
12009 $string .= str_pad(self::$types[$type], 8, ' ') . ": ";
12010 foreach ($rules as $rule) {
12011 $string .= ($pool ? $rule->getPrettyString($pool) : $rule)."\n";
12012 }
12013 $string .= "\n\n";
12014 }
12015
12016 return $string;
12017 }
12018
12019 public function __toString()
12020 {
12021 return $this->getPrettyString(null);
12022 }
12023 }
12024 <?php
12025
12026
12027
12028
12029
12030
12031
12032
12033
12034
12035
12036 namespace Composer\DependencyResolver;
12037
12038 use Composer\Package\PackageInterface;
12039 use Composer\Package\AliasPackage;
12040 use Composer\Repository\PlatformRepository;
12041
12042
12043
12044
12045 class RuleSetGenerator
12046 {
12047 protected $policy;
12048 protected $pool;
12049 protected $rules;
12050 protected $jobs;
12051 protected $installedMap;
12052 protected $whitelistedMap;
12053 protected $addedMap;
12054
12055 public function __construct(PolicyInterface $policy, Pool $pool)
12056 {
12057 $this->policy = $policy;
12058 $this->pool = $pool;
12059 }
12060
12061
12062
12063
12064
12065
12066
12067
12068
12069
12070
12071
12072
12073
12074
12075 protected function createRequireRule(PackageInterface $package, array $providers, $reason, $reasonData = null)
12076 {
12077 $literals = array(-$package->id);
12078
12079 foreach ($providers as $provider) {
12080
12081  if ($provider === $package) {
12082 return null;
12083 }
12084 $literals[] = $provider->id;
12085 }
12086
12087 return new GenericRule($literals, $reason, $reasonData);
12088 }
12089
12090
12091
12092
12093
12094
12095
12096
12097
12098
12099
12100
12101
12102 protected function createInstallOneOfRule(array $packages, $reason, $job)
12103 {
12104 $literals = array();
12105 foreach ($packages as $package) {
12106 $literals[] = $package->id;
12107 }
12108
12109 return new GenericRule($literals, $reason, $job['packageName'], $job);
12110 }
12111
12112
12113
12114
12115
12116
12117
12118
12119
12120
12121
12122
12123 protected function createRemoveRule(PackageInterface $package, $reason, $job)
12124 {
12125 return new GenericRule(array(-$package->id), $reason, $job['packageName'], $job);
12126 }
12127
12128
12129
12130
12131
12132
12133
12134
12135
12136
12137
12138
12139
12140
12141
12142 protected function createRule2Literals(PackageInterface $issuer, PackageInterface $provider, $reason, $reasonData = null)
12143 {
12144
12145  if ($issuer === $provider) {
12146 return null;
12147 }
12148
12149 return new Rule2Literals(-$issuer->id, -$provider->id, $reason, $reasonData);
12150 }
12151
12152
12153
12154
12155
12156
12157
12158
12159
12160
12161 private function addRule($type, Rule $newRule = null)
12162 {
12163 if (!$newRule) {
12164 return;
12165 }
12166
12167 $this->rules->add($newRule, $type);
12168 }
12169
12170 protected function whitelistFromPackage(PackageInterface $package)
12171 {
12172 $workQueue = new \SplQueue;
12173 $workQueue->enqueue($package);
12174
12175 while (!$workQueue->isEmpty()) {
12176 $package = $workQueue->dequeue();
12177 if (isset($this->whitelistedMap[$package->id])) {
12178 continue;
12179 }
12180
12181 $this->whitelistedMap[$package->id] = true;
12182
12183 foreach ($package->getRequires() as $link) {
12184 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint(), true);
12185
12186 foreach ($possibleRequires as $require) {
12187 $workQueue->enqueue($require);
12188 }
12189 }
12190
12191 $obsoleteProviders = $this->pool->whatProvides($package->getName(), null, true);
12192
12193 foreach ($obsoleteProviders as $provider) {
12194 if ($provider === $package) {
12195 continue;
12196 }
12197
12198 if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
12199 $workQueue->enqueue($provider);
12200 }
12201 }
12202 }
12203 }
12204
12205 protected function addRulesForPackage(PackageInterface $package, $ignorePlatformReqs)
12206 {
12207 $workQueue = new \SplQueue;
12208 $workQueue->enqueue($package);
12209
12210 while (!$workQueue->isEmpty()) {
12211 $package = $workQueue->dequeue();
12212 if (isset($this->addedMap[$package->id])) {
12213 continue;
12214 }
12215
12216 $this->addedMap[$package->id] = true;
12217
12218 foreach ($package->getRequires() as $link) {
12219 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
12220 continue;
12221 }
12222
12223 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
12224
12225 $this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createRequireRule($package, $possibleRequires, Rule::RULE_PACKAGE_REQUIRES, $link));
12226
12227 foreach ($possibleRequires as $require) {
12228 $workQueue->enqueue($require);
12229 }
12230 }
12231
12232 foreach ($package->getConflicts() as $link) {
12233 $possibleConflicts = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
12234
12235 foreach ($possibleConflicts as $conflict) {
12236 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $conflict, Rule::RULE_PACKAGE_CONFLICT, $link));
12237 }
12238 }
12239
12240
12241  $isInstalled = (isset($this->installedMap[$package->id]));
12242
12243 foreach ($package->getReplaces() as $link) {
12244 $obsoleteProviders = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
12245
12246 foreach ($obsoleteProviders as $provider) {
12247 if ($provider === $package) {
12248 continue;
12249 }
12250
12251 if (!$this->obsoleteImpossibleForAlias($package, $provider)) {
12252 $reason = ($isInstalled) ? Rule::RULE_INSTALLED_PACKAGE_OBSOLETES : Rule::RULE_PACKAGE_OBSOLETES;
12253 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $provider, $reason, $link));
12254 }
12255 }
12256 }
12257
12258 $obsoleteProviders = $this->pool->whatProvides($package->getName(), null);
12259
12260 foreach ($obsoleteProviders as $provider) {
12261 if ($provider === $package) {
12262 continue;
12263 }
12264
12265 if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
12266 $this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createRequireRule($package, array($provider), Rule::RULE_PACKAGE_ALIAS, $package));
12267 } elseif (!$this->obsoleteImpossibleForAlias($package, $provider)) {
12268 $reason = ($package->getName() == $provider->getName()) ? Rule::RULE_PACKAGE_SAME_NAME : Rule::RULE_PACKAGE_IMPLICIT_OBSOLETES;
12269 $this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createRule2Literals($package, $provider, $reason, $package));
12270 }
12271 }
12272 }
12273 }
12274
12275 protected function obsoleteImpossibleForAlias($package, $provider)
12276 {
12277 $packageIsAlias = $package instanceof AliasPackage;
12278 $providerIsAlias = $provider instanceof AliasPackage;
12279
12280 $impossible = (
12281 ($packageIsAlias && $package->getAliasOf() === $provider) ||
12282 ($providerIsAlias && $provider->getAliasOf() === $package) ||
12283 ($packageIsAlias && $providerIsAlias && $provider->getAliasOf() === $package->getAliasOf())
12284 );
12285
12286 return $impossible;
12287 }
12288
12289 protected function whitelistFromJobs()
12290 {
12291 foreach ($this->jobs as $job) {
12292 switch ($job['cmd']) {
12293 case 'install':
12294 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint'], true);
12295 foreach ($packages as $package) {
12296 $this->whitelistFromPackage($package);
12297 }
12298 break;
12299 }
12300 }
12301 }
12302
12303 protected function addRulesForJobs($ignorePlatformReqs)
12304 {
12305 foreach ($this->jobs as $job) {
12306 switch ($job['cmd']) {
12307 case 'install':
12308 if (!$job['fixed'] && $ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
12309 continue;
12310 }
12311
12312 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
12313 if ($packages) {
12314 foreach ($packages as $package) {
12315 if (!isset($this->installedMap[$package->id])) {
12316 $this->addRulesForPackage($package, $ignorePlatformReqs);
12317 }
12318 }
12319
12320 $rule = $this->createInstallOneOfRule($packages, Rule::RULE_JOB_INSTALL, $job);
12321 $this->addRule(RuleSet::TYPE_JOB, $rule);
12322 }
12323 break;
12324 case 'remove':
12325
12326  
12327  $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
12328 foreach ($packages as $package) {
12329 $rule = $this->createRemoveRule($package, Rule::RULE_JOB_REMOVE, $job);
12330 $this->addRule(RuleSet::TYPE_JOB, $rule);
12331 }
12332 break;
12333 }
12334 }
12335 }
12336
12337 public function getRulesFor($jobs, $installedMap, $ignorePlatformReqs = false)
12338 {
12339 $this->jobs = $jobs;
12340 $this->rules = new RuleSet;
12341 $this->installedMap = $installedMap;
12342
12343 $this->whitelistedMap = array();
12344 foreach ($this->installedMap as $package) {
12345 $this->whitelistFromPackage($package);
12346 }
12347 $this->whitelistFromJobs();
12348
12349 $this->pool->setWhitelist($this->whitelistedMap);
12350
12351 $this->addedMap = array();
12352 foreach ($this->installedMap as $package) {
12353 $this->addRulesForPackage($package, $ignorePlatformReqs);
12354 }
12355
12356 $this->addRulesForJobs($ignorePlatformReqs);
12357
12358 return $this->rules;
12359 }
12360 }
12361 <?php
12362
12363
12364
12365
12366
12367
12368
12369
12370
12371
12372
12373 namespace Composer\DependencyResolver;
12374
12375
12376
12377
12378 class RuleSetIterator implements \Iterator
12379 {
12380 protected $rules;
12381 protected $types;
12382
12383 protected $currentOffset;
12384 protected $currentType;
12385 protected $currentTypeOffset;
12386
12387 public function __construct(array $rules)
12388 {
12389 $this->rules = $rules;
12390 $this->types = array_keys($rules);
12391 sort($this->types);
12392
12393 $this->rewind();
12394 }
12395
12396 public function current()
12397 {
12398 return $this->rules[$this->currentType][$this->currentOffset];
12399 }
12400
12401 public function key()
12402 {
12403 return $this->currentType;
12404 }
12405
12406 public function next()
12407 {
12408 $this->currentOffset++;
12409
12410 if (!isset($this->rules[$this->currentType])) {
12411 return;
12412 }
12413
12414 if ($this->currentOffset >= sizeof($this->rules[$this->currentType])) {
12415 $this->currentOffset = 0;
12416
12417 do {
12418 $this->currentTypeOffset++;
12419
12420 if (!isset($this->types[$this->currentTypeOffset])) {
12421 $this->currentType = -1;
12422 break;
12423 }
12424
12425 $this->currentType = $this->types[$this->currentTypeOffset];
12426 } while (isset($this->types[$this->currentTypeOffset]) && !sizeof($this->rules[$this->currentType]));
12427 }
12428 }
12429
12430 public function rewind()
12431 {
12432 $this->currentOffset = 0;
12433
12434 $this->currentTypeOffset = -1;
12435 $this->currentType = -1;
12436
12437 do {
12438 $this->currentTypeOffset++;
12439
12440 if (!isset($this->types[$this->currentTypeOffset])) {
12441 $this->currentType = -1;
12442 break;
12443 }
12444
12445 $this->currentType = $this->types[$this->currentTypeOffset];
12446 } while (isset($this->types[$this->currentTypeOffset]) && !sizeof($this->rules[$this->currentType]));
12447 }
12448
12449 public function valid()
12450 {
12451 return isset($this->rules[$this->currentType])
12452 && isset($this->rules[$this->currentType][$this->currentOffset]);
12453 }
12454 }
12455 <?php
12456
12457
12458
12459
12460
12461
12462
12463
12464
12465
12466
12467 namespace Composer\DependencyResolver;
12468
12469
12470
12471
12472
12473
12474
12475
12476
12477 class RuleWatchChain extends \SplDoublyLinkedList
12478 {
12479 protected $offset = 0;
12480
12481
12482
12483
12484
12485
12486 public function seek($offset)
12487 {
12488 $this->rewind();
12489 for ($i = 0; $i < $offset; $i++, $this->next());
12490 }
12491
12492
12493
12494
12495
12496
12497
12498
12499
12500 public function remove()
12501 {
12502 $offset = $this->key();
12503 $this->offsetUnset($offset);
12504 $this->seek($offset);
12505 }
12506 }
12507 <?php
12508
12509
12510
12511
12512
12513
12514
12515
12516
12517
12518
12519 namespace Composer\DependencyResolver;
12520
12521
12522
12523
12524
12525
12526
12527
12528
12529
12530
12531 class RuleWatchGraph
12532 {
12533 protected $watchChains = array();
12534
12535
12536
12537
12538
12539
12540
12541
12542
12543
12544
12545
12546
12547 public function insert(RuleWatchNode $node)
12548 {
12549 if ($node->getRule()->isAssertion()) {
12550 return;
12551 }
12552
12553 foreach (array($node->watch1, $node->watch2) as $literal) {
12554 if (!isset($this->watchChains[$literal])) {
12555 $this->watchChains[$literal] = new RuleWatchChain;
12556 }
12557
12558 $this->watchChains[$literal]->unshift($node);
12559 }
12560 }
12561
12562
12563
12564
12565
12566
12567
12568
12569
12570
12571
12572
12573
12574
12575
12576
12577
12578
12579
12580
12581
12582
12583
12584
12585 public function propagateLiteral($decidedLiteral, $level, $decisions)
12586 {
12587
12588  
12589  
12590  $literal = -$decidedLiteral;
12591
12592 if (!isset($this->watchChains[$literal])) {
12593 return null;
12594 }
12595
12596 $chain = $this->watchChains[$literal];
12597
12598 $chain->rewind();
12599 while ($chain->valid()) {
12600 $node = $chain->current();
12601 $otherWatch = $node->getOtherWatch($literal);
12602
12603 if (!$node->getRule()->isDisabled() && !$decisions->satisfy($otherWatch)) {
12604 $ruleLiterals = $node->getRule()->getLiterals();
12605
12606 $alternativeLiterals = array_filter($ruleLiterals, function ($ruleLiteral) use ($literal, $otherWatch, $decisions) {
12607 return $literal !== $ruleLiteral &&
12608 $otherWatch !== $ruleLiteral &&
12609 !$decisions->conflict($ruleLiteral);
12610 });
12611
12612 if ($alternativeLiterals) {
12613 reset($alternativeLiterals);
12614 $this->moveWatch($literal, current($alternativeLiterals), $node);
12615 continue;
12616 }
12617
12618 if ($decisions->conflict($otherWatch)) {
12619 return $node->getRule();
12620 }
12621
12622 $decisions->decide($otherWatch, $level, $node->getRule());
12623 }
12624
12625 $chain->next();
12626 }
12627
12628 return null;
12629 }
12630
12631
12632
12633
12634
12635
12636
12637
12638
12639
12640 protected function moveWatch($fromLiteral, $toLiteral, $node)
12641 {
12642 if (!isset($this->watchChains[$toLiteral])) {
12643 $this->watchChains[$toLiteral] = new RuleWatchChain;
12644 }
12645
12646 $node->moveWatch($fromLiteral, $toLiteral);
12647 $this->watchChains[$fromLiteral]->remove();
12648 $this->watchChains[$toLiteral]->unshift($node);
12649 }
12650 }
12651 <?php
12652
12653
12654
12655
12656
12657
12658
12659
12660
12661
12662
12663 namespace Composer\DependencyResolver;
12664
12665
12666
12667
12668
12669
12670
12671
12672 class RuleWatchNode
12673 {
12674 public $watch1;
12675 public $watch2;
12676
12677 protected $rule;
12678
12679
12680
12681
12682
12683
12684 public function __construct($rule)
12685 {
12686 $this->rule = $rule;
12687
12688 $literals = $rule->getLiterals();
12689
12690 $this->watch1 = count($literals) > 0 ? $literals[0] : 0;
12691 $this->watch2 = count($literals) > 1 ? $literals[1] : 0;
12692 }
12693
12694
12695
12696
12697
12698
12699
12700
12701
12702 public function watch2OnHighest(Decisions $decisions)
12703 {
12704 $literals = $this->rule->getLiterals();
12705
12706
12707  if (count($literals) < 3) {
12708 return;
12709 }
12710
12711 $watchLevel = 0;
12712
12713 foreach ($literals as $literal) {
12714 $level = $decisions->decisionLevel($literal);
12715
12716 if ($level > $watchLevel) {
12717 $this->watch2 = $literal;
12718 $watchLevel = $level;
12719 }
12720 }
12721 }
12722
12723
12724
12725
12726
12727
12728 public function getRule()
12729 {
12730 return $this->rule;
12731 }
12732
12733
12734
12735
12736
12737
12738
12739 public function getOtherWatch($literal)
12740 {
12741 if ($this->watch1 == $literal) {
12742 return $this->watch2;
12743 } else {
12744 return $this->watch1;
12745 }
12746 }
12747
12748
12749
12750
12751
12752
12753
12754 public function moveWatch($from, $to)
12755 {
12756 if ($this->watch1 == $from) {
12757 $this->watch1 = $to;
12758 } else {
12759 $this->watch2 = $to;
12760 }
12761 }
12762 }
12763 <?php
12764
12765
12766
12767
12768
12769
12770
12771
12772
12773
12774
12775 namespace Composer\DependencyResolver;
12776
12777 use Composer\IO\IOInterface;
12778 use Composer\Repository\RepositoryInterface;
12779 use Composer\Repository\PlatformRepository;
12780
12781
12782
12783
12784 class Solver
12785 {
12786 const BRANCH_LITERALS = 0;
12787 const BRANCH_LEVEL = 1;
12788
12789
12790 protected $policy;
12791
12792 protected $pool;
12793
12794 protected $installed;
12795
12796 protected $rules;
12797
12798 protected $ruleSetGenerator;
12799
12800 protected $jobs;
12801
12802
12803 protected $updateMap = array();
12804
12805 protected $watchGraph;
12806
12807 protected $decisions;
12808
12809 protected $installedMap;
12810
12811
12812 protected $propagateIndex;
12813
12814 protected $branches = array();
12815
12816 protected $problems = array();
12817
12818 protected $learnedPool = array();
12819
12820 protected $learnedWhy = array();
12821
12822
12823 protected $io;
12824
12825
12826
12827
12828
12829
12830
12831 public function __construct(PolicyInterface $policy, Pool $pool, RepositoryInterface $installed, IOInterface $io)
12832 {
12833 $this->io = $io;
12834 $this->policy = $policy;
12835 $this->pool = $pool;
12836 $this->installed = $installed;
12837 $this->ruleSetGenerator = new RuleSetGenerator($policy, $pool);
12838 }
12839
12840
12841
12842
12843 public function getRuleSetSize()
12844 {
12845 return count($this->rules);
12846 }
12847
12848
12849
12850 private function makeAssertionRuleDecisions()
12851 {
12852 $decisionStart = count($this->decisions) - 1;
12853
12854 $rulesCount = count($this->rules);
12855 for ($ruleIndex = 0; $ruleIndex < $rulesCount; $ruleIndex++) {
12856 $rule = $this->rules->ruleById[$ruleIndex];
12857
12858 if (!$rule->isAssertion() || $rule->isDisabled()) {
12859 continue;
12860 }
12861
12862 $literals = $rule->getLiterals();
12863 $literal = $literals[0];
12864
12865 if (!$this->decisions->decided(abs($literal))) {
12866 $this->decisions->decide($literal, 1, $rule);
12867 continue;
12868 }
12869
12870 if ($this->decisions->satisfy($literal)) {
12871 continue;
12872 }
12873
12874
12875  if (RuleSet::TYPE_LEARNED === $rule->getType()) {
12876 $rule->disable();
12877 continue;
12878 }
12879
12880 $conflict = $this->decisions->decisionRule($literal);
12881
12882 if ($conflict && RuleSet::TYPE_PACKAGE === $conflict->getType()) {
12883 $problem = new Problem($this->pool);
12884
12885 $problem->addRule($rule);
12886 $problem->addRule($conflict);
12887 $this->disableProblem($rule);
12888 $this->problems[] = $problem;
12889 continue;
12890 }
12891
12892
12893  $problem = new Problem($this->pool);
12894 $problem->addRule($rule);
12895 $problem->addRule($conflict);
12896
12897
12898  
12899  foreach ($this->rules->getIteratorFor(RuleSet::TYPE_JOB) as $assertRule) {
12900 if ($assertRule->isDisabled() || !$assertRule->isAssertion()) {
12901 continue;
12902 }
12903
12904 $assertRuleLiterals = $assertRule->getLiterals();
12905 $assertRuleLiteral = $assertRuleLiterals[0];
12906
12907 if (abs($literal) !== abs($assertRuleLiteral)) {
12908 continue;
12909 }
12910
12911 $problem->addRule($assertRule);
12912 $this->disableProblem($assertRule);
12913 }
12914 $this->problems[] = $problem;
12915
12916 $this->decisions->resetToOffset($decisionStart);
12917 $ruleIndex = -1;
12918 }
12919 }
12920
12921 protected function setupInstalledMap()
12922 {
12923 $this->installedMap = array();
12924 foreach ($this->installed->getPackages() as $package) {
12925 $this->installedMap[$package->id] = $package;
12926 }
12927 }
12928
12929
12930
12931
12932 protected function checkForRootRequireProblems($ignorePlatformReqs)
12933 {
12934 foreach ($this->jobs as $job) {
12935 switch ($job['cmd']) {
12936 case 'update':
12937 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
12938 foreach ($packages as $package) {
12939 if (isset($this->installedMap[$package->id])) {
12940 $this->updateMap[$package->id] = true;
12941 }
12942 }
12943 break;
12944
12945 case 'update-all':
12946 foreach ($this->installedMap as $package) {
12947 $this->updateMap[$package->id] = true;
12948 }
12949 break;
12950
12951 case 'install':
12952 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
12953 break;
12954 }
12955
12956 if (!$this->pool->whatProvides($job['packageName'], $job['constraint'])) {
12957 $problem = new Problem($this->pool);
12958 $problem->addRule(new GenericRule(array(), null, null, $job));
12959 $this->problems[] = $problem;
12960 }
12961 break;
12962 }
12963 }
12964 }
12965
12966
12967
12968
12969
12970
12971 public function solve(Request $request, $ignorePlatformReqs = false)
12972 {
12973 $this->jobs = $request->getJobs();
12974
12975 $this->setupInstalledMap();
12976 $this->rules = $this->ruleSetGenerator->getRulesFor($this->jobs, $this->installedMap, $ignorePlatformReqs);
12977 $this->checkForRootRequireProblems($ignorePlatformReqs);
12978 $this->decisions = new Decisions($this->pool);
12979 $this->watchGraph = new RuleWatchGraph;
12980
12981 foreach ($this->rules as $rule) {
12982 $this->watchGraph->insert(new RuleWatchNode($rule));
12983 }
12984
12985
12986 $this->makeAssertionRuleDecisions();
12987
12988 $this->io->writeError('Resolving dependencies through SAT', true, IOInterface::DEBUG);
12989 $before = microtime(true);
12990 $this->runSat(true);
12991 $this->io->writeError(sprintf('Dependency resolution completed in %.3f seconds', microtime(true) - $before), true, IOInterface::VERBOSE);
12992
12993
12994  foreach ($this->installedMap as $packageId => $void) {
12995 if ($this->decisions->undecided($packageId)) {
12996 $this->decisions->decide(-$packageId, 1, null);
12997 }
12998 }
12999
13000 if ($this->problems) {
13001 throw new SolverProblemsException($this->problems, $this->installedMap);
13002 }
13003
13004 $transaction = new Transaction($this->policy, $this->pool, $this->installedMap, $this->decisions);
13005
13006 return $transaction->getOperations();
13007 }
13008
13009
13010
13011
13012
13013
13014
13015
13016
13017
13018 protected function propagate($level)
13019 {
13020 while ($this->decisions->validOffset($this->propagateIndex)) {
13021 $decision = $this->decisions->atOffset($this->propagateIndex);
13022
13023 $conflict = $this->watchGraph->propagateLiteral(
13024 $decision[Decisions::DECISION_LITERAL],
13025 $level,
13026 $this->decisions
13027 );
13028
13029 $this->propagateIndex++;
13030
13031 if ($conflict) {
13032 return $conflict;
13033 }
13034 }
13035
13036 return null;
13037 }
13038
13039
13040
13041
13042
13043
13044 private function revert($level)
13045 {
13046 while (!$this->decisions->isEmpty()) {
13047 $literal = $this->decisions->lastLiteral();
13048
13049 if ($this->decisions->undecided($literal)) {
13050 break;
13051 }
13052
13053 $decisionLevel = $this->decisions->decisionLevel($literal);
13054
13055 if ($decisionLevel <= $level) {
13056 break;
13057 }
13058
13059 $this->decisions->revertLast();
13060 $this->propagateIndex = count($this->decisions);
13061 }
13062
13063 while (!empty($this->branches) && $this->branches[count($this->branches) - 1][self::BRANCH_LEVEL] >= $level) {
13064 array_pop($this->branches);
13065 }
13066 }
13067
13068
13069
13070
13071
13072
13073
13074
13075
13076
13077
13078
13079
13080
13081
13082
13083
13084
13085
13086
13087 private function setPropagateLearn($level, $literal, $disableRules, Rule $rule)
13088 {
13089 $level++;
13090
13091 $this->decisions->decide($literal, $level, $rule);
13092
13093 while (true) {
13094 $rule = $this->propagate($level);
13095
13096 if (!$rule) {
13097 break;
13098 }
13099
13100 if ($level == 1) {
13101 return $this->analyzeUnsolvable($rule, $disableRules);
13102 }
13103
13104
13105  list($learnLiteral, $newLevel, $newRule, $why) = $this->analyze($level, $rule);
13106
13107 if ($newLevel <= 0 || $newLevel >= $level) {
13108 throw new SolverBugException(
13109 "Trying to revert to invalid level ".(int) $newLevel." from level ".(int) $level."."
13110 );
13111 } elseif (!$newRule) {
13112 throw new SolverBugException(
13113 "No rule was learned from analyzing $rule at level $level."
13114 );
13115 }
13116
13117 $level = $newLevel;
13118
13119 $this->revert($level);
13120
13121 $this->rules->add($newRule, RuleSet::TYPE_LEARNED);
13122
13123 $this->learnedWhy[spl_object_hash($newRule)] = $why;
13124
13125 $ruleNode = new RuleWatchNode($newRule);
13126 $ruleNode->watch2OnHighest($this->decisions);
13127 $this->watchGraph->insert($ruleNode);
13128
13129 $this->decisions->decide($learnLiteral, $level, $newRule);
13130 }
13131
13132 return $level;
13133 }
13134
13135
13136
13137
13138
13139
13140
13141
13142 private function selectAndInstall($level, array $decisionQueue, $disableRules, Rule $rule)
13143 {
13144
13145  $literals = $this->policy->selectPreferredPackages($this->pool, $this->installedMap, $decisionQueue, $rule->getRequiredPackage());
13146
13147 $selectedLiteral = array_shift($literals);
13148
13149
13150  if (count($literals)) {
13151 $this->branches[] = array($literals, $level);
13152 }
13153
13154 return $this->setPropagateLearn($level, $selectedLiteral, $disableRules, $rule);
13155 }
13156
13157
13158
13159
13160
13161
13162 protected function analyze($level, Rule $rule)
13163 {
13164 $analyzedRule = $rule;
13165 $ruleLevel = 1;
13166 $num = 0;
13167 $l1num = 0;
13168 $seen = array();
13169 $learnedLiterals = array(null);
13170
13171 $decisionId = count($this->decisions);
13172
13173 $this->learnedPool[] = array();
13174
13175 while (true) {
13176 $this->learnedPool[count($this->learnedPool) - 1][] = $rule;
13177
13178 foreach ($rule->getLiterals() as $literal) {
13179
13180  if ($this->decisions->satisfy($literal)) {
13181 continue;
13182 }
13183
13184 if (isset($seen[abs($literal)])) {
13185 continue;
13186 }
13187 $seen[abs($literal)] = true;
13188
13189 $l = $this->decisions->decisionLevel($literal);
13190
13191 if (1 === $l) {
13192 $l1num++;
13193 } elseif ($level === $l) {
13194 $num++;
13195 } else {
13196
13197  $learnedLiterals[] = $literal;
13198
13199 if ($l > $ruleLevel) {
13200 $ruleLevel = $l;
13201 }
13202 }
13203 }
13204
13205 $l1retry = true;
13206 while ($l1retry) {
13207 $l1retry = false;
13208
13209 if (!$num && !--$l1num) {
13210
13211  break 2;
13212 }
13213
13214 while (true) {
13215 if ($decisionId <= 0) {
13216 throw new SolverBugException(
13217 "Reached invalid decision id $decisionId while looking through $rule for a literal present in the analyzed rule $analyzedRule."
13218 );
13219 }
13220
13221 $decisionId--;
13222
13223 $decision = $this->decisions->atOffset($decisionId);
13224 $literal = $decision[Decisions::DECISION_LITERAL];
13225
13226 if (isset($seen[abs($literal)])) {
13227 break;
13228 }
13229 }
13230
13231 unset($seen[abs($literal)]);
13232
13233 if ($num && 0 === --$num) {
13234 $learnedLiterals[0] = -abs($literal);
13235
13236 if (!$l1num) {
13237 break 2;
13238 }
13239
13240 foreach ($learnedLiterals as $i => $learnedLiteral) {
13241 if ($i !== 0) {
13242 unset($seen[abs($learnedLiteral)]);
13243 }
13244 }
13245
13246  $l1num++;
13247 $l1retry = true;
13248 }
13249 }
13250
13251 $decision = $this->decisions->atOffset($decisionId);
13252 $rule = $decision[Decisions::DECISION_REASON];
13253 }
13254
13255 $why = count($this->learnedPool) - 1;
13256
13257 if (!$learnedLiterals[0]) {
13258 throw new SolverBugException(
13259 "Did not find a learnable literal in analyzed rule $analyzedRule."
13260 );
13261 }
13262
13263 $newRule = new GenericRule($learnedLiterals, Rule::RULE_LEARNED, $why);
13264
13265 return array($learnedLiterals[0], $ruleLevel, $newRule, $why);
13266 }
13267
13268
13269
13270
13271
13272 private function analyzeUnsolvableRule(Problem $problem, Rule $conflictRule)
13273 {
13274 $why = spl_object_hash($conflictRule);
13275
13276 if ($conflictRule->getType() == RuleSet::TYPE_LEARNED) {
13277 $learnedWhy = $this->learnedWhy[$why];
13278 $problemRules = $this->learnedPool[$learnedWhy];
13279
13280 foreach ($problemRules as $problemRule) {
13281 $this->analyzeUnsolvableRule($problem, $problemRule);
13282 }
13283
13284 return;
13285 }
13286
13287 if ($conflictRule->getType() == RuleSet::TYPE_PACKAGE) {
13288
13289  return;
13290 }
13291
13292 $problem->nextSection();
13293 $problem->addRule($conflictRule);
13294 }
13295
13296
13297
13298
13299
13300
13301 private function analyzeUnsolvable(Rule $conflictRule, $disableRules)
13302 {
13303 $problem = new Problem($this->pool);
13304 $problem->addRule($conflictRule);
13305
13306 $this->analyzeUnsolvableRule($problem, $conflictRule);
13307
13308 $this->problems[] = $problem;
13309
13310 $seen = array();
13311 $literals = $conflictRule->getLiterals();
13312
13313 foreach ($literals as $literal) {
13314
13315  if ($this->decisions->satisfy($literal)) {
13316 continue;
13317 }
13318 $seen[abs($literal)] = true;
13319 }
13320
13321 foreach ($this->decisions as $decision) {
13322 $literal = $decision[Decisions::DECISION_LITERAL];
13323
13324
13325  if (!isset($seen[abs($literal)])) {
13326 continue;
13327 }
13328
13329 $why = $decision[Decisions::DECISION_REASON];
13330
13331 $problem->addRule($why);
13332 $this->analyzeUnsolvableRule($problem, $why);
13333
13334 $literals = $why->getLiterals();
13335
13336 foreach ($literals as $literal) {
13337
13338  if ($this->decisions->satisfy($literal)) {
13339 continue;
13340 }
13341 $seen[abs($literal)] = true;
13342 }
13343 }
13344
13345 if ($disableRules) {
13346 foreach ($this->problems[count($this->problems) - 1] as $reason) {
13347 $this->disableProblem($reason['rule']);
13348 }
13349
13350 $this->resetSolver();
13351
13352 return 1;
13353 }
13354
13355 return 0;
13356 }
13357
13358
13359
13360
13361 private function disableProblem(Rule $why)
13362 {
13363 $job = $why->getJob();
13364
13365 if (!$job) {
13366 $why->disable();
13367
13368 return;
13369 }
13370
13371
13372  foreach ($this->rules as $rule) {
13373
13374 if ($job === $rule->getJob()) {
13375 $rule->disable();
13376 }
13377 }
13378 }
13379
13380 private function resetSolver()
13381 {
13382 $this->decisions->reset();
13383
13384 $this->propagateIndex = 0;
13385 $this->branches = array();
13386
13387 $this->enableDisableLearnedRules();
13388 $this->makeAssertionRuleDecisions();
13389 }
13390
13391
13392
13393
13394
13395
13396
13397
13398 private function enableDisableLearnedRules()
13399 {
13400 foreach ($this->rules->getIteratorFor(RuleSet::TYPE_LEARNED) as $rule) {
13401 $why = $this->learnedWhy[spl_object_hash($rule)];
13402 $problemRules = $this->learnedPool[$why];
13403
13404 $foundDisabled = false;
13405 foreach ($problemRules as $problemRule) {
13406 if ($problemRule->isDisabled()) {
13407 $foundDisabled = true;
13408 break;
13409 }
13410 }
13411
13412 if ($foundDisabled && $rule->isEnabled()) {
13413 $rule->disable();
13414 } elseif (!$foundDisabled && $rule->isDisabled()) {
13415 $rule->enable();
13416 }
13417 }
13418 }
13419
13420
13421
13422
13423 private function runSat($disableRules = true)
13424 {
13425 $this->propagateIndex = 0;
13426
13427
13428
13429
13430
13431
13432
13433
13434
13435
13436
13437 $decisionQueue = array();
13438 $decisionSupplementQueue = array();
13439
13440
13441
13442 $disableRules = array();
13443
13444 $level = 1;
13445 $systemLevel = $level + 1;
13446 $installedPos = 0;
13447
13448 while (true) {
13449 if (1 === $level) {
13450 $conflictRule = $this->propagate($level);
13451 if (null !== $conflictRule) {
13452 if ($this->analyzeUnsolvable($conflictRule, $disableRules)) {
13453 continue;
13454 }
13455
13456 return;
13457 }
13458 }
13459
13460
13461  if ($level < $systemLevel) {
13462 $iterator = $this->rules->getIteratorFor(RuleSet::TYPE_JOB);
13463 foreach ($iterator as $rule) {
13464 if ($rule->isEnabled()) {
13465 $decisionQueue = array();
13466 $noneSatisfied = true;
13467
13468 foreach ($rule->getLiterals() as $literal) {
13469 if ($this->decisions->satisfy($literal)) {
13470 $noneSatisfied = false;
13471 break;
13472 }
13473 if ($literal > 0 && $this->decisions->undecided($literal)) {
13474 $decisionQueue[] = $literal;
13475 }
13476 }
13477
13478 if ($noneSatisfied && count($decisionQueue)) {
13479
13480  
13481  if (count($this->installed) != count($this->updateMap)) {
13482 $prunedQueue = array();
13483 foreach ($decisionQueue as $literal) {
13484 if (isset($this->installedMap[abs($literal)])) {
13485 $prunedQueue[] = $literal;
13486 if (isset($this->updateMap[abs($literal)])) {
13487 $prunedQueue = $decisionQueue;
13488 break;
13489 }
13490 }
13491 }
13492 $decisionQueue = $prunedQueue;
13493 }
13494 }
13495
13496 if ($noneSatisfied && count($decisionQueue)) {
13497 $oLevel = $level;
13498 $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
13499
13500 if (0 === $level) {
13501 return;
13502 }
13503 if ($level <= $oLevel) {
13504 break;
13505 }
13506 }
13507 }
13508 }
13509
13510 $systemLevel = $level + 1;
13511
13512
13513  $iterator->next();
13514 if ($iterator->valid()) {
13515 continue;
13516 }
13517 }
13518
13519 if ($level < $systemLevel) {
13520 $systemLevel = $level;
13521 }
13522
13523 $rulesCount = count($this->rules);
13524
13525 for ($i = 0, $n = 0; $n < $rulesCount; $i++, $n++) {
13526 if ($i == $rulesCount) {
13527 $i = 0;
13528 }
13529
13530 $rule = $this->rules->ruleById[$i];
13531 $literals = $rule->getLiterals();
13532
13533 if ($rule->isDisabled()) {
13534 continue;
13535 }
13536
13537 $decisionQueue = array();
13538
13539
13540  
13541  
13542  
13543  
13544  
13545  foreach ($literals as $literal) {
13546 if ($literal <= 0) {
13547 if (!$this->decisions->decidedInstall(abs($literal))) {
13548 continue 2; 
13549  }
13550 } else {
13551 if ($this->decisions->decidedInstall(abs($literal))) {
13552 continue 2; 
13553  }
13554 if ($this->decisions->undecided(abs($literal))) {
13555 $decisionQueue[] = $literal;
13556 }
13557 }
13558 }
13559
13560
13561  if (count($decisionQueue) < 2) {
13562 continue;
13563 }
13564
13565 $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
13566
13567 if (0 === $level) {
13568 return;
13569 }
13570
13571
13572  $rulesCount = count($this->rules);
13573 $n = -1;
13574 }
13575
13576 if ($level < $systemLevel) {
13577 continue;
13578 }
13579
13580
13581  if (count($this->branches)) {
13582 $lastLiteral = null;
13583 $lastLevel = null;
13584 $lastBranchIndex = 0;
13585 $lastBranchOffset = 0;
13586
13587 for ($i = count($this->branches) - 1; $i >= 0; $i--) {
13588 list($literals, $l) = $this->branches[$i];
13589
13590 foreach ($literals as $offset => $literal) {
13591 if ($literal && $literal > 0 && $this->decisions->decisionLevel($literal) > $l + 1) {
13592 $lastLiteral = $literal;
13593 $lastBranchIndex = $i;
13594 $lastBranchOffset = $offset;
13595 $lastLevel = $l;
13596 }
13597 }
13598 }
13599
13600 if ($lastLiteral) {
13601 unset($this->branches[$lastBranchIndex][self::BRANCH_LITERALS][$lastBranchOffset]);
13602
13603 $level = $lastLevel;
13604 $this->revert($level);
13605
13606 $why = $this->decisions->lastReason();
13607
13608 $level = $this->setPropagateLearn($level, $lastLiteral, $disableRules, $why);
13609
13610 if ($level == 0) {
13611 return;
13612 }
13613
13614 continue;
13615 }
13616 }
13617
13618 break;
13619 }
13620 }
13621 }
13622 <?php
13623
13624
13625
13626
13627
13628
13629
13630
13631
13632
13633
13634 namespace Composer\DependencyResolver;
13635
13636
13637
13638
13639 class SolverBugException extends \RuntimeException
13640 {
13641 public function __construct($message)
13642 {
13643 parent::__construct(
13644 $message."\nThis exception was most likely caused by a bug in Composer.\n".
13645 "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");
13646 }
13647 }
13648 <?php
13649
13650
13651
13652
13653
13654
13655
13656
13657
13658
13659
13660 namespace Composer\DependencyResolver;
13661
13662 use Composer\Util\IniHelper;
13663
13664
13665
13666
13667 class SolverProblemsException extends \RuntimeException
13668 {
13669 protected $problems;
13670 protected $installedMap;
13671
13672 public function __construct(array $problems, array $installedMap)
13673 {
13674 $this->problems = $problems;
13675 $this->installedMap = $installedMap;
13676
13677 parent::__construct($this->createMessage(), 2);
13678 }
13679
13680 protected function createMessage()
13681 {
13682 $text = "\n";
13683 $hasExtensionProblems = false;
13684 foreach ($this->problems as $i => $problem) {
13685 $text .= "  Problem ".($i + 1).$problem->getPrettyString($this->installedMap)."\n";
13686
13687 if (!$hasExtensionProblems && $this->hasExtensionProblems($problem->getReasons())) {
13688 $hasExtensionProblems = true;
13689 }
13690 }
13691
13692 if (strpos($text, 'could not be found') || strpos($text, 'no matching package found')) {
13693 $text .= "\nPotential causes:\n - A typo in the package name\n - The package is not available in a stable-enough version according to your minimum-stability setting\n   see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.\n - It's a private package and you forgot to add a custom repository to find it\n\nRead <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.";
13694 }
13695
13696 if ($hasExtensionProblems) {
13697 $text .= $this->createExtensionHint();
13698 }
13699
13700 return $text;
13701 }
13702
13703 public function getProblems()
13704 {
13705 return $this->problems;
13706 }
13707
13708 private function createExtensionHint()
13709 {
13710 $paths = IniHelper::getAll();
13711
13712 if (count($paths) === 1 && empty($paths[0])) {
13713 return '';
13714 }
13715
13716 $text = "\n  To enable extensions, verify that they are enabled in your .ini files:\n    - ";
13717 $text .= implode("\n    - ", $paths);
13718 $text .= "\n  You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.";
13719
13720 return $text;
13721 }
13722
13723 private function hasExtensionProblems(array $reasonSets)
13724 {
13725 foreach ($reasonSets as $reasonSet) {
13726 foreach ($reasonSet as $reason) {
13727 if (isset($reason["rule"]) && 0 === strpos($reason["rule"]->getRequiredPackage(), 'ext-')) {
13728 return true;
13729 }
13730 }
13731 }
13732
13733 return false;
13734 }
13735 }
13736 <?php
13737
13738
13739
13740
13741
13742
13743
13744
13745
13746
13747
13748 namespace Composer\DependencyResolver;
13749
13750 use Composer\Package\AliasPackage;
13751
13752
13753
13754
13755 class Transaction
13756 {
13757 protected $policy;
13758 protected $pool;
13759 protected $installedMap;
13760 protected $decisions;
13761 protected $transaction;
13762
13763 public function __construct($policy, $pool, $installedMap, $decisions)
13764 {
13765 $this->policy = $policy;
13766 $this->pool = $pool;
13767 $this->installedMap = $installedMap;
13768 $this->decisions = $decisions;
13769 $this->transaction = array();
13770 }
13771
13772 public function getOperations()
13773 {
13774 $installMeansUpdateMap = $this->findUpdates();
13775
13776 $updateMap = array();
13777 $installMap = array();
13778 $uninstallMap = array();
13779
13780 foreach ($this->decisions as $i => $decision) {
13781 $literal = $decision[Decisions::DECISION_LITERAL];
13782 $reason = $decision[Decisions::DECISION_REASON];
13783
13784 $package = $this->pool->literalToPackage($literal);
13785
13786
13787  if (($literal > 0) == (isset($this->installedMap[$package->id]))) {
13788 continue;
13789 }
13790
13791 if ($literal > 0) {
13792 if (isset($installMeansUpdateMap[abs($literal)]) && !$package instanceof AliasPackage) {
13793 $source = $installMeansUpdateMap[abs($literal)];
13794
13795 $updateMap[$package->id] = array(
13796 'package' => $package,
13797 'source' => $source,
13798 'reason' => $reason,
13799 );
13800
13801
13802  unset($installMeansUpdateMap[abs($literal)]);
13803 $ignoreRemove[$source->id] = true;
13804 } else {
13805 $installMap[$package->id] = array(
13806 'package' => $package,
13807 'reason' => $reason,
13808 );
13809 }
13810 }
13811 }
13812
13813 foreach ($this->decisions as $i => $decision) {
13814 $literal = $decision[Decisions::DECISION_LITERAL];
13815 $reason = $decision[Decisions::DECISION_REASON];
13816 $package = $this->pool->literalToPackage($literal);
13817
13818 if ($literal <= 0 &&
13819 isset($this->installedMap[$package->id]) &&
13820 !isset($ignoreRemove[$package->id])) {
13821 $uninstallMap[$package->id] = array(
13822 'package' => $package,
13823 'reason' => $reason,
13824 );
13825 }
13826 }
13827
13828 $this->transactionFromMaps($installMap, $updateMap, $uninstallMap);
13829
13830 return $this->transaction;
13831 }
13832
13833 protected function transactionFromMaps($installMap, $updateMap, $uninstallMap)
13834 {
13835 $queue = array_map(
13836 function ($operation) {
13837 return $operation['package'];
13838 },
13839 $this->findRootPackages($installMap, $updateMap)
13840 );
13841
13842 $visited = array();
13843
13844 while (!empty($queue)) {
13845 $package = array_pop($queue);
13846 $packageId = $package->id;
13847
13848 if (!isset($visited[$packageId])) {
13849 array_push($queue, $package);
13850
13851 if ($package instanceof AliasPackage) {
13852 array_push($queue, $package->getAliasOf());
13853 } else {
13854 foreach ($package->getRequires() as $link) {
13855 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
13856
13857 foreach ($possibleRequires as $require) {
13858 array_push($queue, $require);
13859 }
13860 }
13861 }
13862
13863 $visited[$package->id] = true;
13864 } else {
13865 if (isset($installMap[$packageId])) {
13866 $this->install(
13867 $installMap[$packageId]['package'],
13868 $installMap[$packageId]['reason']
13869 );
13870 unset($installMap[$packageId]);
13871 }
13872 if (isset($updateMap[$packageId])) {
13873 $this->update(
13874 $updateMap[$packageId]['source'],
13875 $updateMap[$packageId]['package'],
13876 $updateMap[$packageId]['reason']
13877 );
13878 unset($updateMap[$packageId]);
13879 }
13880 }
13881 }
13882
13883 foreach ($uninstallMap as $uninstall) {
13884 $this->uninstall($uninstall['package'], $uninstall['reason']);
13885 }
13886 }
13887
13888 protected function findRootPackages($installMap, $updateMap)
13889 {
13890 $packages = $installMap + $updateMap;
13891 $roots = $packages;
13892
13893 foreach ($packages as $packageId => $operation) {
13894 $package = $operation['package'];
13895
13896 if (!isset($roots[$packageId])) {
13897 continue;
13898 }
13899
13900 foreach ($package->getRequires() as $link) {
13901 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
13902
13903 foreach ($possibleRequires as $require) {
13904 if ($require !== $package) {
13905 unset($roots[$require->id]);
13906 }
13907 }
13908 }
13909 }
13910
13911 return $roots;
13912 }
13913
13914 protected function findUpdates()
13915 {
13916 $installMeansUpdateMap = array();
13917
13918 foreach ($this->decisions as $i => $decision) {
13919 $literal = $decision[Decisions::DECISION_LITERAL];
13920 $package = $this->pool->literalToPackage($literal);
13921
13922 if ($package instanceof AliasPackage) {
13923 continue;
13924 }
13925
13926
13927  if ($literal <= 0 && isset($this->installedMap[$package->id])) {
13928 $updates = $this->policy->findUpdatePackages($this->pool, $this->installedMap, $package);
13929
13930 $literals = array($package->id);
13931
13932 foreach ($updates as $update) {
13933 $literals[] = $update->id;
13934 }
13935
13936 foreach ($literals as $updateLiteral) {
13937 if ($updateLiteral !== $literal) {
13938 $installMeansUpdateMap[abs($updateLiteral)] = $package;
13939 }
13940 }
13941 }
13942 }
13943
13944 return $installMeansUpdateMap;
13945 }
13946
13947 protected function install($package, $reason)
13948 {
13949 if ($package instanceof AliasPackage) {
13950 return $this->markAliasInstalled($package, $reason);
13951 }
13952
13953 $this->transaction[] = new Operation\InstallOperation($package, $reason);
13954 }
13955
13956 protected function update($from, $to, $reason)
13957 {
13958 $this->transaction[] = new Operation\UpdateOperation($from, $to, $reason);
13959 }
13960
13961 protected function uninstall($package, $reason)
13962 {
13963 if ($package instanceof AliasPackage) {
13964 return $this->markAliasUninstalled($package, $reason);
13965 }
13966
13967 $this->transaction[] = new Operation\UninstallOperation($package, $reason);
13968 }
13969
13970 protected function markAliasInstalled($package, $reason)
13971 {
13972 $this->transaction[] = new Operation\MarkAliasInstalledOperation($package, $reason);
13973 }
13974
13975 protected function markAliasUninstalled($package, $reason)
13976 {
13977 $this->transaction[] = new Operation\MarkAliasUninstalledOperation($package, $reason);
13978 }
13979 }
13980 <?php
13981
13982
13983
13984
13985
13986
13987
13988
13989
13990
13991
13992 namespace Composer\Downloader;
13993
13994 use Composer\Package\PackageInterface;
13995 use Symfony\Component\Finder\Finder;
13996 use Composer\IO\IOInterface;
13997
13998
13999
14000
14001
14002
14003
14004
14005 abstract class ArchiveDownloader extends FileDownloader
14006 {
14007
14008
14009
14010 public function download(PackageInterface $package, $path, $output = true)
14011 {
14012 $temporaryDir = $this->config->get('vendor-dir').'/composer/'.substr(md5(uniqid('', true)), 0, 8);
14013 $retries = 3;
14014 while ($retries--) {
14015 $fileName = parent::download($package, $path, $output);
14016
14017 $this->io->writeError(' Extracting archive', false, IOInterface::VERBOSE);
14018
14019 try {
14020 $this->filesystem->ensureDirectoryExists($temporaryDir);
14021 try {
14022 $this->extract($fileName, $temporaryDir);
14023 } catch (\Exception $e) {
14024
14025  parent::clearLastCacheWrite($package);
14026 throw $e;
14027 }
14028
14029 $this->filesystem->unlink($fileName);
14030
14031 $contentDir = $this->getFolderContent($temporaryDir);
14032
14033
14034  if (1 === count($contentDir) && is_dir(reset($contentDir))) {
14035 $contentDir = $this->getFolderContent((string) reset($contentDir));
14036 }
14037
14038
14039  foreach ($contentDir as $file) {
14040 $file = (string) $file;
14041 $this->filesystem->rename($file, $path . '/' . basename($file));
14042 }
14043
14044 $this->filesystem->removeDirectory($temporaryDir);
14045 if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir').'/composer/')) {
14046 $this->filesystem->removeDirectory($this->config->get('vendor-dir').'/composer/');
14047 }
14048 if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir'))) {
14049 $this->filesystem->removeDirectory($this->config->get('vendor-dir'));
14050 }
14051 } catch (\Exception $e) {
14052
14053  $this->filesystem->removeDirectory($path);
14054 $this->filesystem->removeDirectory($temporaryDir);
14055
14056
14057  if ($retries && $e instanceof \UnexpectedValueException && class_exists('ZipArchive') && $e->getCode() === \ZipArchive::ER_NOZIP) {
14058 $this->io->writeError('');
14059 if ($this->io->isDebug()) {
14060 $this->io->writeError('    Invalid zip file ('.$e->getMessage().'), retrying...');
14061 } else {
14062 $this->io->writeError('    Invalid zip file, retrying...');
14063 }
14064 usleep(500000);
14065 continue;
14066 }
14067
14068 throw $e;
14069 }
14070
14071 break;
14072 }
14073 }
14074
14075
14076
14077
14078 protected function getFileName(PackageInterface $package, $path)
14079 {
14080 return rtrim($path.'/'.md5($path.spl_object_hash($package)).'.'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_EXTENSION), '.');
14081 }
14082
14083
14084
14085
14086 protected function processUrl(PackageInterface $package, $url)
14087 {
14088 if ($package->getDistReference() && strpos($url, 'github.com')) {
14089 if (preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/(zip|tar)ball/(.+)$}i', $url, $match)) {
14090
14091  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $package->getDistReference();
14092 } elseif ($package->getDistReference() && preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/archive/.+\.(zip|tar)(?:\.gz)?$}i', $url, $match)) {
14093
14094  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $package->getDistReference();
14095 } elseif ($package->getDistReference() && preg_match('{^https?://api\.github\.com/repos/([^/]+)/([^/]+)/(zip|tar)ball(?:/.+)?$}i', $url, $match)) {
14096
14097  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $package->getDistReference();
14098 }
14099 } elseif ($package->getDistReference() && strpos($url, 'bitbucket.org')) {
14100 if (preg_match('{^https?://(?:www\.)?bitbucket\.org/([^/]+)/([^/]+)/get/(.+)\.(zip|tar\.gz|tar\.bz2)$}i', $url, $match)) {
14101
14102  $url = 'https://bitbucket.org/' . $match[1] . '/'. $match[2] . '/get/' . $package->getDistReference() . '.' . $match[4];
14103 }
14104 }
14105
14106 return parent::processUrl($package, $url);
14107 }
14108
14109
14110
14111
14112
14113
14114
14115
14116
14117 abstract protected function extract($file, $path);
14118
14119
14120
14121
14122
14123
14124
14125 private function getFolderContent($dir)
14126 {
14127 $finder = Finder::create()
14128 ->ignoreVCS(false)
14129 ->ignoreDotFiles(false)
14130 ->depth(0)
14131 ->in($dir);
14132
14133 return iterator_to_array($finder);
14134 }
14135 }
14136 <?php
14137
14138
14139
14140
14141
14142
14143
14144
14145
14146
14147
14148 namespace Composer\Downloader;
14149
14150 use Composer\Package\PackageInterface;
14151
14152
14153
14154
14155
14156
14157 interface ChangeReportInterface
14158 {
14159
14160
14161
14162
14163
14164
14165
14166 public function getLocalChanges(PackageInterface $package, $path);
14167 }
14168 <?php
14169
14170
14171
14172
14173
14174
14175
14176
14177
14178
14179
14180 namespace Composer\Downloader;
14181
14182 use Composer\Package\PackageInterface;
14183 use Composer\IO\IOInterface;
14184 use Composer\Util\Filesystem;
14185
14186
14187
14188
14189
14190
14191 class DownloadManager
14192 {
14193 private $io;
14194 private $preferDist = false;
14195 private $preferSource = false;
14196 private $packagePreferences = array();
14197 private $filesystem;
14198 private $downloaders = array();
14199
14200
14201
14202
14203
14204
14205
14206
14207 public function __construct(IOInterface $io, $preferSource = false, Filesystem $filesystem = null)
14208 {
14209 $this->io = $io;
14210 $this->preferSource = $preferSource;
14211 $this->filesystem = $filesystem ?: new Filesystem();
14212 }
14213
14214
14215
14216
14217
14218
14219
14220 public function setPreferSource($preferSource)
14221 {
14222 $this->preferSource = $preferSource;
14223
14224 return $this;
14225 }
14226
14227
14228
14229
14230
14231
14232
14233 public function setPreferDist($preferDist)
14234 {
14235 $this->preferDist = $preferDist;
14236
14237 return $this;
14238 }
14239
14240
14241
14242
14243
14244
14245
14246 public function setPreferences(array $preferences)
14247 {
14248 $this->packagePreferences = $preferences;
14249
14250 return $this;
14251 }
14252
14253
14254
14255
14256
14257
14258
14259
14260 public function setOutputProgress($outputProgress)
14261 {
14262 foreach ($this->downloaders as $downloader) {
14263 $downloader->setOutputProgress($outputProgress);
14264 }
14265
14266 return $this;
14267 }
14268
14269
14270
14271
14272
14273
14274
14275
14276 public function setDownloader($type, DownloaderInterface $downloader)
14277 {
14278 $type = strtolower($type);
14279 $this->downloaders[$type] = $downloader;
14280
14281 return $this;
14282 }
14283
14284
14285
14286
14287
14288
14289
14290
14291 public function getDownloader($type)
14292 {
14293 $type = strtolower($type);
14294 if (!isset($this->downloaders[$type])) {
14295 throw new \InvalidArgumentException(sprintf('Unknown downloader type: %s. Available types: %s.', $type, implode(', ', array_keys($this->downloaders))));
14296 }
14297
14298 return $this->downloaders[$type];
14299 }
14300
14301
14302
14303
14304
14305
14306
14307
14308
14309
14310 public function getDownloaderForInstalledPackage(PackageInterface $package)
14311 {
14312 $installationSource = $package->getInstallationSource();
14313
14314 if ('metapackage' === $package->getType()) {
14315 return;
14316 }
14317
14318 if ('dist' === $installationSource) {
14319 $downloader = $this->getDownloader($package->getDistType());
14320 } elseif ('source' === $installationSource) {
14321 $downloader = $this->getDownloader($package->getSourceType());
14322 } else {
14323 throw new \InvalidArgumentException(
14324 'Package '.$package.' seems not been installed properly'
14325 );
14326 }
14327
14328 if ($installationSource !== $downloader->getInstallationSource()) {
14329 throw new \LogicException(sprintf(
14330 'Downloader "%s" is a %s type downloader and can not be used to download %s',
14331 get_class($downloader), $downloader->getInstallationSource(), $installationSource
14332 ));
14333 }
14334
14335 return $downloader;
14336 }
14337
14338
14339
14340
14341
14342
14343
14344
14345
14346
14347
14348 public function download(PackageInterface $package, $targetDir, $preferSource = null)
14349 {
14350 $preferSource = null !== $preferSource ? $preferSource : $this->preferSource;
14351 $sourceType = $package->getSourceType();
14352 $distType = $package->getDistType();
14353
14354 $sources = array();
14355 if ($sourceType) {
14356 $sources[] = 'source';
14357 }
14358 if ($distType) {
14359 $sources[] = 'dist';
14360 }
14361
14362 if (empty($sources)) {
14363 throw new \InvalidArgumentException('Package '.$package.' must have a source or dist specified');
14364 }
14365
14366 if (!$preferSource && ($this->preferDist || 'dist' === $this->resolvePackageInstallPreference($package))) {
14367 $sources = array_reverse($sources);
14368 }
14369
14370 $this->filesystem->ensureDirectoryExists($targetDir);
14371
14372 foreach ($sources as $i => $source) {
14373 if (isset($e)) {
14374 $this->io->writeError('    <warning>Now trying to download from ' . $source . '</warning>');
14375 }
14376 $package->setInstallationSource($source);
14377 try {
14378 $downloader = $this->getDownloaderForInstalledPackage($package);
14379 if ($downloader) {
14380 $downloader->download($package, $targetDir);
14381 }
14382 break;
14383 } catch (\RuntimeException $e) {
14384 if ($i === count($sources) - 1) {
14385 throw $e;
14386 }
14387
14388 $this->io->writeError(
14389 '    <warning>Failed to download '.
14390 $package->getPrettyName().
14391 ' from ' . $source . ': '.
14392 $e->getMessage().'</warning>'
14393 );
14394 }
14395 }
14396 }
14397
14398
14399
14400
14401
14402
14403
14404
14405
14406
14407 public function update(PackageInterface $initial, PackageInterface $target, $targetDir)
14408 {
14409 $downloader = $this->getDownloaderForInstalledPackage($initial);
14410 if (!$downloader) {
14411 return;
14412 }
14413
14414 $installationSource = $initial->getInstallationSource();
14415
14416 if ('dist' === $installationSource) {
14417 $initialType = $initial->getDistType();
14418 $targetType = $target->getDistType();
14419 } else {
14420 $initialType = $initial->getSourceType();
14421 $targetType = $target->getSourceType();
14422 }
14423
14424
14425  if ($target->isDev() && 'dist' === $installationSource) {
14426 $downloader->remove($initial, $targetDir);
14427 $this->download($target, $targetDir);
14428
14429 return;
14430 }
14431
14432 if ($initialType === $targetType) {
14433 $target->setInstallationSource($installationSource);
14434 try {
14435 $downloader->update($initial, $target, $targetDir);
14436
14437 return;
14438 } catch (\RuntimeException $e) {
14439 if (!$this->io->isInteractive()) {
14440 throw $e;
14441 }
14442 $this->io->writeError('<error>    Update failed ('.$e->getMessage().')</error>');
14443 if (!$this->io->askConfirmation('    Would you like to try reinstalling the package instead [<comment>yes</comment>]? ', true)) {
14444 throw $e;
14445 }
14446 }
14447 }
14448
14449 $downloader->remove($initial, $targetDir);
14450 $this->download($target, $targetDir, 'source' === $installationSource);
14451 }
14452
14453
14454
14455
14456
14457
14458
14459 public function remove(PackageInterface $package, $targetDir)
14460 {
14461 $downloader = $this->getDownloaderForInstalledPackage($package);
14462 if ($downloader) {
14463 $downloader->remove($package, $targetDir);
14464 }
14465 }
14466
14467
14468
14469
14470
14471
14472
14473
14474 protected function resolvePackageInstallPreference(PackageInterface $package)
14475 {
14476 foreach ($this->packagePreferences as $pattern => $preference) {
14477 $pattern = '{^'.str_replace('\\*', '.*', preg_quote($pattern)).'$}i';
14478 if (preg_match($pattern, $package->getName())) {
14479 if ('dist' === $preference || (!$package->isDev() && 'auto' === $preference)) {
14480 return 'dist';
14481 }
14482
14483 return 'source';
14484 }
14485 }
14486
14487 return $package->isDev() ? 'source' : 'dist';
14488 }
14489 }
14490 <?php
14491
14492
14493
14494
14495
14496
14497
14498
14499
14500
14501
14502 namespace Composer\Downloader;
14503
14504 use Composer\Package\PackageInterface;
14505
14506
14507
14508
14509
14510
14511
14512 interface DownloaderInterface
14513 {
14514
14515
14516
14517
14518
14519 public function getInstallationSource();
14520
14521
14522
14523
14524
14525
14526
14527 public function download(PackageInterface $package, $path);
14528
14529
14530
14531
14532
14533
14534
14535
14536 public function update(PackageInterface $initial, PackageInterface $target, $path);
14537
14538
14539
14540
14541
14542
14543
14544 public function remove(PackageInterface $package, $path);
14545
14546
14547
14548
14549
14550
14551
14552 public function setOutputProgress($outputProgress);
14553 }
14554 <?php
14555
14556
14557
14558
14559
14560
14561
14562
14563
14564
14565
14566 namespace Composer\Downloader;
14567
14568 use Composer\Package\PackageInterface;
14569
14570
14571
14572
14573
14574
14575 interface DvcsDownloaderInterface
14576 {
14577
14578
14579
14580
14581
14582
14583
14584 public function getUnpushedChanges(PackageInterface $package, $path);
14585 }
14586 <?php
14587
14588
14589
14590
14591
14592
14593
14594
14595
14596
14597
14598 namespace Composer\Downloader;
14599
14600 use Composer\Config;
14601 use Composer\Cache;
14602 use Composer\Factory;
14603 use Composer\IO\IOInterface;
14604 use Composer\Package\PackageInterface;
14605 use Composer\Plugin\PluginEvents;
14606 use Composer\Plugin\PreFileDownloadEvent;
14607 use Composer\EventDispatcher\EventDispatcher;
14608 use Composer\Util\Filesystem;
14609 use Composer\Util\RemoteFilesystem;
14610
14611
14612
14613
14614
14615
14616
14617
14618
14619 class FileDownloader implements DownloaderInterface
14620 {
14621 protected $io;
14622 protected $config;
14623 protected $rfs;
14624 protected $filesystem;
14625 protected $cache;
14626 protected $outputProgress = true;
14627 private $lastCacheWrites = array();
14628 private $eventDispatcher;
14629
14630
14631
14632
14633
14634
14635
14636
14637
14638
14639
14640 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, RemoteFilesystem $rfs = null, Filesystem $filesystem = null)
14641 {
14642 $this->io = $io;
14643 $this->config = $config;
14644 $this->eventDispatcher = $eventDispatcher;
14645 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $config);
14646 $this->filesystem = $filesystem ?: new Filesystem();
14647 $this->cache = $cache;
14648
14649 if ($this->cache && $this->cache->gcIsNecessary()) {
14650 $this->cache->gc($config->get('cache-files-ttl'), $config->get('cache-files-maxsize'));
14651 }
14652 }
14653
14654
14655
14656
14657 public function getInstallationSource()
14658 {
14659 return 'dist';
14660 }
14661
14662
14663
14664
14665 public function download(PackageInterface $package, $path, $output = true)
14666 {
14667 if (!$package->getDistUrl()) {
14668 throw new \InvalidArgumentException('The given package is missing url information');
14669 }
14670
14671 if ($output) {
14672 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>): ", false);
14673 }
14674
14675 $urls = $package->getDistUrls();
14676 while ($url = array_shift($urls)) {
14677 try {
14678 $fileName = $this->doDownload($package, $path, $url);
14679 break;
14680 } catch (\Exception $e) {
14681 if ($this->io->isDebug()) {
14682 $this->io->writeError('');
14683 $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getCode().': '.$e->getMessage());
14684 } elseif (count($urls)) {
14685 $this->io->writeError('');
14686 $this->io->writeError(' Failed, trying the next URL ('.$e->getCode().': '.$e->getMessage().')', false);
14687 }
14688
14689 if (!count($urls)) {
14690 throw $e;
14691 }
14692 }
14693 }
14694
14695 if ($output) {
14696 $this->io->writeError('');
14697 }
14698
14699 return $fileName;
14700 }
14701
14702 protected function doDownload(PackageInterface $package, $path, $url)
14703 {
14704 $this->filesystem->emptyDirectory($path);
14705
14706 $fileName = $this->getFileName($package, $path);
14707
14708 $processedUrl = $this->processUrl($package, $url);
14709 $hostname = parse_url($processedUrl, PHP_URL_HOST);
14710
14711 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $processedUrl);
14712 if ($this->eventDispatcher) {
14713 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
14714 }
14715 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
14716
14717 try {
14718 $checksum = $package->getDistSha1Checksum();
14719 $cacheKey = $this->getCacheKey($package, $processedUrl);
14720
14721
14722  if (!$this->cache || ($checksum && $checksum !== $this->cache->sha1($cacheKey)) || !$this->cache->copyTo($cacheKey, $fileName)) {
14723 if (!$this->outputProgress) {
14724 $this->io->writeError('Downloading', false);
14725 }
14726
14727
14728  $retries = 3;
14729 while ($retries--) {
14730 try {
14731 $rfs->copy($hostname, $processedUrl, $fileName, $this->outputProgress, $package->getTransportOptions());
14732 break;
14733 } catch (TransportException $e) {
14734
14735  if ((0 !== $e->getCode() && !in_array($e->getCode(), array(500, 502, 503, 504))) || !$retries) {
14736 throw $e;
14737 }
14738 $this->io->writeError('');
14739 $this->io->writeError('    Download failed, retrying...', true, IOInterface::VERBOSE);
14740 usleep(500000);
14741 }
14742 }
14743
14744 if (!$this->outputProgress) {
14745 $this->io->writeError(' (<comment>100%</comment>)', false);
14746 }
14747
14748 if ($this->cache) {
14749 $this->lastCacheWrites[$package->getName()] = $cacheKey;
14750 $this->cache->copyFrom($cacheKey, $fileName);
14751 }
14752 } else {
14753 $this->io->writeError('Loading from cache', false);
14754 }
14755
14756 if (!file_exists($fileName)) {
14757 throw new \UnexpectedValueException($url.' could not be saved to '.$fileName.', make sure the'
14758 .' directory is writable and you have internet connectivity');
14759 }
14760
14761 if ($checksum && hash_file('sha1', $fileName) !== $checksum) {
14762 throw new \UnexpectedValueException('The checksum verification of the file failed (downloaded from '.$url.')');
14763 }
14764 } catch (\Exception $e) {
14765
14766  $this->filesystem->removeDirectory($path);
14767 $this->clearLastCacheWrite($package);
14768 throw $e;
14769 }
14770
14771 return $fileName;
14772 }
14773
14774
14775
14776
14777 public function setOutputProgress($outputProgress)
14778 {
14779 $this->outputProgress = $outputProgress;
14780
14781 return $this;
14782 }
14783
14784 protected function clearLastCacheWrite(PackageInterface $package)
14785 {
14786 if ($this->cache && isset($this->lastCacheWrites[$package->getName()])) {
14787 $this->cache->remove($this->lastCacheWrites[$package->getName()]);
14788 unset($this->lastCacheWrites[$package->getName()]);
14789 }
14790 }
14791
14792
14793
14794
14795 public function update(PackageInterface $initial, PackageInterface $target, $path)
14796 {
14797 $name = $target->getName();
14798 $from = $initial->getPrettyVersion();
14799 $to = $target->getPrettyVersion();
14800
14801 $this->io->writeError("  - Updating <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>): ", false);
14802
14803 $this->remove($initial, $path, false);
14804 $this->download($target, $path, false);
14805
14806 $this->io->writeError('');
14807 }
14808
14809
14810
14811
14812 public function remove(PackageInterface $package, $path, $output = true)
14813 {
14814 if ($output) {
14815 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
14816 }
14817 if (!$this->filesystem->removeDirectory($path)) {
14818 throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
14819 }
14820 }
14821
14822
14823
14824
14825
14826
14827
14828
14829 protected function getFileName(PackageInterface $package, $path)
14830 {
14831 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
14832 }
14833
14834
14835
14836
14837
14838
14839
14840
14841
14842 protected function processUrl(PackageInterface $package, $url)
14843 {
14844 if (!extension_loaded('openssl') && 0 === strpos($url, 'https:')) {
14845 throw new \RuntimeException('You must enable the openssl extension to download files via https');
14846 }
14847
14848 return $url;
14849 }
14850
14851 private function getCacheKey(PackageInterface $package, $processedUrl)
14852 {
14853
14854  
14855  
14856  
14857  $cacheKey = sha1($processedUrl);
14858
14859 return $package->getName().'/'.$cacheKey.'.'.$package->getDistType();
14860 }
14861 }
14862 <?php
14863
14864
14865
14866
14867
14868
14869
14870
14871
14872
14873
14874 namespace Composer\Downloader;
14875
14876
14877
14878
14879
14880
14881 class FilesystemException extends \Exception
14882 {
14883 public function __construct($message = '', $code = 0, \Exception $previous = null)
14884 {
14885 parent::__construct("Filesystem exception: \n".$message, $code, $previous);
14886 }
14887 }
14888 <?php
14889
14890
14891
14892
14893
14894
14895
14896
14897
14898
14899
14900 namespace Composer\Downloader;
14901
14902 use Composer\Package\PackageInterface;
14903 use Composer\Util\ProcessExecutor;
14904
14905
14906
14907
14908 class FossilDownloader extends VcsDownloader
14909 {
14910
14911
14912
14913 public function doDownload(PackageInterface $package, $path, $url)
14914 {
14915
14916  $this->config->prohibitUrlByConfig($url, $this->io);
14917
14918 $url = ProcessExecutor::escape($url);
14919 $ref = ProcessExecutor::escape($package->getSourceReference());
14920 $repoFile = $path . '.fossil';
14921 $this->io->writeError("Cloning ".$package->getSourceReference());
14922 $command = sprintf('fossil clone %s %s', $url, ProcessExecutor::escape($repoFile));
14923 if (0 !== $this->process->execute($command, $ignoredOutput)) {
14924 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
14925 }
14926 $command = sprintf('fossil open %s', ProcessExecutor::escape($repoFile));
14927 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
14928 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
14929 }
14930 $command = sprintf('fossil update %s', $ref);
14931 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
14932 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
14933 }
14934 }
14935
14936
14937
14938
14939 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
14940 {
14941
14942  $this->config->prohibitUrlByConfig($url, $this->io);
14943
14944 $url = ProcessExecutor::escape($url);
14945 $ref = ProcessExecutor::escape($target->getSourceReference());
14946 $this->io->writeError(" Updating to ".$target->getSourceReference());
14947
14948 if (!$this->hasMetadataRepository($path)) {
14949 throw new \RuntimeException('The .fslckout file is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
14950 }
14951
14952 $command = sprintf('fossil pull && fossil up %s', $ref);
14953 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
14954 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
14955 }
14956 }
14957
14958
14959
14960
14961 public function getLocalChanges(PackageInterface $package, $path)
14962 {
14963 if (!$this->hasMetadataRepository($path)) {
14964 return null;
14965 }
14966
14967 $this->process->execute('fossil changes', $output, realpath($path));
14968
14969 return trim($output) ?: null;
14970 }
14971
14972
14973
14974
14975 protected function getCommitLogs($fromReference, $toReference, $path)
14976 {
14977 $command = sprintf('fossil timeline -t ci -W 0 -n 0 before %s', $toReference);
14978
14979 if (0 !== $this->process->execute($command, $output, realpath($path))) {
14980 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
14981 }
14982
14983 $log = '';
14984 $match = '/\d\d:\d\d:\d\d\s+\[' . $toReference . '\]/';
14985
14986 foreach ($this->process->splitLines($output) as $line) {
14987 if (preg_match($match, $line)) {
14988 break;
14989 }
14990 $log .= $line;
14991 }
14992
14993 return $log;
14994 }
14995
14996
14997
14998
14999 protected function hasMetadataRepository($path)
15000 {
15001 return is_file($path . '/.fslckout') || is_file($path . '/_FOSSIL_');
15002 }
15003 }
15004 <?php
15005
15006
15007
15008
15009
15010
15011
15012
15013
15014
15015
15016 namespace Composer\Downloader;
15017
15018 use Composer\Package\PackageInterface;
15019 use Composer\Util\Git as GitUtil;
15020 use Composer\Util\Platform;
15021 use Composer\Util\ProcessExecutor;
15022 use Composer\IO\IOInterface;
15023 use Composer\Util\Filesystem;
15024 use Composer\Config;
15025
15026
15027
15028
15029 class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
15030 {
15031 private $hasStashedChanges = false;
15032 private $hasDiscardedChanges = false;
15033 private $gitUtil;
15034
15035 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
15036 {
15037 parent::__construct($io, $config, $process, $fs);
15038 $this->gitUtil = new GitUtil($this->io, $this->config, $this->process, $this->filesystem);
15039 }
15040
15041
15042
15043
15044 public function doDownload(PackageInterface $package, $path, $url)
15045 {
15046 GitUtil::cleanEnv();
15047 $path = $this->normalizePath($path);
15048 $cachePath = $this->config->get('cache-vcs-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $url).'/';
15049 $cacheOptions = '';
15050 $ref = $package->getSourceReference();
15051 $flag = Platform::isWindows() ? '/D ' : '';
15052
15053
15054  $gitVersion = $this->gitUtil->getVersion();
15055 $msg = "Cloning ".$this->getShortHash($ref);
15056 if ($gitVersion && version_compare($gitVersion, '2.3.0-rc0', '>=')) {
15057 $this->io->writeError('', true, IOInterface::DEBUG);
15058 $this->io->writeError(sprintf('    Cloning to cache at %s', ProcessExecutor::escape($cachePath)), true, IOInterface::DEBUG);
15059 try {
15060 $this->gitUtil->syncMirror($url, $cachePath);
15061 if (is_dir($cachePath)) {
15062 $cacheOptions = sprintf('--dissociate --reference %s ', ProcessExecutor::escape($cachePath));
15063 $msg = "Cloning ".$this->getShortHash($ref).' from cache';
15064 }
15065 } catch (\RuntimeException $e) {
15066 }
15067 }
15068 $command = 'git clone --no-checkout %s %s '.$cacheOptions.'&& cd '.$flag.'%2$s && git remote add composer %1$s && git fetch composer';
15069 $this->io->writeError($msg);
15070
15071 $commandCallable = function ($url) use ($ref, $path, $command) {
15072 return sprintf($command, ProcessExecutor::escape($url), ProcessExecutor::escape($path), ProcessExecutor::escape($ref));
15073 };
15074
15075 $this->gitUtil->runCommand($commandCallable, $url, $path, true);
15076 if ($url !== $package->getSourceUrl()) {
15077 $this->updateOriginUrl($path, $package->getSourceUrl());
15078 } else {
15079 $this->setPushUrl($path, $url);
15080 }
15081
15082 if ($newRef = $this->updateToCommit($path, $ref, $package->getPrettyVersion(), $package->getReleaseDate())) {
15083 if ($package->getDistReference() === $package->getSourceReference()) {
15084 $package->setDistReference($newRef);
15085 }
15086 $package->setSourceReference($newRef);
15087 }
15088 }
15089
15090
15091
15092
15093 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
15094 {
15095 GitUtil::cleanEnv();
15096 if (!$this->hasMetadataRepository($path)) {
15097 throw new \RuntimeException('The .git directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
15098 }
15099
15100 $updateOriginUrl = false;
15101 if (
15102 0 === $this->process->execute('git remote -v', $output, $path)
15103 && preg_match('{^origin\s+(?P<url>\S+)}m', $output, $originMatch)
15104 && preg_match('{^composer\s+(?P<url>\S+)}m', $output, $composerMatch)
15105 ) {
15106 if ($originMatch['url'] === $composerMatch['url'] && $composerMatch['url'] !== $target->getSourceUrl()) {
15107 $updateOriginUrl = true;
15108 }
15109 }
15110
15111 $ref = $target->getSourceReference();
15112 $this->io->writeError(" Checking out ".$this->getShortHash($ref));
15113 $command = 'git remote set-url composer %s && git rev-parse --quiet --verify %s^{commit} || (git fetch composer && git fetch --tags composer)';
15114
15115 $commandCallable = function ($url) use ($command, $ref) {
15116 return sprintf($command, ProcessExecutor::escape($url), ProcessExecutor::escape($ref));
15117 };
15118
15119 $this->gitUtil->runCommand($commandCallable, $url, $path);
15120 if ($newRef = $this->updateToCommit($path, $ref, $target->getPrettyVersion(), $target->getReleaseDate())) {
15121 if ($target->getDistReference() === $target->getSourceReference()) {
15122 $target->setDistReference($newRef);
15123 }
15124 $target->setSourceReference($newRef);
15125 }
15126
15127 if ($updateOriginUrl) {
15128 $this->updateOriginUrl($path, $target->getSourceUrl());
15129 }
15130 }
15131
15132
15133
15134
15135 public function getLocalChanges(PackageInterface $package, $path)
15136 {
15137 GitUtil::cleanEnv();
15138 if (!$this->hasMetadataRepository($path)) {
15139 return;
15140 }
15141
15142 $command = 'git status --porcelain --untracked-files=no';
15143 if (0 !== $this->process->execute($command, $output, $path)) {
15144 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15145 }
15146
15147 return trim($output) ?: null;
15148 }
15149
15150 public function getUnpushedChanges(PackageInterface $package, $path)
15151 {
15152 GitUtil::cleanEnv();
15153 $path = $this->normalizePath($path);
15154 if (!$this->hasMetadataRepository($path)) {
15155 return;
15156 }
15157
15158 $command = 'git show-ref --head -d';
15159 if (0 !== $this->process->execute($command, $output, $path)) {
15160 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15161 }
15162
15163 $refs = trim($output);
15164 if (!preg_match('{^([a-f0-9]+) HEAD$}mi', $refs, $match)) {
15165
15166  return;
15167 }
15168
15169 $headRef = $match[1];
15170 if (!preg_match_all('{^'.$headRef.' refs/heads/(.+)$}mi', $refs, $matches)) {
15171
15172  return;
15173 }
15174
15175
15176  $branch = $matches[1][0];
15177 $unpushedChanges = null;
15178
15179
15180  for ($i = 0; $i <= 1; $i++) {
15181
15182  foreach ($matches[1] as $candidate) {
15183 if (preg_match('{^[a-f0-9]+ refs/remotes/((?:composer|origin)/'.preg_quote($candidate).')$}mi', $refs, $match)) {
15184 $branch = $candidate;
15185 $remoteBranch = $match[1];
15186 break;
15187 }
15188 }
15189
15190
15191  
15192  
15193  if (!isset($remoteBranch)) {
15194 $unpushedChanges = 'Branch ' . $branch . ' could not be found on the origin remote and appears to be unpushed';
15195 } else {
15196 $command = sprintf('git diff --name-status %s...%s --', $remoteBranch, $branch);
15197 if (0 !== $this->process->execute($command, $output, $path)) {
15198 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15199 }
15200
15201 $unpushedChanges = trim($output) ?: null;
15202 }
15203
15204
15205  
15206  if ($unpushedChanges && $i === 0) {
15207 $this->process->execute('git fetch composer && git fetch origin', $output, $path);
15208 }
15209
15210
15211  if (!$unpushedChanges) {
15212 break;
15213 }
15214 }
15215
15216 return $unpushedChanges;
15217 }
15218
15219
15220
15221
15222 protected function cleanChanges(PackageInterface $package, $path, $update)
15223 {
15224 GitUtil::cleanEnv();
15225 $path = $this->normalizePath($path);
15226
15227 $unpushed = $this->getUnpushedChanges($package, $path);
15228 if ($unpushed && ($this->io->isInteractive() || $this->config->get('discard-changes') !== true)) {
15229 throw new \RuntimeException('Source directory ' . $path . ' has unpushed changes on the current branch: '."\n".$unpushed);
15230 }
15231
15232 if (!$changes = $this->getLocalChanges($package, $path)) {
15233 return;
15234 }
15235
15236 if (!$this->io->isInteractive()) {
15237 $discardChanges = $this->config->get('discard-changes');
15238 if (true === $discardChanges) {
15239 return $this->discardChanges($path);
15240 }
15241 if ('stash' === $discardChanges) {
15242 if (!$update) {
15243 return parent::cleanChanges($package, $path, $update);
15244 }
15245
15246 return $this->stashChanges($path);
15247 }
15248
15249 return parent::cleanChanges($package, $path, $update);
15250 }
15251
15252 $changes = array_map(function ($elem) {
15253 return '    '.$elem;
15254 }, preg_split('{\s*\r?\n\s*}', $changes));
15255 $this->io->writeError('    <error>The package has modified files:</error>');
15256 $this->io->writeError(array_slice($changes, 0, 10));
15257 if (count($changes) > 10) {
15258 $this->io->writeError('    <info>' . (count($changes) - 10) . ' more files modified, choose "v" to view the full list</info>');
15259 }
15260
15261 while (true) {
15262 switch ($this->io->ask('    <info>Discard changes [y,n,v,d,'.($update ? 's,' : '').'?]?</info> ', '?')) {
15263 case 'y':
15264 $this->discardChanges($path);
15265 break 2;
15266
15267 case 's':
15268 if (!$update) {
15269 goto help;
15270 }
15271
15272 $this->stashChanges($path);
15273 break 2;
15274
15275 case 'n':
15276 throw new \RuntimeException('Update aborted');
15277
15278 case 'v':
15279 $this->io->writeError($changes);
15280 break;
15281
15282 case 'd':
15283 $this->viewDiff($path);
15284 break;
15285
15286 case '?':
15287 default:
15288 help:
15289 $this->io->writeError(array(
15290 '    y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
15291 '    n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
15292 '    v - view modified files',
15293 '    d - view local modifications (diff)',
15294 ));
15295 if ($update) {
15296 $this->io->writeError('    s - stash changes and try to reapply them after the update');
15297 }
15298 $this->io->writeError('    ? - print help');
15299 break;
15300 }
15301 }
15302 }
15303
15304
15305
15306
15307 protected function reapplyChanges($path)
15308 {
15309 $path = $this->normalizePath($path);
15310 if ($this->hasStashedChanges) {
15311 $this->hasStashedChanges = false;
15312 $this->io->writeError('    <info>Re-applying stashed changes</info>');
15313 if (0 !== $this->process->execute('git stash pop', $output, $path)) {
15314 throw new \RuntimeException("Failed to apply stashed changes:\n\n".$this->process->getErrorOutput());
15315 }
15316 }
15317
15318 $this->hasDiscardedChanges = false;
15319 }
15320
15321
15322
15323
15324
15325
15326
15327
15328
15329
15330
15331 protected function updateToCommit($path, $reference, $branch, $date)
15332 {
15333 $force = $this->hasDiscardedChanges || $this->hasStashedChanges ? '-f ' : '';
15334
15335
15336  
15337  
15338  
15339  
15340  $template = 'git checkout '.$force.'%s -- && git reset --hard %1$s --';
15341 $branch = preg_replace('{(?:^dev-|(?:\.x)?-dev$)}i', '', $branch);
15342
15343 $branches = null;
15344 if (0 === $this->process->execute('git branch -r', $output, $path)) {
15345 $branches = $output;
15346 }
15347
15348
15349  $gitRef = $reference;
15350 if (!preg_match('{^[a-f0-9]{40}$}', $reference)
15351 && $branches
15352 && preg_match('{^\s+composer/'.preg_quote($reference).'$}m', $branches)
15353 ) {
15354 $command = sprintf('git checkout '.$force.'-B %s %s -- && git reset --hard %2$s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$reference));
15355 if (0 === $this->process->execute($command, $output, $path)) {
15356 return;
15357 }
15358 }
15359
15360
15361  if (preg_match('{^[a-f0-9]{40}$}', $reference)) {
15362
15363  if (!preg_match('{^\s+composer/'.preg_quote($branch).'$}m', $branches) && preg_match('{^\s+composer/v'.preg_quote($branch).'$}m', $branches)) {
15364 $branch = 'v' . $branch;
15365 }
15366
15367 $command = sprintf('git checkout %s --', ProcessExecutor::escape($branch));
15368 $fallbackCommand = sprintf('git checkout '.$force.'-B %s %s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$branch));
15369 if (0 === $this->process->execute($command, $output, $path)
15370 || 0 === $this->process->execute($fallbackCommand, $output, $path)
15371 ) {
15372 $command = sprintf('git reset --hard %s --', ProcessExecutor::escape($reference));
15373 if (0 === $this->process->execute($command, $output, $path)) {
15374 return;
15375 }
15376 }
15377 }
15378
15379 $command = sprintf($template, ProcessExecutor::escape($gitRef));
15380 if (0 === $this->process->execute($command, $output, $path)) {
15381 return;
15382 }
15383
15384
15385  if (false !== strpos($this->process->getErrorOutput(), $reference)) {
15386 $this->io->writeError('    <warning>'.$reference.' is gone (history was rewritten?)</warning>');
15387 }
15388
15389 throw new \RuntimeException(GitUtil::sanitizeUrl('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()));
15390 }
15391
15392 protected function updateOriginUrl($path, $url)
15393 {
15394 $this->process->execute(sprintf('git remote set-url origin %s', ProcessExecutor::escape($url)), $output, $path);
15395 $this->setPushUrl($path, $url);
15396 }
15397
15398 protected function setPushUrl($path, $url)
15399 {
15400
15401  if (preg_match('{^(?:https?|git)://'.GitUtil::getGitHubDomainsRegex($this->config).'/([^/]+)/([^/]+?)(?:\.git)?$}', $url, $match)) {
15402 $protocols = $this->config->get('github-protocols');
15403 $pushUrl = 'git@'.$match[1].':'.$match[2].'/'.$match[3].'.git';
15404 if (!in_array('ssh', $protocols, true)) {
15405 $pushUrl = 'https://' . $match[1] . '/'.$match[2].'/'.$match[3].'.git';
15406 }
15407 $cmd = sprintf('git remote set-url --push origin %s', ProcessExecutor::escape($pushUrl));
15408 $this->process->execute($cmd, $ignoredOutput, $path);
15409 }
15410 }
15411
15412
15413
15414
15415 protected function getCommitLogs($fromReference, $toReference, $path)
15416 {
15417 $path = $this->normalizePath($path);
15418 $command = sprintf('git log %s..%s --pretty=format:"%%h - %%an: %%s"', $fromReference, $toReference);
15419
15420 if (0 !== $this->process->execute($command, $output, $path)) {
15421 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15422 }
15423
15424 return $output;
15425 }
15426
15427
15428
15429
15430
15431 protected function discardChanges($path)
15432 {
15433 $path = $this->normalizePath($path);
15434 if (0 !== $this->process->execute('git reset --hard', $output, $path)) {
15435 throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
15436 }
15437
15438 $this->hasDiscardedChanges = true;
15439 }
15440
15441
15442
15443
15444
15445 protected function stashChanges($path)
15446 {
15447 $path = $this->normalizePath($path);
15448 if (0 !== $this->process->execute('git stash --include-untracked', $output, $path)) {
15449 throw new \RuntimeException("Could not stash changes\n\n:".$this->process->getErrorOutput());
15450 }
15451
15452 $this->hasStashedChanges = true;
15453 }
15454
15455
15456
15457
15458
15459 protected function viewDiff($path)
15460 {
15461 $path = $this->normalizePath($path);
15462 if (0 !== $this->process->execute('git diff HEAD', $output, $path)) {
15463 throw new \RuntimeException("Could not view diff\n\n:".$this->process->getErrorOutput());
15464 }
15465
15466 $this->io->writeError($output);
15467 }
15468
15469 protected function normalizePath($path)
15470 {
15471 if (Platform::isWindows() && strlen($path) > 0) {
15472 $basePath = $path;
15473 $removed = array();
15474
15475 while (!is_dir($basePath) && $basePath !== '\\') {
15476 array_unshift($removed, basename($basePath));
15477 $basePath = dirname($basePath);
15478 }
15479
15480 if ($basePath === '\\') {
15481 return $path;
15482 }
15483
15484 $path = rtrim(realpath($basePath) . '/' . implode('/', $removed), '/');
15485 }
15486
15487 return $path;
15488 }
15489
15490
15491
15492
15493 protected function hasMetadataRepository($path)
15494 {
15495 $path = $this->normalizePath($path);
15496
15497 return is_dir($path.'/.git');
15498 }
15499
15500 protected function getShortHash($reference)
15501 {
15502 if (!$this->io->isVerbose() && preg_match('{^[0-9a-f]{40}$}', $reference)) {
15503 return substr($reference, 0, 10);
15504 }
15505
15506 return $reference;
15507 }
15508 }
15509 <?php
15510
15511
15512
15513
15514
15515
15516
15517
15518
15519
15520
15521 namespace Composer\Downloader;
15522
15523 use Composer\Config;
15524 use Composer\Cache;
15525 use Composer\EventDispatcher\EventDispatcher;
15526 use Composer\Package\PackageInterface;
15527 use Composer\Util\Platform;
15528 use Composer\Util\ProcessExecutor;
15529 use Composer\Util\RemoteFilesystem;
15530 use Composer\IO\IOInterface;
15531
15532
15533
15534
15535
15536
15537 class GzipDownloader extends ArchiveDownloader
15538 {
15539 protected $process;
15540
15541 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
15542 {
15543 $this->process = $process ?: new ProcessExecutor($io);
15544 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
15545 }
15546
15547 protected function extract($file, $path)
15548 {
15549 $targetFilepath = $path . DIRECTORY_SEPARATOR . basename(substr($file, 0, -3));
15550
15551
15552  if (!Platform::isWindows()) {
15553 $command = 'gzip -cd ' . ProcessExecutor::escape($file) . ' > ' . ProcessExecutor::escape($targetFilepath);
15554
15555 if (0 === $this->process->execute($command, $ignoredOutput)) {
15556 return;
15557 }
15558
15559 if (extension_loaded('zlib')) {
15560
15561  $this->extractUsingExt($file, $targetFilepath);
15562
15563 return;
15564 }
15565
15566 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
15567 throw new \RuntimeException($processError);
15568 }
15569
15570
15571  $this->extractUsingExt($file, $targetFilepath);
15572 }
15573
15574
15575
15576
15577 protected function getFileName(PackageInterface $package, $path)
15578 {
15579 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
15580 }
15581
15582 private function extractUsingExt($file, $targetFilepath)
15583 {
15584 $archiveFile = gzopen($file, 'rb');
15585 $targetFile = fopen($targetFilepath, 'wb');
15586 while ($string = gzread($archiveFile, 4096)) {
15587 fwrite($targetFile, $string, Platform::strlen($string));
15588 }
15589 gzclose($archiveFile);
15590 fclose($targetFile);
15591 }
15592 }
15593 <?php
15594
15595
15596
15597
15598
15599
15600
15601
15602
15603
15604
15605 namespace Composer\Downloader;
15606
15607 use Composer\Package\PackageInterface;
15608 use Composer\Util\ProcessExecutor;
15609
15610
15611
15612
15613 class HgDownloader extends VcsDownloader
15614 {
15615
15616
15617
15618 public function doDownload(PackageInterface $package, $path, $url)
15619 {
15620
15621  $this->config->prohibitUrlByConfig($url, $this->io);
15622
15623 $url = ProcessExecutor::escape($url);
15624 $ref = ProcessExecutor::escape($package->getSourceReference());
15625 $this->io->writeError("Cloning ".$package->getSourceReference());
15626 $command = sprintf('hg clone %s %s', $url, ProcessExecutor::escape($path));
15627 if (0 !== $this->process->execute($command, $ignoredOutput)) {
15628 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15629 }
15630 $command = sprintf('hg up %s', $ref);
15631 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
15632 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15633 }
15634 }
15635
15636
15637
15638
15639 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
15640 {
15641
15642  $this->config->prohibitUrlByConfig($url, $this->io);
15643
15644 $url = ProcessExecutor::escape($url);
15645 $ref = ProcessExecutor::escape($target->getSourceReference());
15646 $this->io->writeError(" Updating to ".$target->getSourceReference());
15647
15648 if (!$this->hasMetadataRepository($path)) {
15649 throw new \RuntimeException('The .hg directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
15650 }
15651
15652 $command = sprintf('hg pull %s && hg up %s', $url, $ref);
15653 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
15654 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15655 }
15656 }
15657
15658
15659
15660
15661 public function getLocalChanges(PackageInterface $package, $path)
15662 {
15663 if (!is_dir($path.'/.hg')) {
15664 return null;
15665 }
15666
15667 $this->process->execute('hg st', $output, realpath($path));
15668
15669 return trim($output) ?: null;
15670 }
15671
15672
15673
15674
15675 protected function getCommitLogs($fromReference, $toReference, $path)
15676 {
15677 $command = sprintf('hg log -r %s:%s --style compact', $fromReference, $toReference);
15678
15679 if (0 !== $this->process->execute($command, $output, realpath($path))) {
15680 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15681 }
15682
15683 return $output;
15684 }
15685
15686
15687
15688
15689 protected function hasMetadataRepository($path)
15690 {
15691 return is_dir($path . '/.hg');
15692 }
15693 }
15694 <?php
15695
15696
15697
15698
15699
15700
15701
15702
15703
15704
15705
15706 namespace Composer\Downloader;
15707
15708 use Composer\Package\Archiver\ArchivableFilesFinder;
15709 use Composer\Package\Dumper\ArrayDumper;
15710 use Composer\Package\PackageInterface;
15711 use Composer\Package\Version\VersionGuesser;
15712 use Composer\Package\Version\VersionParser;
15713 use Composer\Util\Platform;
15714 use Composer\Util\ProcessExecutor;
15715 use Composer\Util\Filesystem as ComposerFilesystem;
15716 use Symfony\Component\Filesystem\Exception\IOException;
15717 use Symfony\Component\Filesystem\Filesystem;
15718
15719
15720
15721
15722
15723
15724
15725 class PathDownloader extends FileDownloader implements VcsCapableDownloaderInterface
15726 {
15727 const STRATEGY_SYMLINK = 10;
15728 const STRATEGY_MIRROR = 20;
15729
15730
15731
15732
15733 public function download(PackageInterface $package, $path, $output = true)
15734 {
15735 $url = $package->getDistUrl();
15736 $realUrl = realpath($url);
15737 if (false === $realUrl || !file_exists($realUrl) || !is_dir($realUrl)) {
15738 throw new \RuntimeException(sprintf(
15739 'Source path "%s" is not found for package %s', $url, $package->getName()
15740 ));
15741 }
15742
15743 if (strpos(realpath($path) . DIRECTORY_SEPARATOR, $realUrl . DIRECTORY_SEPARATOR) === 0) {
15744
15745  
15746  
15747  
15748  throw new \RuntimeException(sprintf(
15749 'Package %s cannot install to "%s" inside its source at "%s"',
15750 $package->getName(), realpath($path), $realUrl
15751 ));
15752 }
15753
15754
15755  $transportOptions = $package->getTransportOptions() + array('symlink' => null);
15756
15757
15758  $currentStrategy = self::STRATEGY_SYMLINK;
15759 $allowedStrategies = array(self::STRATEGY_SYMLINK, self::STRATEGY_MIRROR);
15760
15761 $mirrorPathRepos = getenv('COMPOSER_MIRROR_PATH_REPOS');
15762 if ($mirrorPathRepos) {
15763 $currentStrategy = self::STRATEGY_MIRROR;
15764 }
15765
15766 if (true === $transportOptions['symlink']) {
15767 $currentStrategy = self::STRATEGY_SYMLINK;
15768 $allowedStrategies = array(self::STRATEGY_SYMLINK);
15769 } elseif (false === $transportOptions['symlink']) {
15770 $currentStrategy = self::STRATEGY_MIRROR;
15771 $allowedStrategies = array(self::STRATEGY_MIRROR);
15772 }
15773
15774 $fileSystem = new Filesystem();
15775 $this->filesystem->removeDirectory($path);
15776
15777 if ($output) {
15778 $this->io->writeError(sprintf(
15779 '  - Installing <info>%s</info> (<comment>%s</comment>): ',
15780 $package->getName(),
15781 $package->getFullPrettyVersion()
15782 ), false);
15783 }
15784
15785 $isFallback = false;
15786 if (self::STRATEGY_SYMLINK == $currentStrategy) {
15787 try {
15788 if (Platform::isWindows()) {
15789
15790  $this->io->writeError(sprintf('Junctioning from %s', $url), false);
15791 $this->filesystem->junction($realUrl, $path);
15792 } else {
15793 $absolutePath = $path;
15794 if (!$this->filesystem->isAbsolutePath($absolutePath)) {
15795 $absolutePath = getcwd() . DIRECTORY_SEPARATOR . $path;
15796 }
15797 $shortestPath = $this->filesystem->findShortestPath($absolutePath, $realUrl);
15798 $path = rtrim($path, "/");
15799 $this->io->writeError(sprintf('Symlinking from %s', $url), false);
15800 $fileSystem->symlink($shortestPath, $path);
15801 }
15802 } catch (IOException $e) {
15803 if (in_array(self::STRATEGY_MIRROR, $allowedStrategies)) {
15804 $this->io->writeError('');
15805 $this->io->writeError('    <error>Symlink failed, fallback to use mirroring!</error>');
15806 $currentStrategy = self::STRATEGY_MIRROR;
15807 $isFallback = true;
15808 } else {
15809 throw new \RuntimeException(sprintf('Symlink from "%s" to "%s" failed!', $realUrl, $path));
15810 }
15811 }
15812 }
15813
15814
15815  if (self::STRATEGY_MIRROR == $currentStrategy) {
15816 $fs = new ComposerFilesystem();
15817 $realUrl = $fs->normalizePath($realUrl);
15818
15819 $this->io->writeError(sprintf('%sMirroring from %s', $isFallback ? '    ' : '', $url), false);
15820 $iterator = new ArchivableFilesFinder($realUrl, array());
15821 $fileSystem->mirror($realUrl, $path, $iterator);
15822 }
15823
15824 $this->io->writeError('');
15825 }
15826
15827
15828
15829
15830 public function remove(PackageInterface $package, $path, $output = true)
15831 {
15832
15833
15834
15835
15836
15837 if (Platform::isWindows() && $this->filesystem->isJunction($path)) {
15838 if ($output) {
15839 $this->io->writeError("  - Removing junction for <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
15840 }
15841 if (!$this->filesystem->removeJunction($path)) {
15842 $this->io->writeError("    <warn>Could not remove junction at " . $path . " - is another process locking it?</warn>");
15843 throw new \RuntimeException('Could not reliably remove junction for package ' . $package->getName());
15844 }
15845 } else {
15846 parent::remove($package, $path, $output);
15847 }
15848 }
15849
15850
15851
15852
15853 public function getVcsReference(PackageInterface $package, $path)
15854 {
15855 $parser = new VersionParser;
15856 $guesser = new VersionGuesser($this->config, new ProcessExecutor($this->io), $parser);
15857 $dumper = new ArrayDumper;
15858
15859 $packageConfig = $dumper->dump($package);
15860 if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
15861 return $packageVersion['commit'];
15862 }
15863 }
15864 }
15865 <?php
15866
15867
15868
15869
15870
15871
15872
15873
15874
15875
15876
15877 namespace Composer\Downloader;
15878
15879 use Composer\Util\Filesystem;
15880
15881
15882
15883
15884
15885
15886
15887
15888
15889
15890 class PearPackageExtractor
15891 {
15892 private static $rolesWithoutPackageNamePrefix = array('php', 'script', 'www');
15893
15894 private $filesystem;
15895 private $file;
15896
15897 public function __construct($file)
15898 {
15899 if (!is_file($file)) {
15900 throw new \UnexpectedValueException('PEAR package file is not found at '.$file);
15901 }
15902
15903 $this->filesystem = new Filesystem();
15904 $this->file = $file;
15905 }
15906
15907
15908
15909
15910
15911
15912
15913
15914
15915
15916 public function extractTo($target, array $roles = array('php' => '/', 'script' => '/bin'), $vars = array())
15917 {
15918 $extractionPath = $target.'/tarball';
15919
15920 try {
15921 $archive = new \PharData($this->file);
15922 $archive->extractTo($extractionPath, null, true);
15923
15924 if (!is_file($this->combine($extractionPath, '/package.xml'))) {
15925 throw new \RuntimeException('Invalid PEAR package. It must contain package.xml file.');
15926 }
15927
15928 $fileCopyActions = $this->buildCopyActions($extractionPath, $roles, $vars);
15929 $this->copyFiles($fileCopyActions, $extractionPath, $target, $roles, $vars);
15930 $this->filesystem->removeDirectory($extractionPath);
15931 } catch (\Exception $exception) {
15932 throw new \UnexpectedValueException(sprintf('Failed to extract PEAR package %s to %s. Reason: %s', $this->file, $target, $exception->getMessage()), 0, $exception);
15933 }
15934 }
15935
15936
15937
15938
15939
15940
15941
15942
15943
15944
15945 private function copyFiles($files, $source, $target, $roles, $vars)
15946 {
15947 foreach ($files as $file) {
15948 $from = $this->combine($source, $file['from']);
15949 $to = $this->combine($target, $roles[$file['role']]);
15950 $to = $this->combine($to, $file['to']);
15951 $tasks = $file['tasks'];
15952 $this->copyFile($from, $to, $tasks, $vars);
15953 }
15954 }
15955
15956 private function copyFile($from, $to, $tasks, $vars)
15957 {
15958 if (!is_file($from)) {
15959 throw new \RuntimeException('Invalid PEAR package. package.xml defines file that is not located inside tarball.');
15960 }
15961
15962 $this->filesystem->ensureDirectoryExists(dirname($to));
15963
15964 if (0 == count($tasks)) {
15965 $copied = copy($from, $to);
15966 } else {
15967 $content = file_get_contents($from);
15968 $replacements = array();
15969 foreach ($tasks as $task) {
15970 $pattern = $task['from'];
15971 $varName = $task['to'];
15972 if (isset($vars[$varName])) {
15973 if ($varName === 'php_bin' && false === strpos($to, '.bat')) {
15974 $replacements[$pattern] = preg_replace('{\.bat$}', '', $vars[$varName]);
15975 } else {
15976 $replacements[$pattern] = $vars[$varName];
15977 }
15978 }
15979 }
15980 $content = strtr($content, $replacements);
15981
15982 $copied = file_put_contents($to, $content);
15983 }
15984
15985 if (false === $copied) {
15986 throw new \RuntimeException(sprintf('Failed to copy %s to %s', $from, $to));
15987 }
15988 }
15989
15990
15991
15992
15993
15994
15995
15996
15997
15998
15999
16000 private function buildCopyActions($source, array $roles, $vars)
16001 {
16002
16003 $package = simplexml_load_string(file_get_contents($this->combine($source, 'package.xml')));
16004 if (false === $package) {
16005 throw new \RuntimeException('Package definition file is not valid.');
16006 }
16007
16008 $packageSchemaVersion = $package['version'];
16009 if ('1.0' == $packageSchemaVersion) {
16010 $children = $package->release->filelist->children();
16011 $packageName = (string) $package->name;
16012 $packageVersion = (string) $package->release->version;
16013 $sourceDir = $packageName . '-' . $packageVersion;
16014 $result = $this->buildSourceList10($children, $roles, $sourceDir, '', null, $packageName);
16015 } elseif ('2.0' == $packageSchemaVersion || '2.1' == $packageSchemaVersion) {
16016 $children = $package->contents->children();
16017 $packageName = (string) $package->name;
16018 $packageVersion = (string) $package->version->release;
16019 $sourceDir = $packageName . '-' . $packageVersion;
16020 $result = $this->buildSourceList20($children, $roles, $sourceDir, '', null, $packageName);
16021
16022 $namespaces = $package->getNamespaces();
16023 $package->registerXPathNamespace('ns', $namespaces['']);
16024 $releaseNodes = $package->xpath('ns:phprelease');
16025 $this->applyRelease($result, $releaseNodes, $vars);
16026 } else {
16027 throw new \RuntimeException('Unsupported schema version of package definition file.');
16028 }
16029
16030 return $result;
16031 }
16032
16033 private function applyRelease(&$actions, $releaseNodes, $vars)
16034 {
16035 foreach ($releaseNodes as $releaseNode) {
16036 $requiredOs = $releaseNode->installconditions && $releaseNode->installconditions->os && $releaseNode->installconditions->os->name ? (string) $releaseNode->installconditions->os->name : '';
16037 if ($requiredOs && $vars['os'] != $requiredOs) {
16038 continue;
16039 }
16040
16041 if ($releaseNode->filelist) {
16042 foreach ($releaseNode->filelist->children() as $action) {
16043 if ('install' == $action->getName()) {
16044 $name = (string) $action['name'];
16045 $as = (string) $action['as'];
16046 if (isset($actions[$name])) {
16047 $actions[$name]['to'] = $as;
16048 }
16049 } elseif ('ignore' == $action->getName()) {
16050 $name = (string) $action['name'];
16051 unset($actions[$name]);
16052 } else {
16053
16054  }
16055 }
16056 }
16057 break;
16058 }
16059 }
16060
16061 private function buildSourceList10($children, $targetRoles, $source, $target, $role, $packageName)
16062 {
16063 $result = array();
16064
16065
16066  foreach ($children as $child) {
16067
16068 if ($child->getName() == 'dir') {
16069 $dirSource = $this->combine($source, (string) $child['name']);
16070 $dirTarget = $child['baseinstalldir'] ?: $target;
16071 $dirRole = $child['role'] ?: $role;
16072 $dirFiles = $this->buildSourceList10($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
16073 $result = array_merge($result, $dirFiles);
16074 } elseif ($child->getName() == 'file') {
16075 $fileRole = (string) $child['role'] ?: $role;
16076 if (isset($targetRoles[$fileRole])) {
16077 $fileName = (string) ($child['name'] ?: $child[0]); 
16078  $fileSource = $this->combine($source, $fileName);
16079 $fileTarget = $this->combine((string) $child['baseinstalldir'] ?: $target, $fileName);
16080 if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
16081 $fileTarget = $packageName . '/' . $fileTarget;
16082 }
16083 $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => array());
16084 }
16085 }
16086 }
16087
16088 return $result;
16089 }
16090
16091 private function buildSourceList20($children, $targetRoles, $source, $target, $role, $packageName)
16092 {
16093 $result = array();
16094
16095
16096  foreach ($children as $child) {
16097
16098 if ('dir' == $child->getName()) {
16099 $dirSource = $this->combine($source, $child['name']);
16100 $dirTarget = $child['baseinstalldir'] ?: $target;
16101 $dirRole = $child['role'] ?: $role;
16102 $dirFiles = $this->buildSourceList20($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
16103 $result = array_merge($result, $dirFiles);
16104 } elseif ('file' == $child->getName()) {
16105 $fileRole = (string) $child['role'] ?: $role;
16106 if (isset($targetRoles[$fileRole])) {
16107 $fileSource = $this->combine($source, (string) $child['name']);
16108 $fileTarget = $this->combine((string) ($child['baseinstalldir'] ?: $target), (string) $child['name']);
16109 $fileTasks = array();
16110 foreach ($child->children('http://pear.php.net/dtd/tasks-1.0') as $taskNode) {
16111 if ('replace' == $taskNode->getName()) {
16112 $fileTasks[] = array('from' => (string) $taskNode->attributes()->from, 'to' => (string) $taskNode->attributes()->to);
16113 }
16114 }
16115 if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
16116 $fileTarget = $packageName . '/' . $fileTarget;
16117 }
16118 $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => $fileTasks);
16119 }
16120 }
16121 }
16122
16123 return $result;
16124 }
16125
16126 private function combine($left, $right)
16127 {
16128 return rtrim($left, '/') . '/' . ltrim($right, '/');
16129 }
16130 }
16131 <?php
16132
16133
16134
16135
16136
16137
16138
16139
16140
16141
16142
16143 namespace Composer\Downloader;
16144
16145 use Composer\Package\PackageInterface;
16146 use Composer\Repository\VcsRepository;
16147 use Composer\Util\Perforce;
16148
16149
16150
16151
16152 class PerforceDownloader extends VcsDownloader
16153 {
16154
16155 protected $perforce;
16156
16157
16158
16159
16160 public function doDownload(PackageInterface $package, $path, $url)
16161 {
16162 $ref = $package->getSourceReference();
16163 $label = $this->getLabelFromSourceReference($ref);
16164
16165 $this->io->writeError('Cloning ' . $ref);
16166 $this->initPerforce($package, $path, $url);
16167 $this->perforce->setStream($ref);
16168 $this->perforce->p4Login();
16169 $this->perforce->writeP4ClientSpec();
16170 $this->perforce->connectClient();
16171 $this->perforce->syncCodeBase($label);
16172 $this->perforce->cleanupClientSpec();
16173 }
16174
16175 private function getLabelFromSourceReference($ref)
16176 {
16177 $pos = strpos($ref, '@');
16178 if (false !== $pos) {
16179 return substr($ref, $pos + 1);
16180 }
16181
16182 return null;
16183 }
16184
16185 public function initPerforce(PackageInterface $package, $path, $url)
16186 {
16187 if (!empty($this->perforce)) {
16188 $this->perforce->initializePath($path);
16189
16190 return;
16191 }
16192
16193 $repository = $package->getRepository();
16194 $repoConfig = null;
16195 if ($repository instanceof VcsRepository) {
16196 $repoConfig = $this->getRepoConfig($repository);
16197 }
16198 $this->perforce = Perforce::create($repoConfig, $url, $path, $this->process, $this->io);
16199 }
16200
16201 private function getRepoConfig(VcsRepository $repository)
16202 {
16203 return $repository->getRepoConfig();
16204 }
16205
16206
16207
16208
16209 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
16210 {
16211 $this->doDownload($target, $path, $url);
16212 }
16213
16214
16215
16216
16217 public function getLocalChanges(PackageInterface $package, $path)
16218 {
16219 $this->io->writeError('Perforce driver does not check for local changes before overriding', true);
16220
16221 return;
16222 }
16223
16224
16225
16226
16227 protected function getCommitLogs($fromReference, $toReference, $path)
16228 {
16229 $commitLogs = $this->perforce->getCommitLogs($fromReference, $toReference);
16230
16231 return $commitLogs;
16232 }
16233
16234 public function setPerforce($perforce)
16235 {
16236 $this->perforce = $perforce;
16237 }
16238
16239
16240
16241
16242 protected function hasMetadataRepository($path)
16243 {
16244 return true;
16245 }
16246 }
16247 <?php
16248
16249
16250
16251
16252
16253
16254
16255
16256
16257
16258
16259 namespace Composer\Downloader;
16260
16261
16262
16263
16264
16265
16266 class PharDownloader extends ArchiveDownloader
16267 {
16268
16269
16270
16271 protected function extract($file, $path)
16272 {
16273
16274  $archive = new \Phar($file);
16275 $archive->extractTo($path, null, true);
16276
16277
16278
16279
16280
16281 }
16282 }
16283 <?php
16284
16285
16286
16287
16288
16289
16290
16291
16292
16293
16294
16295 namespace Composer\Downloader;
16296
16297 use Composer\Config;
16298 use Composer\Cache;
16299 use Composer\EventDispatcher\EventDispatcher;
16300 use Composer\Util\IniHelper;
16301 use Composer\Util\Platform;
16302 use Composer\Util\ProcessExecutor;
16303 use Composer\Util\RemoteFilesystem;
16304 use Composer\IO\IOInterface;
16305 use RarArchive;
16306
16307
16308
16309
16310
16311
16312
16313
16314 class RarDownloader extends ArchiveDownloader
16315 {
16316 protected $process;
16317
16318 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
16319 {
16320 $this->process = $process ?: new ProcessExecutor($io);
16321 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
16322 }
16323
16324 protected function extract($file, $path)
16325 {
16326 $processError = null;
16327
16328
16329  if (!Platform::isWindows()) {
16330 $command = 'unrar x ' . ProcessExecutor::escape($file) . ' ' . ProcessExecutor::escape($path) . ' >/dev/null && chmod -R u+w ' . ProcessExecutor::escape($path);
16331
16332 if (0 === $this->process->execute($command, $ignoredOutput)) {
16333 return;
16334 }
16335
16336 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
16337 }
16338
16339 if (!class_exists('RarArchive')) {
16340
16341  $iniMessage = IniHelper::getMessage();
16342
16343 $error = "Could not decompress the archive, enable the PHP rar extension or install unrar.\n"
16344 . $iniMessage . "\n" . $processError;
16345
16346 if (!Platform::isWindows()) {
16347 $error = "Could not decompress the archive, enable the PHP rar extension.\n" . $iniMessage;
16348 }
16349
16350 throw new \RuntimeException($error);
16351 }
16352
16353 $rarArchive = RarArchive::open($file);
16354
16355 if (false === $rarArchive) {
16356 throw new \UnexpectedValueException('Could not open RAR archive: ' . $file);
16357 }
16358
16359 $entries = $rarArchive->getEntries();
16360
16361 if (false === $entries) {
16362 throw new \RuntimeException('Could not retrieve RAR archive entries');
16363 }
16364
16365 foreach ($entries as $entry) {
16366 if (false === $entry->extract($path)) {
16367 throw new \RuntimeException('Could not extract entry');
16368 }
16369 }
16370
16371 $rarArchive->close();
16372 }
16373 }
16374 <?php
16375
16376
16377
16378
16379
16380
16381
16382
16383
16384
16385
16386 namespace Composer\Downloader;
16387
16388 use Composer\Package\PackageInterface;
16389 use Composer\Util\Svn as SvnUtil;
16390 use Composer\Repository\VcsRepository;
16391
16392
16393
16394
16395
16396 class SvnDownloader extends VcsDownloader
16397 {
16398 protected $cacheCredentials = true;
16399
16400
16401
16402
16403 public function doDownload(PackageInterface $package, $path, $url)
16404 {
16405 SvnUtil::cleanEnv();
16406 $ref = $package->getSourceReference();
16407
16408 $repo = $package->getRepository();
16409 if ($repo instanceof VcsRepository) {
16410 $repoConfig = $repo->getRepoConfig();
16411 if (array_key_exists('svn-cache-credentials', $repoConfig)) {
16412 $this->cacheCredentials = (bool) $repoConfig['svn-cache-credentials'];
16413 }
16414 }
16415
16416 $this->io->writeError(" Checking out ".$package->getSourceReference());
16417 $this->execute($url, "svn co", sprintf("%s/%s", $url, $ref), null, $path);
16418 }
16419
16420
16421
16422
16423 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
16424 {
16425 SvnUtil::cleanEnv();
16426 $ref = $target->getSourceReference();
16427
16428 if (!$this->hasMetadataRepository($path)) {
16429 throw new \RuntimeException('The .svn directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
16430 }
16431
16432 $flags = "";
16433 if (0 === $this->process->execute('svn --version', $output)) {
16434 if (preg_match('{(\d+(?:\.\d+)+)}', $output, $match) && version_compare($match[1], '1.7.0', '>=')) {
16435 $flags .= ' --ignore-ancestry';
16436 }
16437 }
16438
16439 $this->io->writeError(" Checking out " . $ref);
16440 $this->execute($url, "svn switch" . $flags, sprintf("%s/%s", $url, $ref), $path);
16441 }
16442
16443
16444
16445
16446 public function getLocalChanges(PackageInterface $package, $path)
16447 {
16448 if (!$this->hasMetadataRepository($path)) {
16449 return null;
16450 }
16451
16452 $this->process->execute('svn status --ignore-externals', $output, $path);
16453
16454 return preg_match('{^ *[^X ] +}m', $output) ? $output : null;
16455 }
16456
16457
16458
16459
16460
16461
16462
16463
16464
16465
16466
16467
16468
16469 protected function execute($baseUrl, $command, $url, $cwd = null, $path = null)
16470 {
16471 $util = new SvnUtil($baseUrl, $this->io, $this->config);
16472 $util->setCacheCredentials($this->cacheCredentials);
16473 try {
16474 return $util->execute($command, $url, $cwd, $path, $this->io->isVerbose());
16475 } catch (\RuntimeException $e) {
16476 throw new \RuntimeException(
16477 'Package could not be downloaded, '.$e->getMessage()
16478 );
16479 }
16480 }
16481
16482
16483
16484
16485 protected function cleanChanges(PackageInterface $package, $path, $update)
16486 {
16487 if (!$changes = $this->getLocalChanges($package, $path)) {
16488 return;
16489 }
16490
16491 if (!$this->io->isInteractive()) {
16492 if (true === $this->config->get('discard-changes')) {
16493 return $this->discardChanges($path);
16494 }
16495
16496 return parent::cleanChanges($package, $path, $update);
16497 }
16498
16499 $changes = array_map(function ($elem) {
16500 return '    '.$elem;
16501 }, preg_split('{\s*\r?\n\s*}', $changes));
16502 $this->io->writeError('    <error>The package has modified files:</error>');
16503 $this->io->writeError(array_slice($changes, 0, 10));
16504 if (count($changes) > 10) {
16505 $this->io->writeError('    <info>'.count($changes) - 10 . ' more files modified, choose "v" to view the full list</info>');
16506 }
16507
16508 while (true) {
16509 switch ($this->io->ask('    <info>Discard changes [y,n,v,?]?</info> ', '?')) {
16510 case 'y':
16511 $this->discardChanges($path);
16512 break 2;
16513
16514 case 'n':
16515 throw new \RuntimeException('Update aborted');
16516
16517 case 'v':
16518 $this->io->writeError($changes);
16519 break;
16520
16521 case '?':
16522 default:
16523 $this->io->writeError(array(
16524 '    y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
16525 '    n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
16526 '    v - view modified files',
16527 '    ? - print help',
16528 ));
16529 break;
16530 }
16531 }
16532 }
16533
16534
16535
16536
16537 protected function getCommitLogs($fromReference, $toReference, $path)
16538 {
16539 if (preg_match('{.*@(\d+)$}', $fromReference) && preg_match('{.*@(\d+)$}', $toReference)) {
16540
16541  $fromRevision = preg_replace('{.*@(\d+)$}', '$1', $fromReference);
16542 $toRevision = preg_replace('{.*@(\d+)$}', '$1', $toReference);
16543
16544 $command = sprintf('svn log -r%s:%s --incremental', $fromRevision, $toRevision);
16545
16546 if (0 !== $this->process->execute($command, $output, $path)) {
16547 throw new \RuntimeException(
16548 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()
16549 );
16550 }
16551 } else {
16552 $output = "Could not retrieve changes between $fromReference and $toReference due to missing revision information";
16553 }
16554
16555 return $output;
16556 }
16557
16558 protected function discardChanges($path)
16559 {
16560 if (0 !== $this->process->execute('svn revert -R .', $output, $path)) {
16561 throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
16562 }
16563 }
16564
16565
16566
16567
16568 protected function hasMetadataRepository($path)
16569 {
16570 return is_dir($path.'/.svn');
16571 }
16572 }
16573 <?php
16574
16575
16576
16577
16578
16579
16580
16581
16582
16583
16584
16585 namespace Composer\Downloader;
16586
16587
16588
16589
16590
16591
16592 class TarDownloader extends ArchiveDownloader
16593 {
16594
16595
16596
16597 protected function extract($file, $path)
16598 {
16599
16600  $archive = new \PharData($file);
16601 $archive->extractTo($path, null, true);
16602 }
16603 }
16604 <?php
16605
16606
16607
16608
16609
16610
16611
16612
16613
16614
16615
16616 namespace Composer\Downloader;
16617
16618
16619
16620
16621 class TransportException extends \RuntimeException
16622 {
16623 protected $headers;
16624 protected $response;
16625 protected $statusCode;
16626
16627 public function setHeaders($headers)
16628 {
16629 $this->headers = $headers;
16630 }
16631
16632 public function getHeaders()
16633 {
16634 return $this->headers;
16635 }
16636
16637 public function setResponse($response)
16638 {
16639 $this->response = $response;
16640 }
16641
16642 public function getResponse()
16643 {
16644 return $this->response;
16645 }
16646
16647 public function setStatusCode($statusCode)
16648 {
16649 $this->statusCode = $statusCode;
16650 }
16651
16652 public function getStatusCode()
16653 {
16654 return $this->statusCode;
16655 }
16656 }
16657 <?php
16658
16659
16660
16661
16662
16663
16664
16665
16666
16667
16668
16669 namespace Composer\Downloader;
16670
16671 use Composer\Package\PackageInterface;
16672
16673
16674
16675
16676
16677
16678 interface VcsCapableDownloaderInterface
16679 {
16680
16681
16682
16683
16684
16685
16686
16687 public function getVcsReference(PackageInterface $package, $path);
16688 }
16689 <?php
16690
16691
16692
16693
16694
16695
16696
16697
16698
16699
16700
16701 namespace Composer\Downloader;
16702
16703 use Composer\Config;
16704 use Composer\Package\Dumper\ArrayDumper;
16705 use Composer\Package\PackageInterface;
16706 use Composer\Package\Version\VersionGuesser;
16707 use Composer\Package\Version\VersionParser;
16708 use Composer\Util\ProcessExecutor;
16709 use Composer\IO\IOInterface;
16710 use Composer\Util\Filesystem;
16711
16712
16713
16714
16715 abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterface, VcsCapableDownloaderInterface
16716 {
16717
16718 protected $io;
16719
16720 protected $config;
16721
16722 protected $process;
16723
16724 protected $filesystem;
16725
16726 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
16727 {
16728 $this->io = $io;
16729 $this->config = $config;
16730 $this->process = $process ?: new ProcessExecutor($io);
16731 $this->filesystem = $fs ?: new Filesystem($this->process);
16732 }
16733
16734
16735
16736
16737 public function getInstallationSource()
16738 {
16739 return 'source';
16740 }
16741
16742
16743
16744
16745 public function download(PackageInterface $package, $path)
16746 {
16747 if (!$package->getSourceReference()) {
16748 throw new \InvalidArgumentException('Package '.$package->getPrettyName().' is missing reference information');
16749 }
16750
16751 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>): ", false);
16752 $this->filesystem->emptyDirectory($path);
16753
16754 $urls = $package->getSourceUrls();
16755 while ($url = array_shift($urls)) {
16756 try {
16757 if (Filesystem::isLocalPath($url)) {
16758
16759  
16760  $needle = 'file://';
16761 $isFileProtocol = false;
16762 if (0 === strpos($url, $needle)) {
16763 $url = substr($url, strlen($needle));
16764 $isFileProtocol = true;
16765 }
16766
16767
16768  if (false !== strpos($url, '%')) {
16769 $url = rawurldecode($url);
16770 }
16771
16772 $url = realpath($url);
16773
16774 if ($isFileProtocol) {
16775 $url = $needle . $url;
16776 }
16777 }
16778 $this->doDownload($package, $path, $url);
16779 break;
16780 } catch (\Exception $e) {
16781
16782  if ($e instanceof \PHPUnit_Framework_Exception) {
16783 throw $e;
16784 }
16785 if ($this->io->isDebug()) {
16786 $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getMessage());
16787 } elseif (count($urls)) {
16788 $this->io->writeError('    Failed, trying the next URL');
16789 }
16790 if (!count($urls)) {
16791 throw $e;
16792 }
16793 }
16794 }
16795 }
16796
16797
16798
16799
16800 public function update(PackageInterface $initial, PackageInterface $target, $path)
16801 {
16802 if (!$target->getSourceReference()) {
16803 throw new \InvalidArgumentException('Package '.$target->getPrettyName().' is missing reference information');
16804 }
16805
16806 $name = $target->getName();
16807 if ($initial->getPrettyVersion() == $target->getPrettyVersion()) {
16808 if ($target->getSourceType() === 'svn') {
16809 $from = $initial->getSourceReference();
16810 $to = $target->getSourceReference();
16811 } else {
16812 $from = substr($initial->getSourceReference(), 0, 7);
16813 $to = substr($target->getSourceReference(), 0, 7);
16814 }
16815 $name .= ' '.$initial->getPrettyVersion();
16816 } else {
16817 $from = $initial->getFullPrettyVersion();
16818 $to = $target->getFullPrettyVersion();
16819 }
16820
16821 $this->io->writeError("  - Updating <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>): ", false);
16822
16823 $this->cleanChanges($initial, $path, true);
16824 $urls = $target->getSourceUrls();
16825
16826 $exception = null;
16827 while ($url = array_shift($urls)) {
16828 try {
16829 if (Filesystem::isLocalPath($url)) {
16830 $url = realpath($url);
16831 }
16832 $this->doUpdate($initial, $target, $path, $url);
16833
16834 $exception = null;
16835 break;
16836 } catch (\Exception $exception) {
16837
16838  if ($exception instanceof \PHPUnit_Framework_Exception) {
16839 throw $exception;
16840 }
16841 if ($this->io->isDebug()) {
16842 $this->io->writeError('Failed: ['.get_class($exception).'] '.$exception->getMessage());
16843 } elseif (count($urls)) {
16844 $this->io->writeError('    Failed, trying the next URL');
16845 }
16846 }
16847 }
16848
16849 $this->reapplyChanges($path);
16850
16851
16852  
16853  if (!$exception && $this->io->isVerbose() && $this->hasMetadataRepository($path)) {
16854 $message = 'Pulling in changes:';
16855 $logs = $this->getCommitLogs($initial->getSourceReference(), $target->getSourceReference(), $path);
16856
16857 if (!trim($logs)) {
16858 $message = 'Rolling back changes:';
16859 $logs = $this->getCommitLogs($target->getSourceReference(), $initial->getSourceReference(), $path);
16860 }
16861
16862 if (trim($logs)) {
16863 $logs = implode("\n", array_map(function ($line) {
16864 return '      ' . $line;
16865 }, explode("\n", $logs)));
16866
16867
16868  $logs = str_replace('<', '\<', $logs);
16869
16870 $this->io->writeError('    '.$message);
16871 $this->io->writeError($logs);
16872 }
16873 }
16874
16875 if (!$urls && $exception) {
16876 throw $exception;
16877 }
16878 }
16879
16880
16881
16882
16883 public function remove(PackageInterface $package, $path)
16884 {
16885 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getPrettyVersion() . "</comment>)");
16886 $this->cleanChanges($package, $path, false);
16887 if (!$this->filesystem->removeDirectory($path)) {
16888 throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
16889 }
16890 }
16891
16892
16893
16894
16895
16896 public function setOutputProgress($outputProgress)
16897 {
16898 return $this;
16899 }
16900
16901
16902
16903
16904 public function getVcsReference(PackageInterface $package, $path)
16905 {
16906 $parser = new VersionParser;
16907 $guesser = new VersionGuesser($this->config, $this->process, $parser);
16908 $dumper = new ArrayDumper;
16909
16910 $packageConfig = $dumper->dump($package);
16911 if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
16912 return $packageVersion['commit'];
16913 }
16914 }
16915
16916
16917
16918
16919
16920
16921
16922
16923
16924
16925 protected function cleanChanges(PackageInterface $package, $path, $update)
16926 {
16927
16928  if (null !== $this->getLocalChanges($package, $path)) {
16929 throw new \RuntimeException('Source directory ' . $path . ' has uncommitted changes.');
16930 }
16931 }
16932
16933
16934
16935
16936
16937
16938
16939 protected function reapplyChanges($path)
16940 {
16941 }
16942
16943
16944
16945
16946
16947
16948
16949
16950 abstract protected function doDownload(PackageInterface $package, $path, $url);
16951
16952
16953
16954
16955
16956
16957
16958
16959
16960 abstract protected function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url);
16961
16962
16963
16964
16965
16966
16967
16968
16969
16970 abstract protected function getCommitLogs($fromReference, $toReference, $path);
16971
16972
16973
16974
16975
16976
16977
16978
16979 abstract protected function hasMetadataRepository($path);
16980 }
16981 <?php
16982
16983
16984
16985
16986
16987
16988
16989
16990
16991
16992
16993 namespace Composer\Downloader;
16994
16995 use Composer\Config;
16996 use Composer\Cache;
16997 use Composer\EventDispatcher\EventDispatcher;
16998 use Composer\Package\PackageInterface;
16999 use Composer\Util\ProcessExecutor;
17000 use Composer\Util\RemoteFilesystem;
17001 use Composer\IO\IOInterface;
17002
17003
17004
17005
17006
17007
17008
17009 class XzDownloader extends ArchiveDownloader
17010 {
17011 protected $process;
17012
17013 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
17014 {
17015 $this->process = $process ?: new ProcessExecutor($io);
17016
17017 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
17018 }
17019
17020 protected function extract($file, $path)
17021 {
17022 $command = 'tar -xJf ' . ProcessExecutor::escape($file) . ' -C ' . ProcessExecutor::escape($path);
17023
17024 if (0 === $this->process->execute($command, $ignoredOutput)) {
17025 return;
17026 }
17027
17028 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
17029
17030 throw new \RuntimeException($processError);
17031 }
17032
17033
17034
17035
17036 protected function getFileName(PackageInterface $package, $path)
17037 {
17038 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
17039 }
17040 }
17041 <?php
17042
17043
17044
17045
17046
17047
17048
17049
17050
17051
17052
17053 namespace Composer\Downloader;
17054
17055 use Composer\Config;
17056 use Composer\Cache;
17057 use Composer\EventDispatcher\EventDispatcher;
17058 use Composer\Package\PackageInterface;
17059 use Composer\Util\IniHelper;
17060 use Composer\Util\Platform;
17061 use Composer\Util\ProcessExecutor;
17062 use Composer\Util\RemoteFilesystem;
17063 use Composer\IO\IOInterface;
17064 use Symfony\Component\Process\ExecutableFinder;
17065 use ZipArchive;
17066
17067
17068
17069
17070 class ZipDownloader extends ArchiveDownloader
17071 {
17072 protected static $hasSystemUnzip;
17073 private static $hasZipArchive;
17074 private static $isWindows;
17075
17076 protected $process;
17077 private $zipArchiveObject;
17078
17079 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
17080 {
17081 $this->process = $process ?: new ProcessExecutor($io);
17082 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
17083 }
17084
17085
17086
17087
17088 public function download(PackageInterface $package, $path, $output = true)
17089 {
17090 if (null === self::$hasSystemUnzip) {
17091 $finder = new ExecutableFinder;
17092 self::$hasSystemUnzip = (bool) $finder->find('unzip');
17093 }
17094
17095 if (null === self::$hasZipArchive) {
17096 self::$hasZipArchive = class_exists('ZipArchive');
17097 }
17098
17099 if (null === self::$isWindows) {
17100 self::$isWindows = Platform::isWindows();
17101 }
17102
17103 if (!self::$hasZipArchive && !self::$hasSystemUnzip) {
17104
17105  $iniMessage = IniHelper::getMessage();
17106 $error = "The zip extension and unzip command are both missing, skipping.\n" . $iniMessage;
17107
17108 throw new \RuntimeException($error);
17109 }
17110
17111 return parent::download($package, $path, $output);
17112 }
17113
17114
17115
17116
17117
17118
17119
17120
17121
17122 protected function extractWithSystemUnzip($file, $path, $isLastChance)
17123 {
17124 if (!self::$hasZipArchive) {
17125
17126  $isLastChance = true;
17127 }
17128
17129 if (!self::$hasSystemUnzip && !$isLastChance) {
17130
17131  
17132  return $this->extractWithZipArchive($file, $path, true);
17133 }
17134
17135 $processError = null;
17136
17137  $overwrite = $isLastChance ? '-o' : '';
17138
17139 $command = 'unzip -qq '.$overwrite.' '.ProcessExecutor::escape($file).' -d '.ProcessExecutor::escape($path);
17140
17141 try {
17142 if (0 === $this->process->execute($command, $ignoredOutput)) {
17143 return true;
17144 }
17145
17146 $processError = new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
17147 } catch (\Exception $e) {
17148 $processError = $e;
17149 }
17150
17151 if ($isLastChance) {
17152 throw $processError;
17153 }
17154
17155 $this->io->writeError('    '.$processError->getMessage());
17156 $this->io->writeError('    The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems)');
17157 $this->io->writeError('    Unzip with unzip command failed, falling back to ZipArchive class');
17158
17159 return $this->extractWithZipArchive($file, $path, true);
17160 }
17161
17162
17163
17164
17165
17166
17167
17168
17169
17170 protected function extractWithZipArchive($file, $path, $isLastChance)
17171 {
17172 if (!self::$hasSystemUnzip) {
17173
17174  $isLastChance = true;
17175 }
17176
17177 if (!self::$hasZipArchive && !$isLastChance) {
17178
17179  
17180  return $this->extractWithSystemUnzip($file, $path, true);
17181 }
17182
17183 $processError = null;
17184 $zipArchive = $this->zipArchiveObject ?: new ZipArchive();
17185
17186 try {
17187 if (true === ($retval = $zipArchive->open($file))) {
17188 $extractResult = $zipArchive->extractTo($path);
17189
17190 if (true === $extractResult) {
17191 $zipArchive->close();
17192
17193 return true;
17194 }
17195
17196 $processError = new \RuntimeException(rtrim("There was an error extracting the ZIP file, it is either corrupted or using an invalid format.\n"));
17197 } else {
17198 $processError = new \UnexpectedValueException(rtrim($this->getErrorMessage($retval, $file)."\n"), $retval);
17199 }
17200 } catch (\ErrorException $e) {
17201 $processError = new \RuntimeException('The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems): '.$e->getMessage(), 0, $e);
17202 } catch (\Exception $e) {
17203 $processError = $e;
17204 }
17205
17206 if ($isLastChance) {
17207 throw $processError;
17208 }
17209
17210 $this->io->writeError('    '.$processError->getMessage());
17211 $this->io->writeError('    Unzip with ZipArchive class failed, falling back to unzip command');
17212
17213 return $this->extractWithSystemUnzip($file, $path, true);
17214 }
17215
17216
17217
17218
17219
17220
17221
17222 public function extract($file, $path)
17223 {
17224
17225  if (self::$isWindows) {
17226 $this->extractWithZipArchive($file, $path, false);
17227 } else {
17228 $this->extractWithSystemUnzip($file, $path, false);
17229 }
17230 }
17231
17232
17233
17234
17235
17236
17237
17238
17239 protected function getErrorMessage($retval, $file)
17240 {
17241 switch ($retval) {
17242 case ZipArchive::ER_EXISTS:
17243 return sprintf("File '%s' already exists.", $file);
17244 case ZipArchive::ER_INCONS:
17245 return sprintf("Zip archive '%s' is inconsistent.", $file);
17246 case ZipArchive::ER_INVAL:
17247 return sprintf("Invalid argument (%s)", $file);
17248 case ZipArchive::ER_MEMORY:
17249 return sprintf("Malloc failure (%s)", $file);
17250 case ZipArchive::ER_NOENT:
17251 return sprintf("No such zip file: '%s'", $file);
17252 case ZipArchive::ER_NOZIP:
17253 return sprintf("'%s' is not a zip archive.", $file);
17254 case ZipArchive::ER_OPEN:
17255 return sprintf("Can't open zip file: %s", $file);
17256 case ZipArchive::ER_READ:
17257 return sprintf("Zip read error (%s)", $file);
17258 case ZipArchive::ER_SEEK:
17259 return sprintf("Zip seek error (%s)", $file);
17260 default:
17261 return sprintf("'%s' is not a valid zip archive, got error code: %s", $file, $retval);
17262 }
17263 }
17264 }
17265 <?php
17266
17267
17268
17269
17270
17271
17272
17273
17274
17275
17276
17277 namespace Composer\EventDispatcher;
17278
17279
17280
17281
17282
17283
17284 class Event
17285 {
17286
17287
17288
17289 protected $name;
17290
17291
17292
17293
17294 protected $args;
17295
17296
17297
17298
17299 protected $flags;
17300
17301
17302
17303
17304 private $propagationStopped = false;
17305
17306
17307
17308
17309
17310
17311
17312
17313 public function __construct($name, array $args = array(), array $flags = array())
17314 {
17315 $this->name = $name;
17316 $this->args = $args;
17317 $this->flags = $flags;
17318 }
17319
17320
17321
17322
17323
17324
17325 public function getName()
17326 {
17327 return $this->name;
17328 }
17329
17330
17331
17332
17333
17334
17335 public function getArguments()
17336 {
17337 return $this->args;
17338 }
17339
17340
17341
17342
17343
17344
17345 public function getFlags()
17346 {
17347 return $this->flags;
17348 }
17349
17350
17351
17352
17353
17354
17355 public function isPropagationStopped()
17356 {
17357 return $this->propagationStopped;
17358 }
17359
17360
17361
17362
17363 public function stopPropagation()
17364 {
17365 $this->propagationStopped = true;
17366 }
17367 }
17368 <?php
17369
17370
17371
17372
17373
17374
17375
17376
17377
17378
17379
17380 namespace Composer\EventDispatcher;
17381
17382 use Composer\DependencyResolver\PolicyInterface;
17383 use Composer\DependencyResolver\Pool;
17384 use Composer\DependencyResolver\Request;
17385 use Composer\Installer\InstallerEvent;
17386 use Composer\IO\IOInterface;
17387 use Composer\Composer;
17388 use Composer\DependencyResolver\Operation\OperationInterface;
17389 use Composer\Repository\CompositeRepository;
17390 use Composer\Script;
17391 use Composer\Installer\PackageEvent;
17392 use Composer\Installer\BinaryInstaller;
17393 use Composer\Util\ProcessExecutor;
17394 use Composer\Script\Event as ScriptEvent;
17395 use Symfony\Component\Process\PhpExecutableFinder;
17396
17397
17398
17399
17400
17401
17402
17403
17404
17405
17406
17407
17408
17409
17410 class EventDispatcher
17411 {
17412 protected $composer;
17413 protected $io;
17414 protected $loader;
17415 protected $process;
17416 protected $listeners;
17417 private $eventStack;
17418
17419
17420
17421
17422
17423
17424
17425
17426 public function __construct(Composer $composer, IOInterface $io, ProcessExecutor $process = null)
17427 {
17428 $this->composer = $composer;
17429 $this->io = $io;
17430 $this->process = $process ?: new ProcessExecutor($io);
17431 $this->eventStack = array();
17432 }
17433
17434
17435
17436
17437
17438
17439
17440
17441
17442 public function dispatch($eventName, Event $event = null)
17443 {
17444 if (null === $event) {
17445 $event = new Event($eventName);
17446 }
17447
17448 return $this->doDispatch($event);
17449 }
17450
17451
17452
17453
17454
17455
17456
17457
17458
17459
17460
17461 public function dispatchScript($eventName, $devMode = false, $additionalArgs = array(), $flags = array())
17462 {
17463 return $this->doDispatch(new Script\Event($eventName, $this->composer, $this->io, $devMode, $additionalArgs, $flags));
17464 }
17465
17466
17467
17468
17469
17470
17471
17472
17473
17474
17475
17476
17477
17478
17479
17480
17481 public function dispatchPackageEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
17482 {
17483 return $this->doDispatch(new PackageEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations, $operation));
17484 }
17485
17486
17487
17488
17489
17490
17491
17492
17493
17494
17495
17496
17497
17498
17499
17500 public function dispatchInstallerEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
17501 {
17502 return $this->doDispatch(new InstallerEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations));
17503 }
17504
17505
17506
17507
17508
17509
17510
17511
17512
17513 protected function doDispatch(Event $event)
17514 {
17515 $pathStr = 'PATH';
17516 if (!isset($_SERVER[$pathStr]) && isset($_SERVER['Path'])) {
17517 $pathStr = 'Path';
17518 }
17519
17520
17521  $binDir = $this->composer->getConfig()->get('bin-dir');
17522 if (is_dir($binDir)) {
17523 $binDir = realpath($binDir);
17524 if (isset($_SERVER[$pathStr]) && !preg_match('{(^|'.PATH_SEPARATOR.')'.preg_quote($binDir).'($|'.PATH_SEPARATOR.')}', $_SERVER[$pathStr])) {
17525 $_SERVER[$pathStr] = $binDir.PATH_SEPARATOR.getenv($pathStr);
17526 putenv($pathStr.'='.$_SERVER[$pathStr]);
17527 }
17528 }
17529
17530 $listeners = $this->getListeners($event);
17531
17532 $this->pushEvent($event);
17533
17534 $return = 0;
17535 foreach ($listeners as $callable) {
17536 if (!is_string($callable) && is_callable($callable)) {
17537 $event = $this->checkListenerExpectedEvent($callable, $event);
17538 $return = false === call_user_func($callable, $event) ? 1 : 0;
17539 } elseif ($this->isComposerScript($callable)) {
17540 $this->io->writeError(sprintf('> %s: %s', $event->getName(), $callable), true, IOInterface::VERBOSE);
17541 $scriptName = substr($callable, 1);
17542 $args = $event->getArguments();
17543 $flags = $event->getFlags();
17544 if (substr($callable, 0, 10) === '@composer ') {
17545 $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(getenv('COMPOSER_BINARY')) . substr($callable, 9);
17546 if (0 !== ($exitCode = $this->process->execute($exec))) {
17547 $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()), true, IOInterface::QUIET);
17548
17549 throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
17550 }
17551 } else {
17552 if (!$this->getListeners(new Event($scriptName))) {
17553 $this->io->writeError(sprintf('<warning>You made a reference to a non-existent script %s</warning>', $callable), true, IOInterface::QUIET);
17554 }
17555
17556 $return = $this->dispatch($scriptName, new Script\Event($scriptName, $event->getComposer(), $event->getIO(), $event->isDevMode(), $args, $flags));
17557 }
17558 } elseif ($this->isPhpScript($callable)) {
17559 $className = substr($callable, 0, strpos($callable, '::'));
17560 $methodName = substr($callable, strpos($callable, '::') + 2);
17561
17562 if (!class_exists($className)) {
17563 $this->io->writeError('<warning>Class '.$className.' is not autoloadable, can not call '.$event->getName().' script</warning>', true, IOInterface::QUIET);
17564 continue;
17565 }
17566 if (!is_callable($callable)) {
17567 $this->io->writeError('<warning>Method '.$callable.' is not callable, can not call '.$event->getName().' script</warning>', true, IOInterface::QUIET);
17568 continue;
17569 }
17570
17571 try {
17572 $return = false === $this->executeEventPhpScript($className, $methodName, $event) ? 1 : 0;
17573 } catch (\Exception $e) {
17574 $message = "Script %s handling the %s event terminated with an exception";
17575 $this->io->writeError('<error>'.sprintf($message, $callable, $event->getName()).'</error>', true, IOInterface::QUIET);
17576 throw $e;
17577 }
17578 } else {
17579 $args = implode(' ', array_map(array('Composer\Util\ProcessExecutor', 'escape'), $event->getArguments()));
17580 $exec = $callable . ($args === '' ? '' : ' '.$args);
17581 if ($this->io->isVerbose()) {
17582 $this->io->writeError(sprintf('> %s: %s', $event->getName(), $exec));
17583 } else {
17584 $this->io->writeError(sprintf('> %s', $exec));
17585 }
17586
17587 $possibleLocalBinaries = $this->composer->getPackage()->getBinaries();
17588 if ($possibleLocalBinaries) {
17589 foreach ($possibleLocalBinaries as $localExec) {
17590 if (preg_match('{\b'.preg_quote($callable).'$}', $localExec)) {
17591 $caller = BinaryInstaller::determineBinaryCaller($localExec);
17592 $exec = preg_replace('{^'.preg_quote($callable).'}', $caller . ' ' . $localExec, $exec);
17593 break;
17594 }
17595 }
17596 }
17597
17598 if (substr($exec, 0, 5) === '@php ') {
17599 $exec = $this->getPhpExecCommand() . ' ' . substr($exec, 5);
17600 }
17601
17602 if (0 !== ($exitCode = $this->process->execute($exec))) {
17603 $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()), true, IOInterface::QUIET);
17604
17605 throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
17606 }
17607 }
17608
17609 if ($event->isPropagationStopped()) {
17610 break;
17611 }
17612 }
17613
17614 $this->popEvent();
17615
17616 return $return;
17617 }
17618
17619 protected function getPhpExecCommand()
17620 {
17621 $finder = new PhpExecutableFinder();
17622 $phpPath = $finder->find();
17623 if (!$phpPath) {
17624 throw new \RuntimeException('Failed to locate PHP binary to execute '.$scriptName);
17625 }
17626
17627 $allowUrlFOpenFlag = ' -d allow_url_fopen=' . ProcessExecutor::escape(ini_get('allow_url_fopen'));
17628 $disableFunctionsFlag = ' -d disable_functions=' . ProcessExecutor::escape(ini_get('disable_functions'));
17629 $memoryLimitFlag = ' -d memory_limit=' . ProcessExecutor::escape(ini_get('memory_limit'));
17630
17631 return ProcessExecutor::escape($phpPath) . $allowUrlFOpenFlag . $disableFunctionsFlag . $memoryLimitFlag;
17632 }
17633
17634
17635
17636
17637
17638
17639 protected function executeEventPhpScript($className, $methodName, Event $event)
17640 {
17641 $event = $this->checkListenerExpectedEvent(array($className, $methodName), $event);
17642
17643 if ($this->io->isVerbose()) {
17644 $this->io->writeError(sprintf('> %s: %s::%s', $event->getName(), $className, $methodName));
17645 } else {
17646 $this->io->writeError(sprintf('> %s::%s', $className, $methodName));
17647 }
17648
17649 return $className::$methodName($event);
17650 }
17651
17652
17653
17654
17655
17656
17657 protected function checkListenerExpectedEvent($target, Event $event)
17658 {
17659 if (in_array($event->getName(), array(
17660 'init',
17661 'command',
17662 'pre-file-download',
17663 ), true)) {
17664 return $event;
17665 }
17666
17667 try {
17668 $reflected = new \ReflectionParameter($target, 0);
17669 } catch (\Exception $e) {
17670 return $event;
17671 }
17672
17673 $typehint = $reflected->getClass();
17674
17675 if (!$typehint instanceof \ReflectionClass) {
17676 return $event;
17677 }
17678
17679 $expected = $typehint->getName();
17680
17681
17682  if (!$event instanceof $expected && $expected === 'Composer\Script\CommandEvent') {
17683 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);
17684 $event = new \Composer\Script\CommandEvent(
17685 $event->getName(), $event->getComposer(), $event->getIO(), $event->isDevMode(), $event->getArguments()
17686 );
17687 }
17688 if (!$event instanceof $expected && $expected === 'Composer\Script\PackageEvent') {
17689 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);
17690 $event = new \Composer\Script\PackageEvent(
17691 $event->getName(), $event->getComposer(), $event->getIO(), $event->isDevMode(),
17692 $event->getPolicy(), $event->getPool(), $event->getInstalledRepo(), $event->getRequest(),
17693 $event->getOperations(), $event->getOperation()
17694 );
17695 }
17696 if (!$event instanceof $expected && $expected === 'Composer\Script\Event') {
17697 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);
17698 $event = new \Composer\Script\Event(
17699 $event->getName(), $event->getComposer(), $event->getIO(), $event->isDevMode(),
17700 $event->getArguments(), $event->getFlags()
17701 );
17702 }
17703
17704 return $event;
17705 }
17706
17707 private function serializeCallback($cb)
17708 {
17709 if (is_array($cb) && count($cb) === 2) {
17710 if (is_object($cb[0])) {
17711 $cb[0] = get_class($cb[0]);
17712 }
17713 if (is_string($cb[0]) && is_string($cb[1])) {
17714 $cb = implode('::', $cb);
17715 }
17716 }
17717 if (is_string($cb)) {
17718 return $cb;
17719 }
17720
17721 return var_export($cb, true);
17722 }
17723
17724
17725
17726
17727
17728
17729
17730
17731 public function addListener($eventName, $listener, $priority = 0)
17732 {
17733 $this->listeners[$eventName][$priority][] = $listener;
17734 }
17735
17736
17737
17738
17739
17740
17741
17742
17743 public function addSubscriber(EventSubscriberInterface $subscriber)
17744 {
17745 foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
17746 if (is_string($params)) {
17747 $this->addListener($eventName, array($subscriber, $params));
17748 } elseif (is_string($params[0])) {
17749 $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0);
17750 } else {
17751 foreach ($params as $listener) {
17752 $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0);
17753 }
17754 }
17755 }
17756 }
17757
17758
17759
17760
17761
17762
17763
17764 protected function getListeners(Event $event)
17765 {
17766 $scriptListeners = $this->getScriptListeners($event);
17767
17768 if (!isset($this->listeners[$event->getName()][0])) {
17769 $this->listeners[$event->getName()][0] = array();
17770 }
17771 krsort($this->listeners[$event->getName()]);
17772
17773 $listeners = $this->listeners;
17774 $listeners[$event->getName()][0] = array_merge($listeners[$event->getName()][0], $scriptListeners);
17775
17776 return call_user_func_array('array_merge', $listeners[$event->getName()]);
17777 }
17778
17779
17780
17781
17782
17783
17784
17785 public function hasEventListeners(Event $event)
17786 {
17787 $listeners = $this->getListeners($event);
17788
17789 return count($listeners) > 0;
17790 }
17791
17792
17793
17794
17795
17796
17797
17798 protected function getScriptListeners(Event $event)
17799 {
17800 $package = $this->composer->getPackage();
17801 $scripts = $package->getScripts();
17802
17803 if (empty($scripts[$event->getName()])) {
17804 return array();
17805 }
17806
17807 if ($this->loader) {
17808 $this->loader->unregister();
17809 }
17810
17811 $generator = $this->composer->getAutoloadGenerator();
17812 if ($event instanceof ScriptEvent) {
17813 $generator->setDevMode($event->isDevMode());
17814 }
17815
17816 $packages = $this->composer->getRepositoryManager()->getLocalRepository()->getCanonicalPackages();
17817 $packageMap = $generator->buildPackageMap($this->composer->getInstallationManager(), $package, $packages);
17818 $map = $generator->parseAutoloads($packageMap, $package);
17819 $this->loader = $generator->createLoader($map);
17820 $this->loader->register();
17821
17822 return $scripts[$event->getName()];
17823 }
17824
17825
17826
17827
17828
17829
17830
17831 protected function isPhpScript($callable)
17832 {
17833 return false === strpos($callable, ' ') && false !== strpos($callable, '::');
17834 }
17835
17836
17837
17838
17839
17840
17841
17842 protected function isComposerScript($callable)
17843 {
17844 return '@' === substr($callable, 0, 1) && '@php ' !== substr($callable, 0, 5);
17845 }
17846
17847
17848
17849
17850
17851
17852
17853
17854 protected function pushEvent(Event $event)
17855 {
17856 $eventName = $event->getName();
17857 if (in_array($eventName, $this->eventStack)) {
17858 throw new \RuntimeException(sprintf("Circular call to script handler '%s' detected", $eventName));
17859 }
17860
17861 return array_push($this->eventStack, $eventName);
17862 }
17863
17864
17865
17866
17867
17868
17869 protected function popEvent()
17870 {
17871 return array_pop($this->eventStack);
17872 }
17873 }
17874 <?php
17875
17876
17877
17878
17879
17880
17881
17882
17883
17884
17885
17886 namespace Composer\EventDispatcher;
17887
17888
17889
17890
17891
17892
17893
17894
17895
17896
17897
17898
17899
17900 interface EventSubscriberInterface
17901 {
17902
17903
17904
17905
17906
17907
17908
17909
17910
17911
17912
17913
17914
17915
17916
17917
17918
17919
17920 public static function getSubscribedEvents();
17921 }
17922 <?php
17923
17924
17925
17926
17927
17928
17929
17930
17931
17932
17933
17934 namespace Composer\EventDispatcher;
17935
17936
17937
17938
17939 class ScriptExecutionException extends \RuntimeException
17940 {
17941 }
17942 <?php
17943
17944
17945
17946
17947
17948
17949
17950
17951
17952
17953
17954 namespace Composer\Exception;
17955
17956
17957
17958
17959 class NoSslException extends \RuntimeException
17960 {
17961 }
17962 <?php
17963
17964
17965
17966
17967
17968
17969
17970
17971
17972
17973
17974 namespace Composer;
17975
17976 use Composer\Config\JsonConfigSource;
17977 use Composer\Json\JsonFile;
17978 use Composer\IO\IOInterface;
17979 use Composer\Package\Archiver;
17980 use Composer\Package\Version\VersionGuesser;
17981 use Composer\Repository\RepositoryManager;
17982 use Composer\Repository\RepositoryFactory;
17983 use Composer\Repository\WritableRepositoryInterface;
17984 use Composer\Util\Filesystem;
17985 use Composer\Util\Platform;
17986 use Composer\Util\ProcessExecutor;
17987 use Composer\Util\RemoteFilesystem;
17988 use Composer\Util\Silencer;
17989 use Composer\Plugin\PluginEvents;
17990 use Composer\EventDispatcher\Event;
17991 use Seld\JsonLint\DuplicateKeyException;
17992 use Symfony\Component\Console\Formatter\OutputFormatter;
17993 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
17994 use Symfony\Component\Console\Output\ConsoleOutput;
17995 use Composer\EventDispatcher\EventDispatcher;
17996 use Composer\Autoload\AutoloadGenerator;
17997 use Composer\Package\Version\VersionParser;
17998 use Composer\Downloader\TransportException;
17999 use Seld\JsonLint\JsonParser;
18000
18001
18002
18003
18004
18005
18006
18007
18008
18009 class Factory
18010 {
18011
18012
18013
18014
18015 protected static function getHomeDir()
18016 {
18017 $home = getenv('COMPOSER_HOME');
18018 if ($home) {
18019 return $home;
18020 }
18021
18022 if (Platform::isWindows()) {
18023 if (!getenv('APPDATA')) {
18024 throw new \RuntimeException('The APPDATA or COMPOSER_HOME environment variable must be set for composer to run correctly');
18025 }
18026
18027 return rtrim(strtr(getenv('APPDATA'), '\\', '/'), '/') . '/Composer';
18028 }
18029
18030 $userDir = self::getUserDir();
18031 if (is_dir($userDir . '/.composer')) {
18032 return $userDir . '/.composer';
18033 }
18034
18035 if (self::useXdg()) {
18036
18037  $xdgConfig = getenv('XDG_CONFIG_HOME') ?: $userDir . '/.config';
18038
18039 return $xdgConfig . '/composer';
18040 }
18041
18042 return $userDir . '/.composer';
18043 }
18044
18045
18046
18047
18048
18049 protected static function getCacheDir($home)
18050 {
18051 $cacheDir = getenv('COMPOSER_CACHE_DIR');
18052 if ($cacheDir) {
18053 return $cacheDir;
18054 }
18055
18056 $homeEnv = getenv('COMPOSER_HOME');
18057 if ($homeEnv) {
18058 return $homeEnv . '/cache';
18059 }
18060
18061 if (Platform::isWindows()) {
18062 if ($cacheDir = getenv('LOCALAPPDATA')) {
18063 $cacheDir .= '/Composer';
18064 } else {
18065 $cacheDir = $home . '/cache';
18066 }
18067
18068 return rtrim(strtr($cacheDir, '\\', '/'), '/');
18069 }
18070
18071 $userDir = self::getUserDir();
18072 if ($home === $userDir . '/.composer' && is_dir($home . '/cache')) {
18073 return $home . '/cache';
18074 }
18075
18076 if (self::useXdg()) {
18077 $xdgCache = getenv('XDG_CACHE_HOME') ?: $userDir . '/.cache';
18078
18079 return $xdgCache . '/composer';
18080 }
18081
18082 return $home . '/cache';
18083 }
18084
18085
18086
18087
18088
18089 protected static function getDataDir($home)
18090 {
18091 $homeEnv = getenv('COMPOSER_HOME');
18092 if ($homeEnv) {
18093 return $homeEnv;
18094 }
18095
18096 if (Platform::isWindows()) {
18097 return strtr($home, '\\', '/');
18098 }
18099
18100 $userDir = self::getUserDir();
18101 if ($home !== $userDir . '/.composer' && self::useXdg()) {
18102 $xdgData = getenv('XDG_DATA_HOME') ?: $userDir . '/.local/share';
18103
18104 return $xdgData . '/composer';
18105 }
18106
18107 return $home;
18108 }
18109
18110
18111
18112
18113
18114 public static function createConfig(IOInterface $io = null, $cwd = null)
18115 {
18116 $cwd = $cwd ?: getcwd();
18117
18118 $config = new Config(true, $cwd);
18119
18120
18121  $home = self::getHomeDir();
18122 $config->merge(array('config' => array(
18123 'home' => $home,
18124 'cache-dir' => self::getCacheDir($home),
18125 'data-dir' => self::getDataDir($home),
18126 )));
18127
18128 $htaccessProtect = (bool) $config->get('htaccess-protect');
18129 if ($htaccessProtect) {
18130
18131  
18132  
18133  $dirs = array($config->get('home'), $config->get('cache-dir'), $config->get('data-dir'));
18134 foreach ($dirs as $dir) {
18135 if (!file_exists($dir . '/.htaccess')) {
18136 if (!is_dir($dir)) {
18137 Silencer::call('mkdir', $dir, 0777, true);
18138 }
18139 Silencer::call('file_put_contents', $dir . '/.htaccess', 'Deny from all');
18140 }
18141 }
18142 }
18143
18144
18145  $file = new JsonFile($config->get('home').'/config.json');
18146 if ($file->exists()) {
18147 if ($io && $io->isDebug()) {
18148 $io->writeError('Loading config file ' . $file->getPath());
18149 }
18150 $config->merge($file->read());
18151 }
18152 $config->setConfigSource(new JsonConfigSource($file));
18153
18154
18155  $file = new JsonFile($config->get('home').'/auth.json');
18156 if ($file->exists()) {
18157 if ($io && $io->isDebug()) {
18158 $io->writeError('Loading config file ' . $file->getPath());
18159 }
18160 $config->merge(array('config' => $file->read()));
18161 }
18162 $config->setAuthConfigSource(new JsonConfigSource($file, true));
18163
18164
18165  if ($composerAuthEnv = getenv('COMPOSER_AUTH')) {
18166 $authData = json_decode($composerAuthEnv, true);
18167
18168 if (is_null($authData)) {
18169 throw new \UnexpectedValueException('COMPOSER_AUTH environment variable is malformed, should be a valid JSON object');
18170 }
18171
18172 if ($io && $io->isDebug()) {
18173 $io->writeError('Loading auth config from COMPOSER_AUTH');
18174 }
18175 $config->merge(array('config' => $authData));
18176 }
18177
18178 return $config;
18179 }
18180
18181 public static function getComposerFile()
18182 {
18183 return trim(getenv('COMPOSER')) ?: './composer.json';
18184 }
18185
18186 public static function createAdditionalStyles()
18187 {
18188 return array(
18189 'highlight' => new OutputFormatterStyle('red'),
18190 'warning' => new OutputFormatterStyle('black', 'yellow'),
18191 );
18192 }
18193
18194
18195
18196
18197
18198
18199 public static function createOutput()
18200 {
18201 $styles = self::createAdditionalStyles();
18202 $formatter = new OutputFormatter(null, $styles);
18203
18204 return new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, null, $formatter);
18205 }
18206
18207
18208
18209
18210 public static function createDefaultRepositories(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
18211 {
18212 return RepositoryFactory::defaultRepos($io, $config, $rm);
18213 }
18214
18215
18216
18217
18218
18219
18220
18221
18222
18223
18224
18225
18226
18227 public function createComposer(IOInterface $io, $localConfig = null, $disablePlugins = false, $cwd = null, $fullLoad = true)
18228 {
18229 $cwd = $cwd ?: getcwd();
18230
18231
18232  if (null === $localConfig) {
18233 $localConfig = static::getComposerFile();
18234 }
18235
18236 if (is_string($localConfig)) {
18237 $composerFile = $localConfig;
18238
18239 $file = new JsonFile($localConfig, null, $io);
18240
18241 if (!$file->exists()) {
18242 if ($localConfig === './composer.json' || $localConfig === 'composer.json') {
18243 $message = 'Composer could not find a composer.json file in '.$cwd;
18244 } else {
18245 $message = 'Composer could not find the config file: '.$localConfig;
18246 }
18247 $instructions = 'To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section';
18248 throw new \InvalidArgumentException($message.PHP_EOL.$instructions);
18249 }
18250
18251 $file->validateSchema(JsonFile::LAX_SCHEMA);
18252 $jsonParser = new JsonParser;
18253 try {
18254 $jsonParser->parse(file_get_contents($localConfig), JsonParser::DETECT_KEY_CONFLICTS);
18255 } catch (DuplicateKeyException $e) {
18256 $details = $e->getDetails();
18257 $io->writeError('<warning>Key '.$details['key'].' is a duplicate in '.$localConfig.' at line '.$details['line'].'</warning>');
18258 }
18259
18260 $localConfig = $file->read();
18261 }
18262
18263
18264  $config = static::createConfig($io, $cwd);
18265 $config->merge($localConfig);
18266 if (isset($composerFile)) {
18267 $io->writeError('Loading config file ' . $composerFile, true, IOInterface::DEBUG);
18268 $config->setConfigSource(new JsonConfigSource(new JsonFile(realpath($composerFile), null, $io)));
18269
18270 $localAuthFile = new JsonFile(dirname(realpath($composerFile)) . '/auth.json', null, $io);
18271 if ($localAuthFile->exists()) {
18272 $io->writeError('Loading config file ' . $localAuthFile->getPath(), true, IOInterface::DEBUG);
18273 $config->merge(array('config' => $localAuthFile->read()));
18274 $config->setAuthConfigSource(new JsonConfigSource($localAuthFile, true));
18275 }
18276 }
18277
18278 $vendorDir = $config->get('vendor-dir');
18279
18280
18281  $composer = new Composer();
18282 $composer->setConfig($config);
18283
18284 if ($fullLoad) {
18285
18286  $io->loadConfiguration($config);
18287 }
18288
18289 $rfs = self::createRemoteFilesystem($io, $config);
18290
18291
18292  $dispatcher = new EventDispatcher($composer, $io);
18293 $composer->setEventDispatcher($dispatcher);
18294
18295
18296  $rm = RepositoryFactory::manager($io, $config, $dispatcher, $rfs);
18297 $composer->setRepositoryManager($rm);
18298
18299
18300  $this->addLocalRepository($io, $rm, $vendorDir);
18301
18302
18303  
18304  if (!$fullLoad && !isset($localConfig['version'])) {
18305 $localConfig['version'] = '1.0.0';
18306 }
18307
18308
18309  $parser = new VersionParser;
18310 $guesser = new VersionGuesser($config, new ProcessExecutor($io), $parser);
18311 $loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, $guesser);
18312 $package = $loader->load($localConfig, 'Composer\Package\RootPackage', $cwd);
18313 $composer->setPackage($package);
18314
18315
18316  $im = $this->createInstallationManager();
18317 $composer->setInstallationManager($im);
18318
18319 if ($fullLoad) {
18320
18321  $dm = $this->createDownloadManager($io, $config, $dispatcher, $rfs);
18322 $composer->setDownloadManager($dm);
18323
18324
18325  $generator = new AutoloadGenerator($dispatcher, $io);
18326 $composer->setAutoloadGenerator($generator);
18327
18328
18329  $am = $this->createArchiveManager($config, $dm);
18330 $composer->setArchiveManager($am);
18331 }
18332
18333
18334  $this->createDefaultInstallers($im, $composer, $io);
18335
18336 if ($fullLoad) {
18337 $globalComposer = null;
18338 if (realpath($config->get('home')) !== $cwd) {
18339 $globalComposer = $this->createGlobalComposer($io, $config, $disablePlugins);
18340 }
18341
18342 $pm = $this->createPluginManager($io, $composer, $globalComposer, $disablePlugins);
18343 $composer->setPluginManager($pm);
18344
18345 $pm->loadInstalledPlugins();
18346 }
18347
18348
18349  if ($fullLoad && isset($composerFile)) {
18350 $lockFile = "json" === pathinfo($composerFile, PATHINFO_EXTENSION)
18351 ? substr($composerFile, 0, -4).'lock'
18352 : $composerFile . '.lock';
18353
18354 $locker = new Package\Locker($io, new JsonFile($lockFile, null, $io), $rm, $im, file_get_contents($composerFile));
18355 $composer->setLocker($locker);
18356 }
18357
18358 if ($fullLoad) {
18359 $initEvent = new Event(PluginEvents::INIT);
18360 $composer->getEventDispatcher()->dispatch($initEvent->getName(), $initEvent);
18361
18362
18363  
18364  if ($rm->getLocalRepository()) {
18365 $this->purgePackages($rm->getLocalRepository(), $im);
18366 }
18367 }
18368
18369 return $composer;
18370 }
18371
18372
18373
18374
18375
18376
18377 public static function createGlobal(IOInterface $io, $disablePlugins = false)
18378 {
18379 $factory = new static();
18380
18381 return $factory->createGlobalComposer($io, static::createConfig($io), $disablePlugins, true);
18382 }
18383
18384
18385
18386
18387
18388 protected function addLocalRepository(IOInterface $io, RepositoryManager $rm, $vendorDir)
18389 {
18390 $rm->setLocalRepository(new Repository\InstalledFilesystemRepository(new JsonFile($vendorDir.'/composer/installed.json', null, $io)));
18391 }
18392
18393
18394
18395
18396
18397 protected function createGlobalComposer(IOInterface $io, Config $config, $disablePlugins, $fullLoad = false)
18398 {
18399 $composer = null;
18400 try {
18401 $composer = self::createComposer($io, $config->get('home') . '/composer.json', $disablePlugins, $config->get('home'), $fullLoad);
18402 } catch (\Exception $e) {
18403 $io->writeError('Failed to initialize global composer: '.$e->getMessage(), true, IOInterface::DEBUG);
18404 }
18405
18406 return $composer;
18407 }
18408
18409
18410
18411
18412
18413
18414
18415 public function createDownloadManager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
18416 {
18417 $cache = null;
18418 if ($config->get('cache-files-ttl') > 0) {
18419 $cache = new Cache($io, $config->get('cache-files-dir'), 'a-z0-9_./');
18420 }
18421
18422 $dm = new Downloader\DownloadManager($io);
18423 switch ($preferred = $config->get('preferred-install')) {
18424 case 'dist':
18425 $dm->setPreferDist(true);
18426 break;
18427 case 'source':
18428 $dm->setPreferSource(true);
18429 break;
18430 case 'auto':
18431 default:
18432
18433  break;
18434 }
18435
18436 if (is_array($preferred)) {
18437 $dm->setPreferences($preferred);
18438 }
18439
18440 $executor = new ProcessExecutor($io);
18441 $fs = new Filesystem($executor);
18442
18443 $dm->setDownloader('git', new Downloader\GitDownloader($io, $config, $executor, $fs));
18444 $dm->setDownloader('svn', new Downloader\SvnDownloader($io, $config, $executor, $fs));
18445 $dm->setDownloader('fossil', new Downloader\FossilDownloader($io, $config, $executor, $fs));
18446 $dm->setDownloader('hg', new Downloader\HgDownloader($io, $config, $executor, $fs));
18447 $dm->setDownloader('perforce', new Downloader\PerforceDownloader($io, $config));
18448 $dm->setDownloader('zip', new Downloader\ZipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
18449 $dm->setDownloader('rar', new Downloader\RarDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
18450 $dm->setDownloader('tar', new Downloader\TarDownloader($io, $config, $eventDispatcher, $cache, $rfs));
18451 $dm->setDownloader('gzip', new Downloader\GzipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
18452 $dm->setDownloader('xz', new Downloader\XzDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
18453 $dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $eventDispatcher, $cache, $rfs));
18454 $dm->setDownloader('file', new Downloader\FileDownloader($io, $config, $eventDispatcher, $cache, $rfs));
18455 $dm->setDownloader('path', new Downloader\PathDownloader($io, $config, $eventDispatcher, $cache, $rfs));
18456
18457 return $dm;
18458 }
18459
18460
18461
18462
18463
18464
18465 public function createArchiveManager(Config $config, Downloader\DownloadManager $dm = null)
18466 {
18467 if (null === $dm) {
18468 $io = new IO\NullIO();
18469 $io->loadConfiguration($config);
18470 $dm = $this->createDownloadManager($io, $config);
18471 }
18472
18473 $am = new Archiver\ArchiveManager($dm);
18474 $am->addArchiver(new Archiver\ZipArchiver);
18475 $am->addArchiver(new Archiver\PharArchiver);
18476
18477 return $am;
18478 }
18479
18480
18481
18482
18483
18484
18485
18486
18487 protected function createPluginManager(IOInterface $io, Composer $composer, Composer $globalComposer = null, $disablePlugins = false)
18488 {
18489 return new Plugin\PluginManager($io, $composer, $globalComposer, $disablePlugins);
18490 }
18491
18492
18493
18494
18495 protected function createInstallationManager()
18496 {
18497 return new Installer\InstallationManager();
18498 }
18499
18500
18501
18502
18503
18504
18505 protected function createDefaultInstallers(Installer\InstallationManager $im, Composer $composer, IOInterface $io)
18506 {
18507 $im->addInstaller(new Installer\LibraryInstaller($io, $composer, null));
18508 $im->addInstaller(new Installer\PearInstaller($io, $composer, 'pear-library'));
18509 $im->addInstaller(new Installer\PluginInstaller($io, $composer));
18510 $im->addInstaller(new Installer\MetapackageInstaller($io));
18511 }
18512
18513
18514
18515
18516
18517 protected function purgePackages(WritableRepositoryInterface $repo, Installer\InstallationManager $im)
18518 {
18519 foreach ($repo->getPackages() as $package) {
18520 if (!$im->isPackageInstalled($repo, $package)) {
18521 $repo->removePackage($package);
18522 }
18523 }
18524 }
18525
18526
18527
18528
18529
18530
18531
18532
18533 public static function create(IOInterface $io, $config = null, $disablePlugins = false)
18534 {
18535 $factory = new static();
18536
18537 return $factory->createComposer($io, $config, $disablePlugins);
18538 }
18539
18540
18541
18542
18543
18544
18545
18546 public static function createRemoteFilesystem(IOInterface $io, Config $config = null, $options = array())
18547 {
18548 static $warned = false;
18549 $disableTls = false;
18550 if ($config && $config->get('disable-tls') === true) {
18551 if (!$warned) {
18552 $io->write('<warning>You are running Composer with SSL/TLS protection disabled.</warning>');
18553 }
18554 $warned = true;
18555 $disableTls = true;
18556 } elseif (!extension_loaded('openssl')) {
18557 throw new Exception\NoSslException('The openssl extension is required for SSL/TLS protection but is not available. '
18558 . '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.');
18559 }
18560 $remoteFilesystemOptions = array();
18561 if ($disableTls === false) {
18562 if ($config && $config->get('cafile')) {
18563 $remoteFilesystemOptions['ssl']['cafile'] = $config->get('cafile');
18564 }
18565 if ($config && $config->get('capath')) {
18566 $remoteFilesystemOptions['ssl']['capath'] = $config->get('capath');
18567 }
18568 $remoteFilesystemOptions = array_replace_recursive($remoteFilesystemOptions, $options);
18569 }
18570 try {
18571 $remoteFilesystem = new RemoteFilesystem($io, $config, $remoteFilesystemOptions, $disableTls);
18572 } catch (TransportException $e) {
18573 if (false !== strpos($e->getMessage(), 'cafile')) {
18574 $io->write('<error>Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.</error>');
18575 $io->write('<error>A valid CA certificate file is required for SSL/TLS protection.</error>');
18576 if (PHP_VERSION_ID < 50600) {
18577 $io->write('<error>It is recommended you upgrade to PHP 5.6+ which can detect your system CA file automatically.</error>');
18578 }
18579 $io->write('<error>You can disable this error, at your own risk, by setting the \'disable-tls\' option to true.</error>');
18580 }
18581 throw $e;
18582 }
18583
18584 return $remoteFilesystem;
18585 }
18586
18587
18588
18589
18590 private static function useXdg()
18591 {
18592 foreach (array_keys($_SERVER) as $key) {
18593 if (substr($key, 0, 4) === 'XDG_') {
18594 return true;
18595 }
18596 }
18597
18598 return false;
18599 }
18600
18601
18602
18603
18604
18605 private static function getUserDir()
18606 {
18607 $home = getenv('HOME');
18608 if (!$home) {
18609 throw new \RuntimeException('The HOME or COMPOSER_HOME environment variable must be set for composer to run correctly');
18610 }
18611
18612 return rtrim(strtr($home, '\\', '/'), '/');
18613 }
18614 }
18615 <?php
18616
18617
18618
18619
18620
18621
18622
18623
18624
18625
18626
18627 namespace Composer\IO;
18628
18629 use Composer\Config;
18630 use Composer\Util\ProcessExecutor;
18631 use Psr\Log\LoggerInterface;
18632 use Psr\Log\LogLevel;
18633
18634 abstract class BaseIO implements IOInterface, LoggerInterface
18635 {
18636 protected $authentications = array();
18637
18638
18639
18640
18641 public function getAuthentications()
18642 {
18643 return $this->authentications;
18644 }
18645
18646
18647
18648
18649 public function hasAuthentication($repositoryName)
18650 {
18651 return isset($this->authentications[$repositoryName]);
18652 }
18653
18654
18655
18656
18657 public function getAuthentication($repositoryName)
18658 {
18659 if (isset($this->authentications[$repositoryName])) {
18660 return $this->authentications[$repositoryName];
18661 }
18662
18663 return array('username' => null, 'password' => null);
18664 }
18665
18666
18667
18668
18669 public function setAuthentication($repositoryName, $username, $password = null)
18670 {
18671 $this->authentications[$repositoryName] = array('username' => $username, 'password' => $password);
18672 }
18673
18674
18675
18676
18677
18678
18679
18680
18681 protected function checkAndSetAuthentication($repositoryName, $username, $password = null)
18682 {
18683 if ($this->hasAuthentication($repositoryName)) {
18684 $auth = $this->getAuthentication($repositoryName);
18685 if ($auth['username'] === $username && $auth['password'] === $password) {
18686 return;
18687 }
18688
18689 $this->writeError(
18690 sprintf(
18691 "<warning>Warning: You should avoid overwriting already defined auth settings for %s.</warning>",
18692 $repositoryName
18693 )
18694 );
18695 }
18696 $this->setAuthentication($repositoryName, $username, $password);
18697 }
18698
18699
18700
18701
18702 public function loadConfiguration(Config $config)
18703 {
18704 $bitbucketOauth = $config->get('bitbucket-oauth') ?: array();
18705 $githubOauth = $config->get('github-oauth') ?: array();
18706 $gitlabOauth = $config->get('gitlab-oauth') ?: array();
18707 $gitlabToken = $config->get('gitlab-token') ?: array();
18708 $httpBasic = $config->get('http-basic') ?: array();
18709
18710
18711
18712 foreach ($bitbucketOauth as $domain => $cred) {
18713 $this->checkAndSetAuthentication($domain, $cred['consumer-key'], $cred['consumer-secret']);
18714 }
18715
18716 foreach ($githubOauth as $domain => $token) {
18717 if (!preg_match('{^[.a-z0-9]+$}', $token)) {
18718 throw new \UnexpectedValueException('Your github oauth token for '.$domain.' contains invalid characters: "'.$token.'"');
18719 }
18720 $this->checkAndSetAuthentication($domain, $token, 'x-oauth-basic');
18721 }
18722
18723 foreach ($gitlabOauth as $domain => $token) {
18724 $this->checkAndSetAuthentication($domain, $token, 'oauth2');
18725 }
18726
18727 foreach ($gitlabToken as $domain => $token) {
18728 $this->checkAndSetAuthentication($domain, $token, 'private-token');
18729 }
18730
18731
18732  foreach ($httpBasic as $domain => $cred) {
18733 $this->checkAndSetAuthentication($domain, $cred['username'], $cred['password']);
18734 }
18735
18736
18737  ProcessExecutor::setTimeout((int) $config->get('process-timeout'));
18738 }
18739
18740
18741
18742
18743
18744
18745
18746
18747 public function emergency($message, array $context = array())
18748 {
18749 return $this->log(LogLevel::EMERGENCY, $message, $context);
18750 }
18751
18752
18753
18754
18755
18756
18757
18758
18759
18760
18761
18762 public function alert($message, array $context = array())
18763 {
18764 return $this->log(LogLevel::ALERT, $message, $context);
18765 }
18766
18767
18768
18769
18770
18771
18772
18773
18774
18775
18776 public function critical($message, array $context = array())
18777 {
18778 return $this->log(LogLevel::CRITICAL, $message, $context);
18779 }
18780
18781
18782
18783
18784
18785
18786
18787
18788
18789 public function error($message, array $context = array())
18790 {
18791 return $this->log(LogLevel::ERROR, $message, $context);
18792 }
18793
18794
18795
18796
18797
18798
18799
18800
18801
18802
18803
18804 public function warning($message, array $context = array())
18805 {
18806 return $this->log(LogLevel::WARNING, $message, $context);
18807 }
18808
18809
18810
18811
18812
18813
18814
18815
18816 public function notice($message, array $context = array())
18817 {
18818 return $this->log(LogLevel::NOTICE, $message, $context);
18819 }
18820
18821
18822
18823
18824
18825
18826
18827
18828
18829
18830 public function info($message, array $context = array())
18831 {
18832 return $this->log(LogLevel::INFO, $message, $context);
18833 }
18834
18835
18836
18837
18838
18839
18840
18841
18842 public function debug($message, array $context = array())
18843 {
18844 return $this->log(LogLevel::DEBUG, $message, $context);
18845 }
18846
18847
18848
18849
18850
18851
18852
18853
18854
18855 public function log($level, $message, array $context = array())
18856 {
18857 if (in_array($level, array(LogLevel::EMERGENCY, LogLevel::ALERT, LogLevel::CRITICAL, LogLevel::ERROR))) {
18858 $this->writeError('<error>'.$message.'</error>', true, self::NORMAL);
18859 } elseif ($level === LogLevel::WARNING) {
18860 $this->writeError('<warning>'.$message.'</warning>', true, self::NORMAL);
18861 } elseif ($level === LogLevel::NOTICE) {
18862 $this->writeError('<info>'.$message.'</info>', true, self::VERBOSE);
18863 } elseif ($level === LogLevel::INFO) {
18864 $this->writeError('<info>'.$message.'</info>', true, self::VERY_VERBOSE);
18865 } else {
18866 $this->writeError($message, true, self::DEBUG);
18867 }
18868 }
18869 }
18870 <?php
18871
18872
18873
18874
18875
18876
18877
18878
18879
18880
18881
18882 namespace Composer\IO;
18883
18884 use Symfony\Component\Console\Output\StreamOutput;
18885 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
18886 use Symfony\Component\Console\Input\StringInput;
18887 use Symfony\Component\Console\Helper\HelperSet;
18888
18889
18890
18891
18892 class BufferIO extends ConsoleIO
18893 {
18894
18895
18896
18897
18898
18899 public function __construct($input = '', $verbosity = StreamOutput::VERBOSITY_NORMAL, OutputFormatterInterface $formatter = null)
18900 {
18901 $input = new StringInput($input);
18902 $input->setInteractive(false);
18903
18904 $output = new StreamOutput(fopen('php://memory', 'rw'), $verbosity, $formatter ? $formatter->isDecorated() : false, $formatter);
18905
18906 parent::__construct($input, $output, new HelperSet(array()));
18907 }
18908
18909 public function getOutput()
18910 {
18911 fseek($this->output->getStream(), 0);
18912
18913 $output = stream_get_contents($this->output->getStream());
18914
18915 $output = preg_replace_callback("{(?<=^|\n|\x08)(.+?)(\x08+)}", function ($matches) {
18916 $pre = strip_tags($matches[1]);
18917
18918 if (strlen($pre) === strlen($matches[2])) {
18919 return '';
18920 }
18921
18922
18923  return rtrim($matches[1])."\n";
18924 }, $output);
18925
18926 return $output;
18927 }
18928 }
18929 <?php
18930
18931
18932
18933
18934
18935
18936
18937
18938
18939
18940
18941 namespace Composer\IO;
18942
18943 use Symfony\Component\Console\Input\InputInterface;
18944 use Symfony\Component\Console\Output\ConsoleOutputInterface;
18945 use Symfony\Component\Console\Output\OutputInterface;
18946 use Symfony\Component\Console\Helper\HelperSet;
18947 use Composer\Question\StrictConfirmationQuestion;
18948 use Symfony\Component\Console\Question\Question;
18949
18950
18951
18952
18953
18954
18955
18956 class ConsoleIO extends BaseIO
18957 {
18958
18959 protected $input;
18960
18961 protected $output;
18962
18963 protected $helperSet;
18964
18965 protected $lastMessage;
18966
18967 protected $lastMessageErr;
18968
18969
18970 private $startTime;
18971
18972 private $verbosityMap;
18973
18974
18975
18976
18977
18978
18979
18980
18981 public function __construct(InputInterface $input, OutputInterface $output, HelperSet $helperSet)
18982 {
18983 $this->input = $input;
18984 $this->output = $output;
18985 $this->helperSet = $helperSet;
18986 $this->verbosityMap = array(
18987 self::QUIET => OutputInterface::VERBOSITY_QUIET,
18988 self::NORMAL => OutputInterface::VERBOSITY_NORMAL,
18989 self::VERBOSE => OutputInterface::VERBOSITY_VERBOSE,
18990 self::VERY_VERBOSE => OutputInterface::VERBOSITY_VERY_VERBOSE,
18991 self::DEBUG => OutputInterface::VERBOSITY_DEBUG,
18992 );
18993 }
18994
18995
18996
18997
18998 public function enableDebugging($startTime)
18999 {
19000 $this->startTime = $startTime;
19001 }
19002
19003
19004
19005
19006 public function isInteractive()
19007 {
19008 return $this->input->isInteractive();
19009 }
19010
19011
19012
19013
19014 public function isDecorated()
19015 {
19016 return $this->output->isDecorated();
19017 }
19018
19019
19020
19021
19022 public function isVerbose()
19023 {
19024 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE;
19025 }
19026
19027
19028
19029
19030 public function isVeryVerbose()
19031 {
19032 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE;
19033 }
19034
19035
19036
19037
19038 public function isDebug()
19039 {
19040 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG;
19041 }
19042
19043
19044
19045
19046 public function write($messages, $newline = true, $verbosity = self::NORMAL)
19047 {
19048 $this->doWrite($messages, $newline, false, $verbosity);
19049 }
19050
19051
19052
19053
19054 public function writeError($messages, $newline = true, $verbosity = self::NORMAL)
19055 {
19056 $this->doWrite($messages, $newline, true, $verbosity);
19057 }
19058
19059
19060
19061
19062
19063
19064
19065 private function doWrite($messages, $newline, $stderr, $verbosity)
19066 {
19067 $sfVerbosity = $this->verbosityMap[$verbosity];
19068 if ($sfVerbosity > $this->output->getVerbosity()) {
19069 return;
19070 }
19071
19072
19073  
19074  
19075  if (OutputInterface::VERBOSITY_QUIET === 0) {
19076 $sfVerbosity = OutputInterface::OUTPUT_NORMAL;
19077 }
19078
19079 if (null !== $this->startTime) {
19080 $memoryUsage = memory_get_usage() / 1024 / 1024;
19081 $timeSpent = microtime(true) - $this->startTime;
19082 $messages = array_map(function ($message) use ($memoryUsage, $timeSpent) {
19083 return sprintf('[%.1fMB/%.2fs] %s', $memoryUsage, $timeSpent, $message);
19084 }, (array) $messages);
19085 }
19086
19087 if (true === $stderr && $this->output instanceof ConsoleOutputInterface) {
19088 $this->output->getErrorOutput()->write($messages, $newline, $sfVerbosity);
19089 $this->lastMessageErr = implode($newline ? "\n" : '', (array) $messages);
19090
19091 return;
19092 }
19093
19094 $this->output->write($messages, $newline, $sfVerbosity);
19095 $this->lastMessage = implode($newline ? "\n" : '', (array) $messages);
19096 }
19097
19098
19099
19100
19101 public function overwrite($messages, $newline = true, $size = null, $verbosity = self::NORMAL)
19102 {
19103 $this->doOverwrite($messages, $newline, $size, false, $verbosity);
19104 }
19105
19106
19107
19108
19109 public function overwriteError($messages, $newline = true, $size = null, $verbosity = self::NORMAL)
19110 {
19111 $this->doOverwrite($messages, $newline, $size, true, $verbosity);
19112 }
19113
19114
19115
19116
19117
19118
19119
19120
19121 private function doOverwrite($messages, $newline, $size, $stderr, $verbosity)
19122 {
19123
19124  $messages = implode($newline ? "\n" : '', (array) $messages);
19125
19126
19127  if (!isset($size)) {
19128
19129  $size = strlen(strip_tags($stderr ? $this->lastMessageErr : $this->lastMessage));
19130 }
19131
19132  $this->doWrite(str_repeat("\x08", $size), false, $stderr, $verbosity);
19133
19134
19135  $this->doWrite($messages, false, $stderr, $verbosity);
19136
19137
19138  
19139  
19140  $fill = $size - strlen(strip_tags($messages));
19141 if ($fill > 0) {
19142
19143  $this->doWrite(str_repeat(' ', $fill), false, $stderr, $verbosity);
19144
19145  $this->doWrite(str_repeat("\x08", $fill), false, $stderr, $verbosity);
19146 }
19147
19148 if ($newline) {
19149 $this->doWrite('', true, $stderr, $verbosity);
19150 }
19151
19152 if ($stderr) {
19153 $this->lastMessageErr = $messages;
19154 } else {
19155 $this->lastMessage = $messages;
19156 }
19157 }
19158
19159
19160
19161
19162 public function ask($question, $default = null)
19163 {
19164
19165 $helper = $this->helperSet->get('question');
19166 $question = new Question($question, $default);
19167
19168 return $helper->ask($this->input, $this->getErrorOutput(), $question);
19169 }
19170
19171
19172
19173
19174 public function askConfirmation($question, $default = true)
19175 {
19176
19177 $helper = $this->helperSet->get('question');
19178 $question = new StrictConfirmationQuestion($question, $default);
19179
19180 return $helper->ask($this->input, $this->getErrorOutput(), $question);
19181 }
19182
19183
19184
19185
19186 public function askAndValidate($question, $validator, $attempts = null, $default = null)
19187 {
19188
19189 $helper = $this->helperSet->get('question');
19190 $question = new Question($question, $default);
19191 $question->setValidator($validator);
19192 $question->setMaxAttempts($attempts);
19193
19194 return $helper->ask($this->input, $this->getErrorOutput(), $question);
19195 }
19196
19197
19198
19199
19200 public function askAndHideAnswer($question)
19201 {
19202 $this->writeError($question, false);
19203
19204 return \Seld\CliPrompt\CliPrompt::hiddenPrompt(true);
19205 }
19206
19207
19208
19209
19210 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
19211 {
19212 if ($this->isInteractive()) {
19213 return $this->helperSet->get('dialog')->select($this->getErrorOutput(), $question, $choices, $default, $attempts, $errorMessage, $multiselect);
19214 }
19215
19216 return $default;
19217 }
19218
19219
19220
19221
19222 private function getErrorOutput()
19223 {
19224 if ($this->output instanceof ConsoleOutputInterface) {
19225 return $this->output->getErrorOutput();
19226 }
19227
19228 return $this->output;
19229 }
19230 }
19231 <?php
19232
19233
19234
19235
19236
19237
19238
19239
19240
19241
19242
19243 namespace Composer\IO;
19244
19245 use Composer\Config;
19246
19247
19248
19249
19250
19251
19252 interface IOInterface
19253 {
19254 const QUIET = 1;
19255 const NORMAL = 2;
19256 const VERBOSE = 4;
19257 const VERY_VERBOSE = 8;
19258 const DEBUG = 16;
19259
19260
19261
19262
19263
19264
19265 public function isInteractive();
19266
19267
19268
19269
19270
19271
19272 public function isVerbose();
19273
19274
19275
19276
19277
19278
19279 public function isVeryVerbose();
19280
19281
19282
19283
19284
19285
19286 public function isDebug();
19287
19288
19289
19290
19291
19292
19293 public function isDecorated();
19294
19295
19296
19297
19298
19299
19300
19301
19302 public function write($messages, $newline = true, $verbosity = self::NORMAL);
19303
19304
19305
19306
19307
19308
19309
19310
19311 public function writeError($messages, $newline = true, $verbosity = self::NORMAL);
19312
19313
19314
19315
19316
19317
19318
19319
19320
19321 public function overwrite($messages, $newline = true, $size = null, $verbosity = self::NORMAL);
19322
19323
19324
19325
19326
19327
19328
19329
19330
19331 public function overwriteError($messages, $newline = true, $size = null, $verbosity = self::NORMAL);
19332
19333
19334
19335
19336
19337
19338
19339
19340
19341
19342 public function ask($question, $default = null);
19343
19344
19345
19346
19347
19348
19349
19350
19351
19352
19353
19354 public function askConfirmation($question, $default = true);
19355
19356
19357
19358
19359
19360
19361
19362
19363
19364
19365
19366
19367
19368
19369
19370
19371 public function askAndValidate($question, $validator, $attempts = null, $default = null);
19372
19373
19374
19375
19376
19377
19378
19379
19380 public function askAndHideAnswer($question);
19381
19382
19383
19384
19385
19386
19387
19388
19389
19390
19391
19392
19393
19394
19395 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false);
19396
19397
19398
19399
19400
19401
19402 public function getAuthentications();
19403
19404
19405
19406
19407
19408
19409
19410
19411 public function hasAuthentication($repositoryName);
19412
19413
19414
19415
19416
19417
19418
19419
19420 public function getAuthentication($repositoryName);
19421
19422
19423
19424
19425
19426
19427
19428
19429 public function setAuthentication($repositoryName, $username, $password = null);
19430
19431
19432
19433
19434
19435
19436 public function loadConfiguration(Config $config);
19437 }
19438 <?php
19439
19440
19441
19442
19443
19444
19445
19446
19447
19448
19449
19450 namespace Composer\IO;
19451
19452
19453
19454
19455
19456
19457 class NullIO extends BaseIO
19458 {
19459
19460
19461
19462 public function isInteractive()
19463 {
19464 return false;
19465 }
19466
19467
19468
19469
19470 public function isVerbose()
19471 {
19472 return false;
19473 }
19474
19475
19476
19477
19478 public function isVeryVerbose()
19479 {
19480 return false;
19481 }
19482
19483
19484
19485
19486 public function isDebug()
19487 {
19488 return false;
19489 }
19490
19491
19492
19493
19494 public function isDecorated()
19495 {
19496 return false;
19497 }
19498
19499
19500
19501
19502 public function write($messages, $newline = true, $verbosity = self::NORMAL)
19503 {
19504 }
19505
19506
19507
19508
19509 public function writeError($messages, $newline = true, $verbosity = self::NORMAL)
19510 {
19511 }
19512
19513
19514
19515
19516 public function overwrite($messages, $newline = true, $size = 80, $verbosity = self::NORMAL)
19517 {
19518 }
19519
19520
19521
19522
19523 public function overwriteError($messages, $newline = true, $size = 80, $verbosity = self::NORMAL)
19524 {
19525 }
19526
19527
19528
19529
19530 public function ask($question, $default = null)
19531 {
19532 return $default;
19533 }
19534
19535
19536
19537
19538 public function askConfirmation($question, $default = true)
19539 {
19540 return $default;
19541 }
19542
19543
19544
19545
19546 public function askAndValidate($question, $validator, $attempts = false, $default = null)
19547 {
19548 return $default;
19549 }
19550
19551
19552
19553
19554 public function askAndHideAnswer($question)
19555 {
19556 return null;
19557 }
19558
19559
19560
19561
19562 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
19563 {
19564 return $default;
19565 }
19566 }
19567 <?php
19568
19569
19570
19571
19572
19573
19574
19575
19576
19577
19578
19579 namespace Composer;
19580
19581 use Composer\Autoload\AutoloadGenerator;
19582 use Composer\DependencyResolver\DefaultPolicy;
19583 use Composer\DependencyResolver\Operation\UpdateOperation;
19584 use Composer\DependencyResolver\Operation\InstallOperation;
19585 use Composer\DependencyResolver\Operation\UninstallOperation;
19586 use Composer\DependencyResolver\Operation\OperationInterface;
19587 use Composer\DependencyResolver\PolicyInterface;
19588 use Composer\DependencyResolver\Pool;
19589 use Composer\DependencyResolver\Request;
19590 use Composer\DependencyResolver\Rule;
19591 use Composer\DependencyResolver\Solver;
19592 use Composer\DependencyResolver\SolverProblemsException;
19593 use Composer\Downloader\DownloadManager;
19594 use Composer\EventDispatcher\EventDispatcher;
19595 use Composer\Installer\InstallationManager;
19596 use Composer\Installer\InstallerEvents;
19597 use Composer\Installer\NoopInstaller;
19598 use Composer\Installer\SuggestedPackagesReporter;
19599 use Composer\IO\IOInterface;
19600 use Composer\Package\AliasPackage;
19601 use Composer\Package\CompletePackage;
19602 use Composer\Package\Link;
19603 use Composer\Package\Loader\ArrayLoader;
19604 use Composer\Package\Dumper\ArrayDumper;
19605 use Composer\Semver\Constraint\Constraint;
19606 use Composer\Package\Locker;
19607 use Composer\Package\PackageInterface;
19608 use Composer\Package\RootPackageInterface;
19609 use Composer\Repository\CompositeRepository;
19610 use Composer\Repository\InstalledArrayRepository;
19611 use Composer\Repository\PlatformRepository;
19612 use Composer\Repository\RepositoryInterface;
19613 use Composer\Repository\RepositoryManager;
19614 use Composer\Repository\WritableRepositoryInterface;
19615 use Composer\Script\ScriptEvents;
19616
19617
19618
19619
19620
19621
19622
19623 class Installer
19624 {
19625
19626
19627
19628 protected $io;
19629
19630
19631
19632
19633 protected $config;
19634
19635
19636
19637
19638 protected $package;
19639
19640
19641
19642
19643 protected $downloadManager;
19644
19645
19646
19647
19648 protected $repositoryManager;
19649
19650
19651
19652
19653 protected $locker;
19654
19655
19656
19657
19658 protected $installationManager;
19659
19660
19661
19662
19663 protected $eventDispatcher;
19664
19665
19666
19667
19668 protected $autoloadGenerator;
19669
19670 protected $preferSource = false;
19671 protected $preferDist = false;
19672 protected $optimizeAutoloader = false;
19673 protected $classMapAuthoritative = false;
19674 protected $apcuAutoloader = false;
19675 protected $devMode = false;
19676 protected $dryRun = false;
19677 protected $verbose = false;
19678 protected $update = false;
19679 protected $dumpAutoloader = true;
19680 protected $runScripts = true;
19681 protected $ignorePlatformReqs = false;
19682 protected $preferStable = false;
19683 protected $preferLowest = false;
19684 protected $skipSuggest = false;
19685 protected $writeLock = true;
19686 protected $executeOperations = true;
19687
19688
19689
19690
19691
19692
19693 protected $updateWhitelist = null;
19694 protected $whitelistDependencies = false;
19695
19696
19697
19698
19699 protected $suggestedPackagesReporter;
19700
19701
19702
19703
19704 protected $additionalInstalledRepository;
19705
19706
19707
19708
19709
19710
19711
19712
19713
19714
19715
19716
19717
19718
19719 public function __construct(IOInterface $io, Config $config, RootPackageInterface $package, DownloadManager $downloadManager, RepositoryManager $repositoryManager, Locker $locker, InstallationManager $installationManager, EventDispatcher $eventDispatcher, AutoloadGenerator $autoloadGenerator)
19720 {
19721 $this->io = $io;
19722 $this->config = $config;
19723 $this->package = $package;
19724 $this->downloadManager = $downloadManager;
19725 $this->repositoryManager = $repositoryManager;
19726 $this->locker = $locker;
19727 $this->installationManager = $installationManager;
19728 $this->eventDispatcher = $eventDispatcher;
19729 $this->autoloadGenerator = $autoloadGenerator;
19730 }
19731
19732
19733
19734
19735
19736
19737
19738 public function run()
19739 {
19740
19741  
19742  
19743  
19744  gc_collect_cycles();
19745 gc_disable();
19746
19747
19748  if (!$this->update && !$this->locker->isLocked()) {
19749 $this->update = true;
19750 }
19751
19752 if ($this->dryRun) {
19753 $this->verbose = true;
19754 $this->runScripts = false;
19755 $this->executeOperations = false;
19756 $this->writeLock = false;
19757 $this->dumpAutoloader = false;
19758 $this->installationManager->addInstaller(new NoopInstaller);
19759 $this->mockLocalRepositories($this->repositoryManager);
19760 }
19761
19762 if ($this->runScripts) {
19763 $devMode = (int) $this->devMode;
19764 putenv("COMPOSER_DEV_MODE=$devMode");
19765
19766
19767  $eventName = $this->update ? ScriptEvents::PRE_UPDATE_CMD : ScriptEvents::PRE_INSTALL_CMD;
19768 $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
19769 }
19770
19771 $this->downloadManager->setPreferSource($this->preferSource);
19772 $this->downloadManager->setPreferDist($this->preferDist);
19773
19774
19775  $localRepo = $this->repositoryManager->getLocalRepository();
19776 if ($this->update) {
19777 $platformOverrides = $this->config->get('platform') ?: array();
19778 } else {
19779 $platformOverrides = $this->locker->getPlatformOverrides();
19780 }
19781 $platformRepo = new PlatformRepository(array(), $platformOverrides);
19782 $installedRepo = $this->createInstalledRepo($localRepo, $platformRepo);
19783
19784 $aliases = $this->getRootAliases();
19785 $this->aliasPlatformPackages($platformRepo, $aliases);
19786
19787 if (!$this->suggestedPackagesReporter) {
19788 $this->suggestedPackagesReporter = new SuggestedPackagesReporter($this->io);
19789 }
19790
19791 try {
19792 list($res, $devPackages) = $this->doInstall($localRepo, $installedRepo, $platformRepo, $aliases);
19793 if ($res !== 0) {
19794 return $res;
19795 }
19796 } catch (\Exception $e) {
19797 if ($this->executeOperations) {
19798 $this->installationManager->notifyInstalls($this->io);
19799 }
19800
19801 throw $e;
19802 }
19803 if ($this->executeOperations) {
19804 $this->installationManager->notifyInstalls($this->io);
19805 }
19806
19807
19808  if ($this->devMode && !$this->skipSuggest) {
19809 $this->suggestedPackagesReporter->output($installedRepo);
19810 }
19811
19812
19813  foreach ($localRepo->getPackages() as $package) {
19814 if (!$package instanceof CompletePackage || !$package->isAbandoned()) {
19815 continue;
19816 }
19817
19818 $replacement = (is_string($package->getReplacementPackage()))
19819 ? 'Use ' . $package->getReplacementPackage() . ' instead'
19820 : 'No replacement was suggested';
19821
19822 $this->io->writeError(
19823 sprintf(
19824 "<warning>Package %s is abandoned, you should avoid using it. %s.</warning>",
19825 $package->getPrettyName(),
19826 $replacement
19827 )
19828 );
19829 }
19830
19831
19832  if ($this->update && $this->writeLock) {
19833 $localRepo->reload();
19834
19835 $platformReqs = $this->extractPlatformRequirements($this->package->getRequires());
19836 $platformDevReqs = $this->extractPlatformRequirements($this->package->getDevRequires());
19837
19838 $updatedLock = $this->locker->setLockData(
19839 array_diff($localRepo->getCanonicalPackages(), $devPackages),
19840 $devPackages,
19841 $platformReqs,
19842 $platformDevReqs,
19843 $aliases,
19844 $this->package->getMinimumStability(),
19845 $this->package->getStabilityFlags(),
19846 $this->preferStable || $this->package->getPreferStable(),
19847 $this->preferLowest,
19848 $this->config->get('platform') ?: array()
19849 );
19850 if ($updatedLock) {
19851 $this->io->writeError('<info>Writing lock file</info>');
19852 }
19853 }
19854
19855 if ($this->dumpAutoloader) {
19856
19857  if ($this->optimizeAutoloader) {
19858 $this->io->writeError('<info>Generating optimized autoload files</info>');
19859 } else {
19860 $this->io->writeError('<info>Generating autoload files</info>');
19861 }
19862
19863 $this->autoloadGenerator->setDevMode($this->devMode);
19864 $this->autoloadGenerator->setClassMapAuthoritative($this->classMapAuthoritative);
19865 $this->autoloadGenerator->setApcu($this->apcuAutoloader);
19866 $this->autoloadGenerator->setRunScripts($this->runScripts);
19867 $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader);
19868 }
19869
19870 if ($this->executeOperations) {
19871
19872  foreach ($localRepo->getPackages() as $package) {
19873 $this->installationManager->ensureBinariesPresence($package);
19874 }
19875
19876 $vendorDir = $this->config->get('vendor-dir');
19877 if (is_dir($vendorDir)) {
19878
19879  
19880  @touch($vendorDir);
19881 }
19882 }
19883
19884 if ($this->runScripts) {
19885
19886  $eventName = $this->update ? ScriptEvents::POST_UPDATE_CMD : ScriptEvents::POST_INSTALL_CMD;
19887 $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
19888 }
19889
19890
19891  if (!defined('HHVM_VERSION')) {
19892 gc_enable();
19893 }
19894
19895 return 0;
19896 }
19897
19898
19899
19900
19901
19902
19903
19904
19905 protected function doInstall($localRepo, $installedRepo, $platformRepo, $aliases)
19906 {
19907
19908  $lockedRepository = null;
19909 $repositories = null;
19910
19911
19912  
19913  
19914  if (!$this->update || (!empty($this->updateWhitelist) && $this->locker->isLocked())) {
19915 try {
19916 $lockedRepository = $this->locker->getLockedRepository($this->devMode);
19917 } catch (\RuntimeException $e) {
19918
19919  if ($this->package->getDevRequires()) {
19920 throw $e;
19921 }
19922
19923  $lockedRepository = $this->locker->getLockedRepository();
19924 }
19925 }
19926
19927 $this->whitelistUpdateDependencies(
19928 $lockedRepository ?: $localRepo,
19929 $this->package->getRequires(),
19930 $this->package->getDevRequires()
19931 );
19932
19933 $this->io->writeError('<info>Loading composer repositories with package information</info>');
19934
19935
19936  $policy = $this->createPolicy();
19937 $pool = $this->createPool($this->update ? null : $lockedRepository);
19938 $pool->addRepository($installedRepo, $aliases);
19939 if ($this->update) {
19940 $repositories = $this->repositoryManager->getRepositories();
19941 foreach ($repositories as $repository) {
19942 $pool->addRepository($repository, $aliases);
19943 }
19944 }
19945
19946  
19947  
19948  if ($lockedRepository) {
19949 $pool->addRepository($lockedRepository, $aliases);
19950 }
19951
19952
19953  $request = $this->createRequest($this->package, $platformRepo);
19954
19955 if ($this->update) {
19956
19957  $removedUnstablePackages = array();
19958 foreach ($localRepo->getPackages() as $package) {
19959 if (
19960 !$pool->isPackageAcceptable($package->getNames(), $package->getStability())
19961 && $this->installationManager->isPackageInstalled($localRepo, $package)
19962 ) {
19963 $removedUnstablePackages[$package->getName()] = true;
19964 $request->remove($package->getName(), new Constraint('=', $package->getVersion()));
19965 }
19966 }
19967
19968 $this->io->writeError('<info>Updating dependencies'.($this->devMode ? ' (including require-dev)' : '').'</info>');
19969
19970 $request->updateAll();
19971
19972 $links = array_merge($this->package->getRequires(), $this->package->getDevRequires());
19973
19974 foreach ($links as $link) {
19975 $request->install($link->getTarget(), $link->getConstraint());
19976 }
19977
19978
19979  
19980  if ($this->updateWhitelist) {
19981 $currentPackages = $this->getCurrentPackages($installedRepo);
19982
19983
19984  $candidates = array();
19985 foreach ($links as $link) {
19986 $candidates[$link->getTarget()] = true;
19987 $rootRequires[$link->getTarget()] = $link;
19988 }
19989 foreach ($currentPackages as $package) {
19990 $candidates[$package->getName()] = true;
19991 }
19992
19993
19994  foreach ($candidates as $candidate => $dummy) {
19995 foreach ($currentPackages as $curPackage) {
19996 if ($curPackage->getName() === $candidate) {
19997 if (!$this->isUpdateable($curPackage) && !isset($removedUnstablePackages[$curPackage->getName()])) {
19998 $constraint = new Constraint('=', $curPackage->getVersion());
19999 $description = $this->locker->isLocked() ? '(locked at' : '(installed at';
20000 $requiredAt = isset($rootRequires[$candidate]) ? ', required as ' . $rootRequires[$candidate]->getPrettyConstraint() : '';
20001 $constraint->setPrettyString($description . ' ' . $curPackage->getPrettyVersion() . $requiredAt . ')');
20002 $request->install($curPackage->getName(), $constraint);
20003 }
20004 break;
20005 }
20006 }
20007 }
20008 }
20009 } else {
20010 $this->io->writeError('<info>Installing dependencies'.($this->devMode ? ' (including require-dev)' : '').' from lock file</info>');
20011
20012 if (!$this->locker->isFresh()) {
20013 $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);
20014 }
20015
20016 foreach ($lockedRepository->getPackages() as $package) {
20017 $version = $package->getVersion();
20018 if (isset($aliases[$package->getName()][$version])) {
20019 $version = $aliases[$package->getName()][$version]['alias_normalized'];
20020 }
20021 $constraint = new Constraint('=', $version);
20022 $constraint->setPrettyString($package->getPrettyVersion());
20023 $request->install($package->getName(), $constraint);
20024 }
20025
20026 foreach ($this->locker->getPlatformRequirements($this->devMode) as $link) {
20027 $request->install($link->getTarget(), $link->getConstraint());
20028 }
20029 }
20030
20031
20032  $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, 'force-links');
20033
20034
20035  $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request);
20036 $solver = new Solver($policy, $pool, $installedRepo, $this->io);
20037 try {
20038 $operations = $solver->solve($request, $this->ignorePlatformReqs);
20039 } catch (SolverProblemsException $e) {
20040 $this->io->writeError('<error>Your requirements could not be resolved to an installable set of packages.</error>', true, IOInterface::QUIET);
20041 $this->io->writeError($e->getMessage());
20042 if ($this->update && !$this->devMode) {
20043 $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);
20044 }
20045
20046 return array(max(1, $e->getCode()), array());
20047 }
20048
20049
20050  $operations = $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, 'force-updates', $operations);
20051
20052 $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request, $operations);
20053
20054 $this->io->writeError("Analyzed ".count($pool)." packages to resolve dependencies", true, IOInterface::VERBOSE);
20055 $this->io->writeError("Analyzed ".$solver->getRuleSetSize()." rules to resolve dependencies", true, IOInterface::VERBOSE);
20056
20057
20058  if (!$operations) {
20059 $this->io->writeError('Nothing to install or update');
20060 }
20061
20062 $operations = $this->movePluginsToFront($operations);
20063 $operations = $this->moveUninstallsToFront($operations);
20064
20065
20066  
20067  if ($this->update) {
20068 $devPackages = $this->extractDevPackages($operations, $localRepo, $platformRepo, $aliases);
20069 if (!$this->devMode) {
20070 $operations = $this->filterDevPackageOperations($devPackages, $operations, $localRepo);
20071 }
20072 } else {
20073 $devPackages = null;
20074 }
20075
20076 if ($operations) {
20077 $installs = $updates = $uninstalls = array();
20078 foreach ($operations as $operation) {
20079 if ($operation instanceof InstallOperation) {
20080 $installs[] = $operation->getPackage()->getPrettyName().':'.$operation->getPackage()->getFullPrettyVersion();
20081 } elseif ($operation instanceof UpdateOperation) {
20082 $updates[] = $operation->getTargetPackage()->getPrettyName().':'.$operation->getTargetPackage()->getFullPrettyVersion();
20083 } elseif ($operation instanceof UninstallOperation) {
20084 $uninstalls[] = $operation->getPackage()->getPrettyName();
20085 }
20086 }
20087
20088 $this->io->writeError(
20089 sprintf("<info>Package operations: %d install%s, %d update%s, %d removal%s</info>",
20090 count($installs),
20091 1 === count($installs) ? '' : 's',
20092 count($updates),
20093 1 === count($updates) ? '' : 's',
20094 count($uninstalls),
20095 1 === count($uninstalls) ? '' : 's')
20096 );
20097 if ($installs) {
20098 $this->io->writeError("Installs: ".implode(', ', $installs), true, IOInterface::VERBOSE);
20099 }
20100 if ($updates) {
20101 $this->io->writeError("Updates: ".implode(', ', $updates), true, IOInterface::VERBOSE);
20102 }
20103 if ($uninstalls) {
20104 $this->io->writeError("Removals: ".implode(', ', $uninstalls), true, IOInterface::VERBOSE);
20105 }
20106 }
20107
20108 foreach ($operations as $operation) {
20109
20110  if ('install' === $operation->getJobType()) {
20111 $this->suggestedPackagesReporter->addSuggestionsFromPackage($operation->getPackage());
20112 }
20113
20114
20115  if ($this->update) {
20116 $package = null;
20117 if ('update' === $operation->getJobType()) {
20118 $package = $operation->getTargetPackage();
20119 } elseif ('install' === $operation->getJobType()) {
20120 $package = $operation->getPackage();
20121 }
20122 if ($package && $package->isDev()) {
20123 $references = $this->package->getReferences();
20124 if (isset($references[$package->getName()])) {
20125 $this->updateInstallReferences($package, $references[$package->getName()]);
20126 }
20127 }
20128 if ('update' === $operation->getJobType()
20129 && $operation->getTargetPackage()->isDev()
20130 && $operation->getTargetPackage()->getVersion() === $operation->getInitialPackage()->getVersion()
20131 && (!$operation->getTargetPackage()->getSourceReference() || $operation->getTargetPackage()->getSourceReference() === $operation->getInitialPackage()->getSourceReference())
20132 && (!$operation->getTargetPackage()->getDistReference() || $operation->getTargetPackage()->getDistReference() === $operation->getInitialPackage()->getDistReference())
20133 ) {
20134 $this->io->writeError('  - Skipping update of '. $operation->getTargetPackage()->getPrettyName().' to the same reference-locked version', true, IOInterface::DEBUG);
20135 $this->io->writeError('', true, IOInterface::DEBUG);
20136
20137 continue;
20138 }
20139 }
20140
20141 $event = 'Composer\Installer\PackageEvents::PRE_PACKAGE_'.strtoupper($operation->getJobType());
20142 if (defined($event) && $this->runScripts) {
20143 $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
20144 }
20145
20146
20147  if (!$this->executeOperations && false === strpos($operation->getJobType(), 'Alias')) {
20148 $this->io->writeError('  - ' . $operation);
20149 } elseif ($this->io->isDebug() && false !== strpos($operation->getJobType(), 'Alias')) {
20150 $this->io->writeError('  - ' . $operation);
20151 }
20152
20153 $this->installationManager->execute($localRepo, $operation);
20154
20155
20156  if ($this->verbose && $this->io->isVeryVerbose() && in_array($operation->getJobType(), array('install', 'update'))) {
20157 $reason = $operation->getReason();
20158 if ($reason instanceof Rule) {
20159 switch ($reason->getReason()) {
20160 case Rule::RULE_JOB_INSTALL:
20161 $this->io->writeError('    REASON: Required by the root package: '.$reason->getPrettyString($pool));
20162 $this->io->writeError('');
20163 break;
20164 case Rule::RULE_PACKAGE_REQUIRES:
20165 $this->io->writeError('    REASON: '.$reason->getPrettyString($pool));
20166 $this->io->writeError('');
20167 break;
20168 }
20169 }
20170 }
20171
20172 $event = 'Composer\Installer\PackageEvents::POST_PACKAGE_'.strtoupper($operation->getJobType());
20173 if (defined($event) && $this->runScripts) {
20174 $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
20175 }
20176
20177 if ($this->executeOperations || $this->writeLock) {
20178 $localRepo->write();
20179 }
20180 }
20181
20182 if ($this->executeOperations) {
20183
20184  $this->processPackageUrls($pool, $policy, $localRepo, $repositories);
20185 $localRepo->write();
20186 }
20187
20188 return array(0, $devPackages);
20189 }
20190
20191
20192
20193
20194
20195
20196
20197
20198
20199
20200
20201 private function extractDevPackages(array $operations, RepositoryInterface $localRepo, PlatformRepository $platformRepo, array $aliases)
20202 {
20203 if (!$this->package->getDevRequires()) {
20204 return array();
20205 }
20206
20207
20208  $tempLocalRepo = clone $localRepo;
20209 foreach ($operations as $operation) {
20210 switch ($operation->getJobType()) {
20211 case 'install':
20212 case 'markAliasInstalled':
20213 if (!$tempLocalRepo->hasPackage($operation->getPackage())) {
20214 $tempLocalRepo->addPackage(clone $operation->getPackage());
20215 }
20216 break;
20217
20218 case 'uninstall':
20219 case 'markAliasUninstalled':
20220 $tempLocalRepo->removePackage($operation->getPackage());
20221 break;
20222
20223 case 'update':
20224 $tempLocalRepo->removePackage($operation->getInitialPackage());
20225 if (!$tempLocalRepo->hasPackage($operation->getTargetPackage())) {
20226 $tempLocalRepo->addPackage(clone $operation->getTargetPackage());
20227 }
20228 break;
20229
20230 default:
20231 throw new \LogicException('Unknown type: '.$operation->getJobType());
20232 }
20233 }
20234
20235
20236  
20237  
20238  $localRepo = new InstalledArrayRepository(array());
20239 $loader = new ArrayLoader(null, true);
20240 $dumper = new ArrayDumper();
20241 foreach ($tempLocalRepo->getCanonicalPackages() as $pkg) {
20242 $localRepo->addPackage($loader->load($dumper->dump($pkg)));
20243 }
20244 unset($tempLocalRepo, $loader, $dumper);
20245
20246 $policy = $this->createPolicy();
20247 $pool = $this->createPool();
20248 $installedRepo = $this->createInstalledRepo($localRepo, $platformRepo);
20249 $pool->addRepository($installedRepo, $aliases);
20250
20251
20252  $request = $this->createRequest($this->package, $platformRepo);
20253 $request->updateAll();
20254 foreach ($this->package->getRequires() as $link) {
20255 $request->install($link->getTarget(), $link->getConstraint());
20256 }
20257
20258
20259  $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request);
20260 $solver = new Solver($policy, $pool, $installedRepo, $this->io);
20261 $ops = $solver->solve($request, $this->ignorePlatformReqs);
20262 $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request, $ops);
20263
20264 $devPackages = array();
20265 foreach ($ops as $op) {
20266 if ($op->getJobType() === 'uninstall') {
20267 $devPackages[] = $op->getPackage();
20268 }
20269 }
20270
20271 return $devPackages;
20272 }
20273
20274
20275
20276
20277 private function filterDevPackageOperations(array $devPackages, array $operations, RepositoryInterface $localRepo)
20278 {
20279 $finalOps = array();
20280 $packagesToSkip = array();
20281 foreach ($devPackages as $pkg) {
20282 $packagesToSkip[$pkg->getName()] = true;
20283 if ($installedDevPkg = $localRepo->findPackage($pkg->getName(), '*')) {
20284 $finalOps[] = new UninstallOperation($installedDevPkg, 'non-dev install removing it');
20285 }
20286 }
20287
20288
20289  foreach ($operations as $op) {
20290 $package = $op->getJobType() === 'update' ? $op->getTargetPackage() : $op->getPackage();
20291 if (isset($packagesToSkip[$package->getName()])) {
20292 continue;
20293 }
20294
20295 $finalOps[] = $op;
20296 }
20297
20298 return $finalOps;
20299 }
20300
20301
20302
20303
20304
20305
20306
20307
20308
20309
20310
20311
20312
20313
20314 private function movePluginsToFront(array $operations)
20315 {
20316 $pluginsNoDeps = array();
20317 $pluginsWithDeps = array();
20318 $pluginRequires = array();
20319
20320 foreach (array_reverse($operations, true) as $idx => $op) {
20321 if ($op instanceof InstallOperation) {
20322 $package = $op->getPackage();
20323 } elseif ($op instanceof UpdateOperation) {
20324 $package = $op->getTargetPackage();
20325 } else {
20326 continue;
20327 }
20328
20329
20330  $isPlugin = $package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer';
20331
20332
20333  if ($isPlugin || count(array_intersect($package->getNames(), $pluginRequires))) {
20334
20335  $requires = array_filter(array_keys($package->getRequires()), function($req) {
20336 return $req !== 'composer-plugin-api' && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req);
20337 });
20338
20339
20340  if ($isPlugin && !count($requires)) {
20341
20342  array_unshift($pluginsNoDeps, $op);
20343 } else {
20344
20345  $pluginRequires = array_merge($pluginRequires, $requires);
20346
20347  array_unshift($pluginsWithDeps, $op);
20348 }
20349
20350 unset($operations[$idx]);
20351 }
20352 }
20353
20354 return array_merge($pluginsNoDeps, $pluginsWithDeps, $operations);
20355 }
20356
20357
20358
20359
20360
20361
20362
20363
20364 private function moveUninstallsToFront(array $operations)
20365 {
20366 $uninstOps = array();
20367 foreach ($operations as $idx => $op) {
20368 if ($op instanceof UninstallOperation) {
20369 $uninstOps[] = $op;
20370 unset($operations[$idx]);
20371 }
20372 }
20373
20374 return array_merge($uninstOps, $operations);
20375 }
20376
20377
20378
20379
20380 private function createInstalledRepo(RepositoryInterface $localRepo, PlatformRepository $platformRepo)
20381 {
20382
20383  
20384  
20385  $installedRootPackage = clone $this->package;
20386 $installedRootPackage->setRequires(array());
20387 $installedRootPackage->setDevRequires(array());
20388
20389 $repos = array(
20390 $localRepo,
20391 new InstalledArrayRepository(array($installedRootPackage)),
20392 $platformRepo,
20393 );
20394 $installedRepo = new CompositeRepository($repos);
20395 if ($this->additionalInstalledRepository) {
20396 $installedRepo->addRepository($this->additionalInstalledRepository);
20397 }
20398
20399 return $installedRepo;
20400 }
20401
20402
20403
20404
20405
20406 private function createPool(RepositoryInterface $lockedRepository = null)
20407 {
20408 if ($this->update) {
20409 $minimumStability = $this->package->getMinimumStability();
20410 $stabilityFlags = $this->package->getStabilityFlags();
20411
20412 $requires = array_merge($this->package->getRequires(), $this->package->getDevRequires());
20413 } else {
20414 $minimumStability = $this->locker->getMinimumStability();
20415 $stabilityFlags = $this->locker->getStabilityFlags();
20416
20417 $requires = array();
20418 foreach ($lockedRepository->getPackages() as $package) {
20419 $constraint = new Constraint('=', $package->getVersion());
20420 $constraint->setPrettyString($package->getPrettyVersion());
20421 $requires[$package->getName()] = $constraint;
20422 }
20423 }
20424
20425 $rootConstraints = array();
20426 foreach ($requires as $req => $constraint) {
20427
20428  if ($this->ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req)) {
20429 continue;
20430 }
20431 if ($constraint instanceof Link) {
20432 $rootConstraints[$req] = $constraint->getConstraint();
20433 } else {
20434 $rootConstraints[$req] = $constraint;
20435 }
20436 }
20437
20438 return new Pool($minimumStability, $stabilityFlags, $rootConstraints);
20439 }
20440
20441
20442
20443
20444 private function createPolicy()
20445 {
20446 $preferStable = null;
20447 $preferLowest = null;
20448 if (!$this->update) {
20449 $preferStable = $this->locker->getPreferStable();
20450 $preferLowest = $this->locker->getPreferLowest();
20451 }
20452
20453  
20454  if (null === $preferStable) {
20455 $preferStable = $this->preferStable || $this->package->getPreferStable();
20456 }
20457 if (null === $preferLowest) {
20458 $preferLowest = $this->preferLowest;
20459 }
20460
20461 return new DefaultPolicy($preferStable, $preferLowest);
20462 }
20463
20464
20465
20466
20467
20468
20469 private function createRequest(RootPackageInterface $rootPackage, PlatformRepository $platformRepo)
20470 {
20471 $request = new Request();
20472
20473 $constraint = new Constraint('=', $rootPackage->getVersion());
20474 $constraint->setPrettyString($rootPackage->getPrettyVersion());
20475 $request->install($rootPackage->getName(), $constraint);
20476
20477 $fixedPackages = $platformRepo->getPackages();
20478 if ($this->additionalInstalledRepository) {
20479 $additionalFixedPackages = $this->additionalInstalledRepository->getPackages();
20480 $fixedPackages = array_merge($fixedPackages, $additionalFixedPackages);
20481 }
20482
20483
20484  
20485  $provided = $rootPackage->getProvides();
20486 foreach ($fixedPackages as $package) {
20487 $constraint = new Constraint('=', $package->getVersion());
20488 $constraint->setPrettyString($package->getPrettyVersion());
20489
20490
20491  if ($package->getRepository() !== $platformRepo
20492 || !isset($provided[$package->getName()])
20493 || !$provided[$package->getName()]->getConstraint()->matches($constraint)
20494 ) {
20495 $request->fix($package->getName(), $constraint);
20496 }
20497 }
20498
20499 return $request;
20500 }
20501
20502
20503
20504
20505
20506
20507
20508
20509
20510
20511
20512
20513 private function processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, $task, array $operations = null)
20514 {
20515 if ($task === 'force-updates' && null === $operations) {
20516 throw new \InvalidArgumentException('Missing operations argument');
20517 }
20518 if ($task === 'force-links') {
20519 $operations = array();
20520 }
20521
20522 if ($this->update && $this->updateWhitelist) {
20523 $currentPackages = $this->getCurrentPackages($installedRepo);
20524 }
20525
20526 foreach ($localRepo->getCanonicalPackages() as $package) {
20527
20528  if (!$package->isDev()) {
20529 continue;
20530 }
20531
20532
20533  foreach ($operations as $operation) {
20534 if (('update' === $operation->getJobType() && $operation->getInitialPackage()->equals($package))
20535 || ('uninstall' === $operation->getJobType() && $operation->getPackage()->equals($package))
20536 ) {
20537 continue 2;
20538 }
20539 }
20540
20541 if ($this->update) {
20542
20543  if ($this->updateWhitelist && !$this->isUpdateable($package)) {
20544
20545  foreach ($currentPackages as $curPackage) {
20546 if ($curPackage->isDev() && $curPackage->getName() === $package->getName() && $curPackage->getVersion() === $package->getVersion()) {
20547 if ($task === 'force-links') {
20548 $package->setRequires($curPackage->getRequires());
20549 $package->setConflicts($curPackage->getConflicts());
20550 $package->setProvides($curPackage->getProvides());
20551 $package->setReplaces($curPackage->getReplaces());
20552 } elseif ($task === 'force-updates') {
20553 if (($curPackage->getSourceReference() && $curPackage->getSourceReference() !== $package->getSourceReference())
20554 || ($curPackage->getDistReference() && $curPackage->getDistReference() !== $package->getDistReference())
20555 ) {
20556 $operations[] = new UpdateOperation($package, $curPackage);
20557 }
20558 }
20559
20560 break;
20561 }
20562 }
20563
20564 continue;
20565 }
20566
20567
20568  $matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion()));
20569 foreach ($matches as $index => $match) {
20570
20571  if (!in_array($match->getRepository(), $repositories, true)) {
20572 unset($matches[$index]);
20573 continue;
20574 }
20575
20576
20577  if ($match->getName() !== $package->getName()) {
20578 unset($matches[$index]);
20579 continue;
20580 }
20581
20582 $matches[$index] = $match->getId();
20583 }
20584
20585
20586  if ($matches && $matches = $policy->selectPreferredPackages($pool, array(), $matches)) {
20587 $newPackage = $pool->literalToPackage($matches[0]);
20588
20589 if ($task === 'force-links' && $newPackage) {
20590 $package->setRequires($newPackage->getRequires());
20591 $package->setConflicts($newPackage->getConflicts());
20592 $package->setProvides($newPackage->getProvides());
20593 $package->setReplaces($newPackage->getReplaces());
20594 }
20595
20596 if ($task === 'force-updates' && $newPackage && (
20597 (($newPackage->getSourceReference() && $newPackage->getSourceReference() !== $package->getSourceReference())
20598 || ($newPackage->getDistReference() && $newPackage->getDistReference() !== $package->getDistReference())
20599 )
20600 )) {
20601 $operations[] = new UpdateOperation($package, $newPackage);
20602
20603 continue;
20604 }
20605 }
20606
20607 if ($task === 'force-updates') {
20608
20609  $references = $this->package->getReferences();
20610
20611 if (isset($references[$package->getName()]) && $references[$package->getName()] !== $package->getSourceReference()) {
20612
20613  $operations[] = new UpdateOperation($package, clone $package);
20614 }
20615 }
20616 } else {
20617
20618  foreach ($lockedRepository->findPackages($package->getName()) as $lockedPackage) {
20619 if ($lockedPackage->isDev() && $lockedPackage->getVersion() === $package->getVersion()) {
20620 if ($task === 'force-links') {
20621 $package->setRequires($lockedPackage->getRequires());
20622 $package->setConflicts($lockedPackage->getConflicts());
20623 $package->setProvides($lockedPackage->getProvides());
20624 $package->setReplaces($lockedPackage->getReplaces());
20625 } elseif ($task === 'force-updates') {
20626 if (($lockedPackage->getSourceReference() && $lockedPackage->getSourceReference() !== $package->getSourceReference())
20627 || ($lockedPackage->getDistReference() && $lockedPackage->getDistReference() !== $package->getDistReference())
20628 ) {
20629 $operations[] = new UpdateOperation($package, $lockedPackage);
20630 }
20631 }
20632
20633 break;
20634 }
20635 }
20636 }
20637 }
20638
20639 return $operations;
20640 }
20641
20642
20643
20644
20645
20646
20647 private function getCurrentPackages($installedRepo)
20648 {
20649 if ($this->locker->isLocked()) {
20650 try {
20651 return $this->locker->getLockedRepository(true)->getPackages();
20652 } catch (\RuntimeException $e) {
20653
20654  return $this->locker->getLockedRepository()->getPackages();
20655 }
20656 }
20657
20658 return $installedRepo->getPackages();
20659 }
20660
20661
20662
20663
20664 private function getRootAliases()
20665 {
20666 if ($this->update) {
20667 $aliases = $this->package->getAliases();
20668 } else {
20669 $aliases = $this->locker->getAliases();
20670 }
20671
20672 $normalizedAliases = array();
20673
20674 foreach ($aliases as $alias) {
20675 $normalizedAliases[$alias['package']][$alias['version']] = array(
20676 'alias' => $alias['alias'],
20677 'alias_normalized' => $alias['alias_normalized'],
20678 );
20679 }
20680
20681 return $normalizedAliases;
20682 }
20683
20684
20685
20686
20687
20688
20689
20690 private function processPackageUrls($pool, $policy, $localRepo, $repositories)
20691 {
20692 if (!$this->update) {
20693 return;
20694 }
20695
20696 $rootRefs = $this->package->getReferences();
20697
20698 foreach ($localRepo->getCanonicalPackages() as $package) {
20699
20700  $matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion()));
20701 foreach ($matches as $index => $match) {
20702
20703  if (!in_array($match->getRepository(), $repositories, true)) {
20704 unset($matches[$index]);
20705 continue;
20706 }
20707
20708
20709  if ($match->getName() !== $package->getName()) {
20710 unset($matches[$index]);
20711 continue;
20712 }
20713
20714 $matches[$index] = $match->getId();
20715 }
20716
20717
20718  if ($matches && $matches = $policy->selectPreferredPackages($pool, array(), $matches)) {
20719 $newPackage = $pool->literalToPackage($matches[0]);
20720
20721
20722  $sourceUrl = $package->getSourceUrl();
20723 $newSourceUrl = $newPackage->getSourceUrl();
20724 $newReference = $newPackage->getSourceReference();
20725
20726 if ($package->isDev() && isset($rootRefs[$package->getName()]) && $package->getSourceReference() === $rootRefs[$package->getName()]) {
20727 $newReference = $rootRefs[$package->getName()];
20728 }
20729
20730 $this->updatePackageUrl($package, $newSourceUrl, $newPackage->getSourceType(), $newReference, $newPackage->getDistUrl());
20731
20732 if ($package instanceof CompletePackage && $newPackage instanceof CompletePackage) {
20733 $package->setAbandoned($newPackage->getReplacementPackage() ?: $newPackage->isAbandoned());
20734 }
20735
20736 $package->setDistMirrors($newPackage->getDistMirrors());
20737 $package->setSourceMirrors($newPackage->getSourceMirrors());
20738 }
20739 }
20740 }
20741
20742 private function updatePackageUrl(PackageInterface $package, $sourceUrl, $sourceType, $sourceReference, $distUrl)
20743 {
20744 $oldSourceRef = $package->getSourceReference();
20745
20746 if ($package->getSourceUrl() !== $sourceUrl) {
20747 $package->setSourceType($sourceType);
20748 $package->setSourceUrl($sourceUrl);
20749 $package->setSourceReference($sourceReference);
20750 }
20751
20752
20753  
20754  if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com)/}i', $distUrl)) {
20755 $package->setDistUrl($distUrl);
20756 $this->updateInstallReferences($package, $sourceReference);
20757 }
20758
20759 if ($this->updateWhitelist && !$this->isUpdateable($package)) {
20760 $this->updateInstallReferences($package, $oldSourceRef);
20761 }
20762 }
20763
20764 private function updateInstallReferences(PackageInterface $package, $reference)
20765 {
20766 if (!$reference) {
20767 return;
20768 }
20769
20770 $package->setSourceReference($reference);
20771
20772 if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com)/}i', $package->getDistUrl())) {
20773 $package->setDistReference($reference);
20774 $package->setDistUrl(preg_replace('{(?<=/)[a-f0-9]{40}(?=/|$)}i', $reference, $package->getDistUrl()));
20775 } else if ($package->getDistReference()) { 
20776  $package->setDistReference($reference);
20777 }
20778 }
20779
20780
20781
20782
20783
20784 private function aliasPlatformPackages(PlatformRepository $platformRepo, $aliases)
20785 {
20786 foreach ($aliases as $package => $versions) {
20787 foreach ($versions as $version => $alias) {
20788 $packages = $platformRepo->findPackages($package, $version);
20789 foreach ($packages as $package) {
20790 $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
20791 $aliasPackage->setRootPackageAlias(true);
20792 $platformRepo->addPackage($aliasPackage);
20793 }
20794 }
20795 }
20796 }
20797
20798
20799
20800
20801
20802 private function isUpdateable(PackageInterface $package)
20803 {
20804 if (!$this->updateWhitelist) {
20805 throw new \LogicException('isUpdateable should only be called when a whitelist is present');
20806 }
20807
20808 foreach ($this->updateWhitelist as $whiteListedPattern => $void) {
20809 $patternRegexp = $this->packageNameToRegexp($whiteListedPattern);
20810 if (preg_match($patternRegexp, $package->getName())) {
20811 return true;
20812 }
20813 }
20814
20815 return false;
20816 }
20817
20818
20819
20820
20821
20822
20823
20824 private function packageNameToRegexp($whiteListedPattern)
20825 {
20826 $cleanedWhiteListedPattern = str_replace('\\*', '.*', preg_quote($whiteListedPattern));
20827
20828 return "{^" . $cleanedWhiteListedPattern . "$}i";
20829 }
20830
20831
20832
20833
20834
20835 private function extractPlatformRequirements($links)
20836 {
20837 $platformReqs = array();
20838 foreach ($links as $link) {
20839 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
20840 $platformReqs[$link->getTarget()] = $link->getPrettyConstraint();
20841 }
20842 }
20843
20844 return $platformReqs;
20845 }
20846
20847
20848
20849
20850
20851
20852
20853
20854
20855
20856
20857
20858
20859
20860 private function whitelistUpdateDependencies($localOrLockRepo, array $rootRequires, array $rootDevRequires)
20861 {
20862 if (!$this->updateWhitelist) {
20863 return;
20864 }
20865
20866 $rootRequires = array_merge($rootRequires, $rootDevRequires);
20867
20868 $requiredPackageNames = array();
20869 foreach ($rootRequires as $require) {
20870 $requiredPackageNames[] = $require->getTarget();
20871 }
20872
20873 $skipPackages = array();
20874 foreach ($rootRequires as $require) {
20875 $skipPackages[$require->getTarget()] = true;
20876 }
20877
20878 $pool = new Pool('dev');
20879 $pool->addRepository($localOrLockRepo);
20880
20881 $seen = array();
20882
20883 $rootRequiredPackageNames = array_keys($rootRequires);
20884
20885 foreach ($this->updateWhitelist as $packageName => $void) {
20886 $packageQueue = new \SplQueue;
20887
20888 $depPackages = $pool->whatProvides($packageName);
20889
20890 $nameMatchesRequiredPackage = in_array($packageName, $requiredPackageNames, true);
20891
20892
20893  if (!$nameMatchesRequiredPackage) {
20894 $whitelistPatternRegexp = $this->packageNameToRegexp($packageName);
20895 foreach ($rootRequiredPackageNames as $rootRequiredPackageName) {
20896 if (preg_match($whitelistPatternRegexp, $rootRequiredPackageName)) {
20897 $nameMatchesRequiredPackage = true;
20898 break;
20899 }
20900 }
20901 }
20902
20903 if (count($depPackages) == 0 && !$nameMatchesRequiredPackage && !in_array($packageName, array('nothing', 'lock', 'mirrors'))) {
20904 $this->io->writeError('<warning>Package "' . $packageName . '" listed for update is not installed. Ignoring.</warning>');
20905 }
20906
20907 foreach ($depPackages as $depPackage) {
20908 $packageQueue->enqueue($depPackage);
20909 }
20910
20911 while (!$packageQueue->isEmpty()) {
20912 $package = $packageQueue->dequeue();
20913 if (isset($seen[$package->getId()])) {
20914 continue;
20915 }
20916
20917 $seen[$package->getId()] = true;
20918 $this->updateWhitelist[$package->getName()] = true;
20919
20920 if (!$this->whitelistDependencies) {
20921 continue;
20922 }
20923
20924 $requires = $package->getRequires();
20925
20926 foreach ($requires as $require) {
20927 $requirePackages = $pool->whatProvides($require->getTarget());
20928
20929 foreach ($requirePackages as $requirePackage) {
20930 if (isset($this->updateWhitelist[$requirePackage->getName()])) {
20931 continue;
20932 }
20933
20934 if (isset($skipPackages[$requirePackage->getName()])) {
20935 $this->io->writeError('<warning>Dependency "' . $requirePackage->getName() . '" is also a root requirement, but is not explicitly whitelisted. Ignoring.</warning>');
20936 continue;
20937 }
20938
20939 $packageQueue->enqueue($requirePackage);
20940 }
20941 }
20942 }
20943 }
20944 }
20945
20946
20947
20948
20949
20950
20951
20952
20953 private function mockLocalRepositories(RepositoryManager $rm)
20954 {
20955 $packages = array();
20956 foreach ($rm->getLocalRepository()->getPackages() as $package) {
20957 $packages[(string) $package] = clone $package;
20958 }
20959 foreach ($packages as $key => $package) {
20960 if ($package instanceof AliasPackage) {
20961 $alias = (string) $package->getAliasOf();
20962 $packages[$key] = new AliasPackage($packages[$alias], $package->getVersion(), $package->getPrettyVersion());
20963 }
20964 }
20965 $rm->setLocalRepository(
20966 new InstalledArrayRepository($packages)
20967 );
20968 }
20969
20970
20971
20972
20973
20974
20975
20976
20977 public static function create(IOInterface $io, Composer $composer)
20978 {
20979 return new static(
20980 $io,
20981 $composer->getConfig(),
20982 $composer->getPackage(),
20983 $composer->getDownloadManager(),
20984 $composer->getRepositoryManager(),
20985 $composer->getLocker(),
20986 $composer->getInstallationManager(),
20987 $composer->getEventDispatcher(),
20988 $composer->getAutoloadGenerator()
20989 );
20990 }
20991
20992
20993
20994
20995
20996 public function setAdditionalInstalledRepository(RepositoryInterface $additionalInstalledRepository)
20997 {
20998 $this->additionalInstalledRepository = $additionalInstalledRepository;
20999
21000 return $this;
21001 }
21002
21003
21004
21005
21006
21007
21008
21009 public function setDryRun($dryRun = true)
21010 {
21011 $this->dryRun = (bool) $dryRun;
21012
21013 return $this;
21014 }
21015
21016
21017
21018
21019
21020
21021 public function isDryRun()
21022 {
21023 return $this->dryRun;
21024 }
21025
21026
21027
21028
21029
21030
21031
21032 public function setPreferSource($preferSource = true)
21033 {
21034 $this->preferSource = (bool) $preferSource;
21035
21036 return $this;
21037 }
21038
21039
21040
21041
21042
21043
21044
21045 public function setPreferDist($preferDist = true)
21046 {
21047 $this->preferDist = (bool) $preferDist;
21048
21049 return $this;
21050 }
21051
21052
21053
21054
21055
21056
21057
21058 public function setOptimizeAutoloader($optimizeAutoloader = false)
21059 {
21060 $this->optimizeAutoloader = (bool) $optimizeAutoloader;
21061 if (!$this->optimizeAutoloader) {
21062
21063  
21064  $this->setClassMapAuthoritative(false);
21065 }
21066
21067 return $this;
21068 }
21069
21070
21071
21072
21073
21074
21075
21076
21077 public function setClassMapAuthoritative($classMapAuthoritative = false)
21078 {
21079 $this->classMapAuthoritative = (bool) $classMapAuthoritative;
21080 if ($this->classMapAuthoritative) {
21081
21082  $this->setOptimizeAutoloader(true);
21083 }
21084
21085 return $this;
21086 }
21087
21088
21089
21090
21091
21092
21093
21094 public function setApcuAutoloader($apcuAutoloader = false)
21095 {
21096 $this->apcuAutoloader = (bool) $apcuAutoloader;
21097
21098 return $this;
21099 }
21100
21101
21102
21103
21104
21105
21106
21107 public function setUpdate($update = true)
21108 {
21109 $this->update = (bool) $update;
21110
21111 return $this;
21112 }
21113
21114
21115
21116
21117
21118
21119
21120 public function setDevMode($devMode = true)
21121 {
21122 $this->devMode = (bool) $devMode;
21123
21124 return $this;
21125 }
21126
21127
21128
21129
21130
21131
21132
21133
21134
21135 public function setDumpAutoloader($dumpAutoloader = true)
21136 {
21137 $this->dumpAutoloader = (bool) $dumpAutoloader;
21138
21139 return $this;
21140 }
21141
21142
21143
21144
21145
21146
21147
21148
21149
21150 public function setRunScripts($runScripts = true)
21151 {
21152 $this->runScripts = (bool) $runScripts;
21153
21154 return $this;
21155 }
21156
21157
21158
21159
21160
21161
21162
21163 public function setConfig(Config $config)
21164 {
21165 $this->config = $config;
21166
21167 return $this;
21168 }
21169
21170
21171
21172
21173
21174
21175
21176 public function setVerbose($verbose = true)
21177 {
21178 $this->verbose = (bool) $verbose;
21179
21180 return $this;
21181 }
21182
21183
21184
21185
21186
21187
21188 public function isVerbose()
21189 {
21190 return $this->verbose;
21191 }
21192
21193
21194
21195
21196
21197
21198
21199 public function setIgnorePlatformRequirements($ignorePlatformReqs = false)
21200 {
21201 $this->ignorePlatformReqs = (bool) $ignorePlatformReqs;
21202
21203 return $this;
21204 }
21205
21206
21207
21208
21209
21210
21211
21212
21213 public function setUpdateWhitelist(array $packages)
21214 {
21215 $this->updateWhitelist = array_flip(array_map('strtolower', $packages));
21216
21217 return $this;
21218 }
21219
21220
21221
21222
21223
21224
21225
21226 public function setWhitelistDependencies($updateDependencies = true)
21227 {
21228 $this->whitelistDependencies = (bool) $updateDependencies;
21229
21230 return $this;
21231 }
21232
21233
21234
21235
21236
21237
21238
21239 public function setPreferStable($preferStable = true)
21240 {
21241 $this->preferStable = (bool) $preferStable;
21242
21243 return $this;
21244 }
21245
21246
21247
21248
21249
21250
21251
21252 public function setPreferLowest($preferLowest = true)
21253 {
21254 $this->preferLowest = (bool) $preferLowest;
21255
21256 return $this;
21257 }
21258
21259
21260
21261
21262
21263
21264
21265
21266
21267 public function setWriteLock($writeLock = true)
21268 {
21269 $this->writeLock = (bool) $writeLock;
21270
21271 return $this;
21272 }
21273
21274
21275
21276
21277
21278
21279
21280
21281
21282 public function setExecuteOperations($executeOperations = true)
21283 {
21284 $this->executeOperations = (bool) $executeOperations;
21285
21286 return $this;
21287 }
21288
21289
21290
21291
21292
21293
21294
21295 public function setSkipSuggest($skipSuggest = true)
21296 {
21297 $this->skipSuggest = (bool) $skipSuggest;
21298
21299 return $this;
21300 }
21301
21302
21303
21304
21305
21306
21307
21308
21309
21310
21311 public function disablePlugins()
21312 {
21313 $this->installationManager->disablePlugins();
21314
21315 return $this;
21316 }
21317
21318
21319
21320
21321
21322 public function setSuggestedPackagesReporter(SuggestedPackagesReporter $suggestedPackagesReporter)
21323 {
21324 $this->suggestedPackagesReporter = $suggestedPackagesReporter;
21325
21326 return $this;
21327 }
21328 }
21329 <?php
21330
21331
21332
21333
21334
21335
21336
21337
21338
21339
21340
21341 namespace Composer\Installer;
21342
21343 use Composer\IO\IOInterface;
21344 use Composer\Package\PackageInterface;
21345 use Composer\Util\Filesystem;
21346 use Composer\Util\Platform;
21347 use Composer\Util\ProcessExecutor;
21348 use Composer\Util\Silencer;
21349
21350
21351
21352
21353
21354
21355
21356
21357 class BinaryInstaller
21358 {
21359 protected $binDir;
21360 protected $binCompat;
21361 protected $io;
21362 protected $filesystem;
21363
21364
21365
21366
21367
21368
21369
21370 public function __construct(IOInterface $io, $binDir, $binCompat, Filesystem $filesystem = null)
21371 {
21372 $this->binDir = $binDir;
21373 $this->binCompat = $binCompat;
21374 $this->io = $io;
21375 $this->filesystem = $filesystem ?: new Filesystem();
21376 }
21377
21378 public function installBinaries(PackageInterface $package, $installPath, $warnOnOverwrite = true)
21379 {
21380 $binaries = $this->getBinaries($package);
21381 if (!$binaries) {
21382 return;
21383 }
21384 foreach ($binaries as $bin) {
21385 $binPath = $installPath.'/'.$bin;
21386 if (!file_exists($binPath)) {
21387 $this->io->writeError('    <warning>Skipped installation of bin '.$bin.' for package '.$package->getName().': file not found in package</warning>');
21388 continue;
21389 }
21390
21391
21392  
21393  
21394  
21395  $binPath = realpath($binPath);
21396
21397 $this->initializeBinDir();
21398 $link = $this->binDir.'/'.basename($bin);
21399 if (file_exists($link)) {
21400 if (is_link($link)) {
21401
21402  
21403  
21404  Silencer::call('chmod', $link, 0777 & ~umask());
21405 }
21406 if ($warnOnOverwrite) {
21407 $this->io->writeError('    Skipped installation of bin '.$bin.' for package '.$package->getName().': name conflicts with an existing file');
21408 }
21409 continue;
21410 }
21411
21412 if ($this->binCompat === "auto") {
21413 if (Platform::isWindows()) {
21414 $this->installFullBinaries($binPath, $link, $bin, $package);
21415 } else {
21416 $this->installSymlinkBinaries($binPath, $link);
21417 }
21418 } elseif ($this->binCompat === "full") {
21419 $this->installFullBinaries($binPath, $link, $bin, $package);
21420 }
21421 Silencer::call('chmod', $link, 0777 & ~umask());
21422 }
21423 }
21424
21425 public function removeBinaries(PackageInterface $package)
21426 {
21427 $this->initializeBinDir();
21428
21429 $binaries = $this->getBinaries($package);
21430 if (!$binaries) {
21431 return;
21432 }
21433 foreach ($binaries as $bin) {
21434 $link = $this->binDir.'/'.basename($bin);
21435 if (is_link($link) || file_exists($link)) {
21436 $this->filesystem->unlink($link);
21437 }
21438 if (file_exists($link.'.bat')) {
21439 $this->filesystem->unlink($link.'.bat');
21440 }
21441 }
21442
21443
21444  if ((is_dir($this->binDir)) && ($this->filesystem->isDirEmpty($this->binDir))) {
21445 Silencer::call('rmdir', $this->binDir);
21446 }
21447 }
21448
21449 public static function determineBinaryCaller($bin)
21450 {
21451 if ('.bat' === substr($bin, -4) || '.exe' === substr($bin, -4)) {
21452 return 'call';
21453 }
21454
21455 $handle = fopen($bin, 'r');
21456 $line = fgets($handle);
21457 fclose($handle);
21458 if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) {
21459 return trim($match[1]);
21460 }
21461
21462 return 'php';
21463 }
21464
21465 protected function getBinaries(PackageInterface $package)
21466 {
21467 return $package->getBinaries();
21468 }
21469
21470 protected function installFullBinaries($binPath, $link, $bin, PackageInterface $package)
21471 {
21472
21473  if ('.bat' !== substr($binPath, -4)) {
21474 $this->installUnixyProxyBinaries($binPath, $link);
21475 @chmod($link, 0777 & ~umask());
21476 $link .= '.bat';
21477 if (file_exists($link)) {
21478 $this->io->writeError('    Skipped installation of bin '.$bin.'.bat proxy for package '.$package->getName().': a .bat proxy was already installed');
21479 }
21480 }
21481 if (!file_exists($link)) {
21482 file_put_contents($link, $this->generateWindowsProxyCode($binPath, $link));
21483 }
21484 }
21485
21486 protected function installSymlinkBinaries($binPath, $link)
21487 {
21488 if (!$this->filesystem->relativeSymlink($binPath, $link)) {
21489 $this->installUnixyProxyBinaries($binPath, $link);
21490 }
21491 }
21492
21493 protected function installUnixyProxyBinaries($binPath, $link)
21494 {
21495 file_put_contents($link, $this->generateUnixyProxyCode($binPath, $link));
21496 }
21497
21498 protected function initializeBinDir()
21499 {
21500 $this->filesystem->ensureDirectoryExists($this->binDir);
21501 $this->binDir = realpath($this->binDir);
21502 }
21503
21504 protected function generateWindowsProxyCode($bin, $link)
21505 {
21506 $binPath = $this->filesystem->findShortestPath($link, $bin);
21507 $caller = self::determineBinaryCaller($bin);
21508
21509 return "@ECHO OFF\r\n".
21510 "setlocal DISABLEDELAYEDEXPANSION\r\n".
21511 "SET BIN_TARGET=%~dp0/".trim(ProcessExecutor::escape($binPath), '"\'')."\r\n".
21512 "{$caller} \"%BIN_TARGET%\" %*\r\n";
21513 }
21514
21515 protected function generateUnixyProxyCode($bin, $link)
21516 {
21517 $binPath = $this->filesystem->findShortestPath($link, $bin);
21518
21519 $binDir = ProcessExecutor::escape(dirname($binPath));
21520 $binFile = basename($binPath);
21521
21522 $proxyCode = <<<PROXY
21523 #!/usr/bin/env sh
21524
21525 dir=$(d=\${0%[/\\\\]*}; cd "\$d" > /dev/null; cd $binDir && pwd)
21526
21527 # See if we are running in Cygwin by checking for cygpath program
21528 if command -v 'cygpath' >/dev/null 2>&1; then
21529         # Cygwin paths start with /cygdrive/ which will break windows PHP,
21530         # so we need to translate the dir path to windows format. However
21531         # we could be using cygwin PHP which does not require this, so we
21532         # test if the path to PHP starts with /cygdrive/ rather than /usr/bin
21533         if [[ $(which php) == /cygdrive/* ]]; then
21534                 dir=$(cygpath -m "\$dir");
21535         fi
21536 fi
21537
21538 dir=$(echo \$dir | sed 's/ /\ /g')
21539 "\${dir}/$binFile" "$@"
21540
21541 PROXY;
21542
21543 return $proxyCode;
21544 }
21545 }
21546 <?php
21547
21548
21549
21550
21551
21552
21553
21554
21555
21556
21557
21558 namespace Composer\Installer;
21559
21560 use Composer\Package\PackageInterface;
21561
21562
21563
21564
21565
21566
21567 interface BinaryPresenceInterface
21568 {
21569
21570
21571
21572
21573
21574 public function ensureBinariesPresence(PackageInterface $package);
21575 }
21576 <?php
21577
21578
21579
21580
21581
21582
21583
21584
21585
21586
21587
21588 namespace Composer\Installer;
21589
21590 use Composer\IO\IOInterface;
21591 use Composer\Package\PackageInterface;
21592 use Composer\Package\AliasPackage;
21593 use Composer\Repository\RepositoryInterface;
21594 use Composer\Repository\InstalledRepositoryInterface;
21595 use Composer\DependencyResolver\Operation\OperationInterface;
21596 use Composer\DependencyResolver\Operation\InstallOperation;
21597 use Composer\DependencyResolver\Operation\UpdateOperation;
21598 use Composer\DependencyResolver\Operation\UninstallOperation;
21599 use Composer\DependencyResolver\Operation\MarkAliasInstalledOperation;
21600 use Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation;
21601 use Composer\Util\StreamContextFactory;
21602
21603
21604
21605
21606
21607
21608
21609
21610 class InstallationManager
21611 {
21612 private $installers = array();
21613 private $cache = array();
21614 private $notifiablePackages = array();
21615
21616 public function reset()
21617 {
21618 $this->notifiablePackages = array();
21619 }
21620
21621
21622
21623
21624
21625
21626 public function addInstaller(InstallerInterface $installer)
21627 {
21628 array_unshift($this->installers, $installer);
21629 $this->cache = array();
21630 }
21631
21632
21633
21634
21635
21636
21637 public function removeInstaller(InstallerInterface $installer)
21638 {
21639 if (false !== ($key = array_search($installer, $this->installers, true))) {
21640 array_splice($this->installers, $key, 1);
21641 $this->cache = array();
21642 }
21643 }
21644
21645
21646
21647
21648
21649
21650
21651
21652 public function disablePlugins()
21653 {
21654 foreach ($this->installers as $i => $installer) {
21655 if (!$installer instanceof PluginInstaller) {
21656 continue;
21657 }
21658
21659 unset($this->installers[$i]);
21660 }
21661 }
21662
21663
21664
21665
21666
21667
21668
21669
21670
21671 public function getInstaller($type)
21672 {
21673 $type = strtolower($type);
21674
21675 if (isset($this->cache[$type])) {
21676 return $this->cache[$type];
21677 }
21678
21679 foreach ($this->installers as $installer) {
21680 if ($installer->supports($type)) {
21681 return $this->cache[$type] = $installer;
21682 }
21683 }
21684
21685 throw new \InvalidArgumentException('Unknown installer type: '.$type);
21686 }
21687
21688
21689
21690
21691
21692
21693
21694
21695
21696 public function isPackageInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
21697 {
21698 if ($package instanceof AliasPackage) {
21699 return $repo->hasPackage($package) && $this->isPackageInstalled($repo, $package->getAliasOf());
21700 }
21701
21702 return $this->getInstaller($package->getType())->isInstalled($repo, $package);
21703 }
21704
21705
21706
21707
21708
21709
21710
21711 public function ensureBinariesPresence(PackageInterface $package)
21712 {
21713 try {
21714 $installer = $this->getInstaller($package->getType());
21715 } catch (\InvalidArgumentException $e) {
21716
21717  return;
21718 }
21719
21720
21721  if ($installer instanceof BinaryPresenceInterface) {
21722 $installer->ensureBinariesPresence($package);
21723 }
21724 }
21725
21726
21727
21728
21729
21730
21731
21732 public function execute(RepositoryInterface $repo, OperationInterface $operation)
21733 {
21734 $method = $operation->getJobType();
21735 $this->$method($repo, $operation);
21736 }
21737
21738
21739
21740
21741
21742
21743
21744 public function install(RepositoryInterface $repo, InstallOperation $operation)
21745 {
21746 $package = $operation->getPackage();
21747 $installer = $this->getInstaller($package->getType());
21748 $installer->install($repo, $package);
21749 $this->markForNotification($package);
21750 }
21751
21752
21753
21754
21755
21756
21757
21758 public function update(RepositoryInterface $repo, UpdateOperation $operation)
21759 {
21760 $initial = $operation->getInitialPackage();
21761 $target = $operation->getTargetPackage();
21762
21763 $initialType = $initial->getType();
21764 $targetType = $target->getType();
21765
21766 if ($initialType === $targetType) {
21767 $installer = $this->getInstaller($initialType);
21768 $installer->update($repo, $initial, $target);
21769 $this->markForNotification($target);
21770 } else {
21771 $this->getInstaller($initialType)->uninstall($repo, $initial);
21772 $this->getInstaller($targetType)->install($repo, $target);
21773 }
21774 }
21775
21776
21777
21778
21779
21780
21781
21782 public function uninstall(RepositoryInterface $repo, UninstallOperation $operation)
21783 {
21784 $package = $operation->getPackage();
21785 $installer = $this->getInstaller($package->getType());
21786 $installer->uninstall($repo, $package);
21787 }
21788
21789
21790
21791
21792
21793
21794
21795 public function markAliasInstalled(RepositoryInterface $repo, MarkAliasInstalledOperation $operation)
21796 {
21797 $package = $operation->getPackage();
21798
21799 if (!$repo->hasPackage($package)) {
21800 $repo->addPackage(clone $package);
21801 }
21802 }
21803
21804
21805
21806
21807
21808
21809
21810 public function markAliasUninstalled(RepositoryInterface $repo, MarkAliasUninstalledOperation $operation)
21811 {
21812 $package = $operation->getPackage();
21813
21814 $repo->removePackage($package);
21815 }
21816
21817
21818
21819
21820
21821
21822
21823 public function getInstallPath(PackageInterface $package)
21824 {
21825 $installer = $this->getInstaller($package->getType());
21826
21827 return $installer->getInstallPath($package);
21828 }
21829
21830 public function notifyInstalls(IOInterface $io)
21831 {
21832 foreach ($this->notifiablePackages as $repoUrl => $packages) {
21833 $repositoryName = parse_url($repoUrl, PHP_URL_HOST);
21834 if ($io->hasAuthentication($repositoryName)) {
21835 $auth = $io->getAuthentication($repositoryName);
21836 $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
21837 $authHeader = 'Authorization: Basic '.$authStr;
21838 }
21839
21840
21841  if (strpos($repoUrl, '%package%')) {
21842 foreach ($packages as $package) {
21843 $url = str_replace('%package%', $package->getPrettyName(), $repoUrl);
21844
21845 $params = array(
21846 'version' => $package->getPrettyVersion(),
21847 'version_normalized' => $package->getVersion(),
21848 );
21849 $opts = array('http' =>
21850 array(
21851 'method' => 'POST',
21852 'header' => array('Content-type: application/x-www-form-urlencoded'),
21853 'content' => http_build_query($params, '', '&'),
21854 'timeout' => 3,
21855 ),
21856 );
21857 if (isset($authHeader)) {
21858 $opts['http']['header'][] = $authHeader;
21859 }
21860
21861 $context = StreamContextFactory::getContext($url, $opts);
21862 @file_get_contents($url, false, $context);
21863 }
21864
21865 continue;
21866 }
21867
21868 $postData = array('downloads' => array());
21869 foreach ($packages as $package) {
21870 $postData['downloads'][] = array(
21871 'name' => $package->getPrettyName(),
21872 'version' => $package->getVersion(),
21873 );
21874 }
21875
21876 $opts = array('http' =>
21877 array(
21878 'method' => 'POST',
21879 'header' => array('Content-Type: application/json'),
21880 'content' => json_encode($postData),
21881 'timeout' => 6,
21882 ),
21883 );
21884 if (isset($authHeader)) {
21885 $opts['http']['header'][] = $authHeader;
21886 }
21887
21888 $context = StreamContextFactory::getContext($repoUrl, $opts);
21889 @file_get_contents($repoUrl, false, $context);
21890 }
21891
21892 $this->reset();
21893 }
21894
21895 private function markForNotification(PackageInterface $package)
21896 {
21897 if ($package->getNotificationUrl()) {
21898 $this->notifiablePackages[$package->getNotificationUrl()][$package->getName()] = $package;
21899 }
21900 }
21901 }
21902 <?php
21903
21904
21905
21906
21907
21908
21909
21910
21911
21912
21913
21914 namespace Composer\Installer;
21915
21916 use Composer\Composer;
21917 use Composer\DependencyResolver\PolicyInterface;
21918 use Composer\DependencyResolver\Operation\OperationInterface;
21919 use Composer\DependencyResolver\Pool;
21920 use Composer\DependencyResolver\Request;
21921 use Composer\EventDispatcher\Event;
21922 use Composer\IO\IOInterface;
21923 use Composer\Repository\CompositeRepository;
21924
21925
21926
21927
21928
21929
21930 class InstallerEvent extends Event
21931 {
21932
21933
21934
21935 private $composer;
21936
21937
21938
21939
21940 private $io;
21941
21942
21943
21944
21945 private $devMode;
21946
21947
21948
21949
21950 private $policy;
21951
21952
21953
21954
21955 private $pool;
21956
21957
21958
21959
21960 private $installedRepo;
21961
21962
21963
21964
21965 private $request;
21966
21967
21968
21969
21970 private $operations;
21971
21972
21973
21974
21975
21976
21977
21978
21979
21980
21981
21982
21983
21984
21985 public function __construct($eventName, Composer $composer, IOInterface $io, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
21986 {
21987 parent::__construct($eventName);
21988
21989 $this->composer = $composer;
21990 $this->io = $io;
21991 $this->devMode = $devMode;
21992 $this->policy = $policy;
21993 $this->pool = $pool;
21994 $this->installedRepo = $installedRepo;
21995 $this->request = $request;
21996 $this->operations = $operations;
21997 }
21998
21999
22000
22001
22002 public function getComposer()
22003 {
22004 return $this->composer;
22005 }
22006
22007
22008
22009
22010 public function getIO()
22011 {
22012 return $this->io;
22013 }
22014
22015
22016
22017
22018 public function isDevMode()
22019 {
22020 return $this->devMode;
22021 }
22022
22023
22024
22025
22026 public function getPolicy()
22027 {
22028 return $this->policy;
22029 }
22030
22031
22032
22033
22034 public function getPool()
22035 {
22036 return $this->pool;
22037 }
22038
22039
22040
22041
22042 public function getInstalledRepo()
22043 {
22044 return $this->installedRepo;
22045 }
22046
22047
22048
22049
22050 public function getRequest()
22051 {
22052 return $this->request;
22053 }
22054
22055
22056
22057
22058 public function getOperations()
22059 {
22060 return $this->operations;
22061 }
22062 }
22063 <?php
22064
22065
22066
22067
22068
22069
22070
22071
22072
22073
22074
22075 namespace Composer\Installer;
22076
22077
22078
22079
22080
22081
22082 class InstallerEvents
22083 {
22084
22085
22086
22087
22088
22089
22090
22091
22092
22093 const PRE_DEPENDENCIES_SOLVING = 'pre-dependencies-solving';
22094
22095
22096
22097
22098
22099
22100
22101
22102
22103
22104 const POST_DEPENDENCIES_SOLVING = 'post-dependencies-solving';
22105 }
22106 <?php
22107
22108
22109
22110
22111
22112
22113
22114
22115
22116
22117
22118 namespace Composer\Installer;
22119
22120 use Composer\Package\PackageInterface;
22121 use Composer\Repository\InstalledRepositoryInterface;
22122 use InvalidArgumentException;
22123
22124
22125
22126
22127
22128
22129
22130 interface InstallerInterface
22131 {
22132
22133
22134
22135
22136
22137
22138 public function supports($packageType);
22139
22140
22141
22142
22143
22144
22145
22146
22147
22148 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package);
22149
22150
22151
22152
22153
22154
22155
22156 public function install(InstalledRepositoryInterface $repo, PackageInterface $package);
22157
22158
22159
22160
22161
22162
22163
22164
22165
22166
22167 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target);
22168
22169
22170
22171
22172
22173
22174
22175 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package);
22176
22177
22178
22179
22180
22181
22182
22183 public function getInstallPath(PackageInterface $package);
22184 }
22185 <?php
22186
22187
22188
22189
22190
22191
22192
22193
22194
22195
22196
22197 namespace Composer\Installer;
22198
22199 use Composer\Composer;
22200 use Composer\IO\IOInterface;
22201 use Composer\Repository\InstalledRepositoryInterface;
22202 use Composer\Package\PackageInterface;
22203 use Composer\Util\Filesystem;
22204 use Composer\Util\Silencer;
22205
22206
22207
22208
22209
22210
22211
22212 class LibraryInstaller implements InstallerInterface, BinaryPresenceInterface
22213 {
22214 protected $composer;
22215 protected $vendorDir;
22216 protected $binDir;
22217 protected $downloadManager;
22218 protected $io;
22219 protected $type;
22220 protected $filesystem;
22221 protected $binCompat;
22222 protected $binaryInstaller;
22223
22224
22225
22226
22227
22228
22229
22230
22231
22232
22233 public function __construct(IOInterface $io, Composer $composer, $type = 'library', Filesystem $filesystem = null, BinaryInstaller $binaryInstaller = null)
22234 {
22235 $this->composer = $composer;
22236 $this->downloadManager = $composer->getDownloadManager();
22237 $this->io = $io;
22238 $this->type = $type;
22239
22240 $this->filesystem = $filesystem ?: new Filesystem();
22241 $this->vendorDir = rtrim($composer->getConfig()->get('vendor-dir'), '/');
22242 $this->binaryInstaller = $binaryInstaller ?: new BinaryInstaller($this->io, rtrim($composer->getConfig()->get('bin-dir'), '/'), $composer->getConfig()->get('bin-compat'), $this->filesystem);
22243 }
22244
22245
22246
22247
22248 public function supports($packageType)
22249 {
22250 return $packageType === $this->type || null === $this->type;
22251 }
22252
22253
22254
22255
22256 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
22257 {
22258 return $repo->hasPackage($package) && is_readable($this->getInstallPath($package));
22259 }
22260
22261
22262
22263
22264 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
22265 {
22266 $this->initializeVendorDir();
22267 $downloadPath = $this->getInstallPath($package);
22268
22269
22270  if (!is_readable($downloadPath) && $repo->hasPackage($package)) {
22271 $this->binaryInstaller->removeBinaries($package);
22272 }
22273
22274 $this->installCode($package);
22275 $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package));
22276 if (!$repo->hasPackage($package)) {
22277 $repo->addPackage(clone $package);
22278 }
22279 }
22280
22281
22282
22283
22284 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
22285 {
22286 if (!$repo->hasPackage($initial)) {
22287 throw new \InvalidArgumentException('Package is not installed: '.$initial);
22288 }
22289
22290 $this->initializeVendorDir();
22291
22292 $this->binaryInstaller->removeBinaries($initial);
22293 $this->updateCode($initial, $target);
22294 $this->binaryInstaller->installBinaries($target, $this->getInstallPath($target));
22295 $repo->removePackage($initial);
22296 if (!$repo->hasPackage($target)) {
22297 $repo->addPackage(clone $target);
22298 }
22299 }
22300
22301
22302
22303
22304 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
22305 {
22306 if (!$repo->hasPackage($package)) {
22307 throw new \InvalidArgumentException('Package is not installed: '.$package);
22308 }
22309
22310 $this->removeCode($package);
22311 $this->binaryInstaller->removeBinaries($package);
22312 $repo->removePackage($package);
22313
22314 $downloadPath = $this->getPackageBasePath($package);
22315 if (strpos($package->getName(), '/')) {
22316 $packageVendorDir = dirname($downloadPath);
22317 if (is_dir($packageVendorDir) && $this->filesystem->isDirEmpty($packageVendorDir)) {
22318 Silencer::call('rmdir', $packageVendorDir);
22319 }
22320 }
22321 }
22322
22323
22324
22325
22326 public function getInstallPath(PackageInterface $package)
22327 {
22328 $this->initializeVendorDir();
22329
22330 $basePath = ($this->vendorDir ? $this->vendorDir.'/' : '') . $package->getPrettyName();
22331 $targetDir = $package->getTargetDir();
22332
22333 return $basePath . ($targetDir ? '/'.$targetDir : '');
22334 }
22335
22336
22337
22338
22339
22340
22341 public function ensureBinariesPresence(PackageInterface $package)
22342 {
22343 $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package), false);
22344 }
22345
22346
22347
22348
22349
22350
22351
22352
22353
22354
22355 protected function getPackageBasePath(PackageInterface $package)
22356 {
22357 $installPath = $this->getInstallPath($package);
22358 $targetDir = $package->getTargetDir();
22359
22360 if ($targetDir) {
22361 return preg_replace('{/*'.str_replace('/', '/+', preg_quote($targetDir)).'/?$}', '', $installPath);
22362 }
22363
22364 return $installPath;
22365 }
22366
22367 protected function installCode(PackageInterface $package)
22368 {
22369 $downloadPath = $this->getInstallPath($package);
22370 $this->downloadManager->download($package, $downloadPath);
22371 }
22372
22373 protected function updateCode(PackageInterface $initial, PackageInterface $target)
22374 {
22375 $initialDownloadPath = $this->getInstallPath($initial);
22376 $targetDownloadPath = $this->getInstallPath($target);
22377 if ($targetDownloadPath !== $initialDownloadPath) {
22378
22379  
22380  if (substr($initialDownloadPath, 0, strlen($targetDownloadPath)) === $targetDownloadPath
22381 || substr($targetDownloadPath, 0, strlen($initialDownloadPath)) === $initialDownloadPath
22382 ) {
22383 $this->removeCode($initial);
22384 $this->installCode($target);
22385
22386 return;
22387 }
22388
22389 $this->filesystem->rename($initialDownloadPath, $targetDownloadPath);
22390 }
22391 $this->downloadManager->update($initial, $target, $targetDownloadPath);
22392 }
22393
22394 protected function removeCode(PackageInterface $package)
22395 {
22396 $downloadPath = $this->getPackageBasePath($package);
22397 $this->downloadManager->remove($package, $downloadPath);
22398 }
22399
22400 protected function initializeVendorDir()
22401 {
22402 $this->filesystem->ensureDirectoryExists($this->vendorDir);
22403 $this->vendorDir = realpath($this->vendorDir);
22404 }
22405 }
22406 <?php
22407
22408
22409
22410
22411
22412
22413
22414
22415
22416
22417
22418 namespace Composer\Installer;
22419
22420 use Composer\Repository\InstalledRepositoryInterface;
22421 use Composer\Package\PackageInterface;
22422
22423
22424
22425
22426
22427
22428 class MetapackageInstaller implements InstallerInterface
22429 {
22430
22431
22432
22433 public function supports($packageType)
22434 {
22435 return $packageType === 'metapackage';
22436 }
22437
22438
22439
22440
22441 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
22442 {
22443 return $repo->hasPackage($package);
22444 }
22445
22446
22447
22448
22449 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
22450 {
22451 $repo->addPackage(clone $package);
22452 }
22453
22454
22455
22456
22457 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
22458 {
22459 if (!$repo->hasPackage($initial)) {
22460 throw new \InvalidArgumentException('Package is not installed: '.$initial);
22461 }
22462
22463 $repo->removePackage($initial);
22464 $repo->addPackage(clone $target);
22465 }
22466
22467
22468
22469
22470 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
22471 {
22472 if (!$repo->hasPackage($package)) {
22473 throw new \InvalidArgumentException('Package is not installed: '.$package);
22474 }
22475
22476 $repo->removePackage($package);
22477 }
22478
22479
22480
22481
22482 public function getInstallPath(PackageInterface $package)
22483 {
22484 return '';
22485 }
22486 }
22487 <?php
22488
22489
22490
22491
22492
22493
22494
22495
22496
22497
22498
22499 namespace Composer\Installer;
22500
22501 use Composer\Repository\InstalledRepositoryInterface;
22502 use Composer\Package\PackageInterface;
22503
22504
22505
22506
22507
22508
22509
22510
22511 class NoopInstaller implements InstallerInterface
22512 {
22513
22514
22515
22516 public function supports($packageType)
22517 {
22518 return true;
22519 }
22520
22521
22522
22523
22524 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
22525 {
22526 return $repo->hasPackage($package);
22527 }
22528
22529
22530
22531
22532 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
22533 {
22534 if (!$repo->hasPackage($package)) {
22535 $repo->addPackage(clone $package);
22536 }
22537 }
22538
22539
22540
22541
22542 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
22543 {
22544 if (!$repo->hasPackage($initial)) {
22545 throw new \InvalidArgumentException('Package is not installed: '.$initial);
22546 }
22547
22548 $repo->removePackage($initial);
22549 if (!$repo->hasPackage($target)) {
22550 $repo->addPackage(clone $target);
22551 }
22552 }
22553
22554
22555
22556
22557 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
22558 {
22559 if (!$repo->hasPackage($package)) {
22560 throw new \InvalidArgumentException('Package is not installed: '.$package);
22561 }
22562 $repo->removePackage($package);
22563 }
22564
22565
22566
22567
22568 public function getInstallPath(PackageInterface $package)
22569 {
22570 $targetDir = $package->getTargetDir();
22571
22572 return $package->getPrettyName() . ($targetDir ? '/'.$targetDir : '');
22573 }
22574 }
22575 <?php
22576
22577
22578
22579
22580
22581
22582
22583
22584
22585
22586
22587 namespace Composer\Installer;
22588
22589 use Composer\Composer;
22590 use Composer\IO\IOInterface;
22591 use Composer\DependencyResolver\Operation\OperationInterface;
22592 use Composer\DependencyResolver\PolicyInterface;
22593 use Composer\DependencyResolver\Pool;
22594 use Composer\DependencyResolver\Request;
22595 use Composer\Repository\CompositeRepository;
22596
22597
22598
22599
22600
22601
22602 class PackageEvent extends InstallerEvent
22603 {
22604
22605
22606
22607 private $operation;
22608
22609
22610
22611
22612
22613
22614
22615
22616
22617
22618
22619
22620
22621
22622
22623 public function __construct($eventName, Composer $composer, IOInterface $io, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
22624 {
22625 parent::__construct($eventName, $composer, $io, $devMode, $policy, $pool, $installedRepo, $request, $operations);
22626
22627 $this->operation = $operation;
22628 }
22629
22630
22631
22632
22633
22634
22635 public function getOperation()
22636 {
22637 return $this->operation;
22638 }
22639 }
22640 <?php
22641
22642
22643
22644
22645
22646
22647
22648
22649
22650
22651
22652 namespace Composer\Installer;
22653
22654
22655
22656
22657
22658
22659 class PackageEvents
22660 {
22661
22662
22663
22664
22665
22666
22667
22668 const PRE_PACKAGE_INSTALL = 'pre-package-install';
22669
22670
22671
22672
22673
22674
22675
22676
22677 const POST_PACKAGE_INSTALL = 'post-package-install';
22678
22679
22680
22681
22682
22683
22684
22685
22686 const PRE_PACKAGE_UPDATE = 'pre-package-update';
22687
22688
22689
22690
22691
22692
22693
22694
22695 const POST_PACKAGE_UPDATE = 'post-package-update';
22696
22697
22698
22699
22700
22701
22702
22703
22704 const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
22705
22706
22707
22708
22709
22710
22711
22712
22713 const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
22714 }
22715 <?php
22716
22717
22718
22719
22720
22721
22722
22723
22724
22725
22726
22727 namespace Composer\Installer;
22728
22729 use Composer\IO\IOInterface;
22730 use Composer\Package\PackageInterface;
22731 use Composer\Util\Filesystem;
22732 use Composer\Util\ProcessExecutor;
22733
22734
22735
22736
22737
22738
22739 class PearBinaryInstaller extends BinaryInstaller
22740 {
22741 private $installer;
22742 private $vendorDir;
22743
22744
22745
22746
22747
22748
22749
22750
22751
22752 public function __construct(IOInterface $io, $binDir, $vendorDir, $binCompat, Filesystem $filesystem, PearInstaller $installer)
22753 {
22754 parent::__construct($io, $binDir, $binCompat, $filesystem);
22755 $this->installer = $installer;
22756 $this->vendorDir = $vendorDir;
22757 }
22758
22759 protected function getBinaries(PackageInterface $package)
22760 {
22761 $binariesPath = $this->installer->getInstallPath($package) . '/bin/';
22762 $binaries = array();
22763 if (file_exists($binariesPath)) {
22764 foreach (new \FilesystemIterator($binariesPath, \FilesystemIterator::KEY_AS_FILENAME | \FilesystemIterator::CURRENT_AS_FILEINFO) as $fileName => $value) {
22765 if (!$value->isDir()) {
22766 $binaries[] = 'bin/'.$fileName;
22767 }
22768 }
22769 }
22770
22771 return $binaries;
22772 }
22773
22774 protected function initializeBinDir()
22775 {
22776 parent::initializeBinDir();
22777 file_put_contents($this->binDir.'/composer-php', $this->generateUnixyPhpProxyCode());
22778 @chmod($this->binDir.'/composer-php', 0777);
22779 file_put_contents($this->binDir.'/composer-php.bat', $this->generateWindowsPhpProxyCode());
22780 @chmod($this->binDir.'/composer-php.bat', 0777);
22781 }
22782
22783 protected function generateWindowsProxyCode($bin, $link)
22784 {
22785 $binPath = $this->filesystem->findShortestPath($link, $bin);
22786 if ('.bat' === substr($bin, -4)) {
22787 $caller = 'call';
22788 } else {
22789 $handle = fopen($bin, 'r');
22790 $line = fgets($handle);
22791 fclose($handle);
22792 if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) {
22793 $caller = trim($match[1]);
22794 } else {
22795 $caller = 'php';
22796 }
22797
22798 if ($caller === 'php') {
22799 return "@echo off\r\n".
22800 "pushd .\r\n".
22801 "cd %~dp0\r\n".
22802 "set PHP_PROXY=%CD%\\composer-php.bat\r\n".
22803 "cd ".ProcessExecutor::escape(dirname($binPath))."\r\n".
22804 "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n".
22805 "popd\r\n".
22806 "%PHP_PROXY% \"%BIN_TARGET%\" %*\r\n";
22807 }
22808 }
22809
22810 return "@echo off\r\n".
22811 "pushd .\r\n".
22812 "cd %~dp0\r\n".
22813 "cd ".ProcessExecutor::escape(dirname($binPath))."\r\n".
22814 "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n".
22815 "popd\r\n".
22816 $caller." \"%BIN_TARGET%\" %*\r\n";
22817 }
22818
22819 private function generateWindowsPhpProxyCode()
22820 {
22821 $binToVendor = $this->filesystem->findShortestPath($this->binDir, $this->vendorDir, true);
22822
22823 return
22824 "@echo off\r\n" .
22825 "setlocal enabledelayedexpansion\r\n" .
22826 "set BIN_DIR=%~dp0\r\n" .
22827 "set VENDOR_DIR=%BIN_DIR%\\".$binToVendor."\r\n" .
22828 "set DIRS=.\r\n" .
22829 "FOR /D %%V IN (%VENDOR_DIR%\\*) DO (\r\n" .
22830 "    FOR /D %%P IN (%%V\\*) DO (\r\n" .
22831 "        set DIRS=!DIRS!;%%~fP\r\n" .
22832 "    )\r\n" .
22833 ")\r\n" .
22834 "php.exe -d include_path=!DIRS! %*\r\n";
22835 }
22836
22837 private function generateUnixyPhpProxyCode()
22838 {
22839 $binToVendor = $this->filesystem->findShortestPath($this->binDir, $this->vendorDir, true);
22840
22841 return
22842 "#!/usr/bin/env sh\n".
22843 "SRC_DIR=`pwd`\n".
22844 "BIN_DIR=`dirname $0`\n".
22845 "VENDOR_DIR=\$BIN_DIR/".escapeshellarg($binToVendor)."\n".
22846 "DIRS=\"\"\n".
22847 "for vendor in \$VENDOR_DIR/*; do\n".
22848 "    if [ -d \"\$vendor\" ]; then\n".
22849 "        for package in \$vendor/*; do\n".
22850 "            if [ -d \"\$package\" ]; then\n".
22851 "                DIRS=\"\${DIRS}:\${package}\"\n".
22852 "            fi\n".
22853 "        done\n".
22854 "    fi\n".
22855 "done\n".
22856 "php -d include_path=\".\$DIRS\" $@\n";
22857 }
22858 }
22859 <?php
22860
22861
22862
22863
22864
22865
22866
22867
22868
22869
22870
22871 namespace Composer\Installer;
22872
22873 use Composer\IO\IOInterface;
22874 use Composer\Composer;
22875 use Composer\Downloader\PearPackageExtractor;
22876 use Composer\Repository\InstalledRepositoryInterface;
22877 use Composer\Package\PackageInterface;
22878 use Composer\Util\Platform;
22879 use Composer\Util\Filesystem;
22880
22881
22882
22883
22884
22885
22886
22887 class PearInstaller extends LibraryInstaller
22888 {
22889
22890
22891
22892
22893
22894
22895
22896 public function __construct(IOInterface $io, Composer $composer, $type = 'pear-library')
22897 {
22898 $filesystem = new Filesystem();
22899 $binaryInstaller = new PearBinaryInstaller($io, rtrim($composer->getConfig()->get('bin-dir'), '/'), rtrim($composer->getConfig()->get('vendor-dir'), '/'), $composer->getConfig()->get('bin-compat'), $filesystem, $this);
22900
22901 parent::__construct($io, $composer, $type, $filesystem, $binaryInstaller);
22902 }
22903
22904
22905
22906
22907 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
22908 {
22909 $this->uninstall($repo, $initial);
22910 $this->install($repo, $target);
22911 }
22912
22913 protected function installCode(PackageInterface $package)
22914 {
22915 parent::installCode($package);
22916
22917 $isWindows = Platform::isWindows();
22918 $php_bin = $this->binDir . ($isWindows ? '/composer-php.bat' : '/composer-php');
22919
22920 if (!$isWindows) {
22921 $php_bin = '/usr/bin/env ' . $php_bin;
22922 }
22923
22924 $installPath = $this->getInstallPath($package);
22925 $vars = array(
22926 'os' => $isWindows ? 'windows' : 'linux',
22927 'php_bin' => $php_bin,
22928 'pear_php' => $installPath,
22929 'php_dir' => $installPath,
22930 'bin_dir' => $installPath . '/bin',
22931 'data_dir' => $installPath . '/data',
22932 'version' => $package->getPrettyVersion(),
22933 );
22934
22935 $packageArchive = $this->getInstallPath($package).'/'.pathinfo($package->getDistUrl(), PATHINFO_BASENAME);
22936 $pearExtractor = new PearPackageExtractor($packageArchive);
22937 $pearExtractor->extractTo($this->getInstallPath($package), array('php' => '/', 'script' => '/bin', 'data' => '/data'), $vars);
22938
22939 $this->io->writeError('    Cleaning up', true, IOInterface::VERBOSE);
22940 $this->filesystem->unlink($packageArchive);
22941 }
22942 }
22943 <?php
22944
22945
22946
22947
22948
22949
22950
22951
22952
22953
22954
22955 namespace Composer\Installer;
22956
22957 use Composer\Composer;
22958 use Composer\IO\IOInterface;
22959 use Composer\Repository\InstalledRepositoryInterface;
22960 use Composer\Package\PackageInterface;
22961
22962
22963
22964
22965
22966
22967
22968 class PluginInstaller extends LibraryInstaller
22969 {
22970 private $installationManager;
22971
22972
22973
22974
22975
22976
22977
22978
22979 public function __construct(IOInterface $io, Composer $composer, $type = 'library')
22980 {
22981 parent::__construct($io, $composer, 'composer-plugin');
22982 $this->installationManager = $composer->getInstallationManager();
22983 }
22984
22985
22986
22987
22988 public function supports($packageType)
22989 {
22990 return $packageType === 'composer-plugin' || $packageType === 'composer-installer';
22991 }
22992
22993
22994
22995
22996 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
22997 {
22998 $extra = $package->getExtra();
22999 if (empty($extra['class'])) {
23000 throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
23001 }
23002
23003 parent::install($repo, $package);
23004 try {
23005 $this->composer->getPluginManager()->registerPackage($package, true);
23006 } catch (\Exception $e) {
23007
23008  $this->io->writeError('Plugin installation failed, rolling back');
23009 parent::uninstall($repo, $package);
23010 throw $e;
23011 }
23012 }
23013
23014
23015
23016
23017 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23018 {
23019 $extra = $target->getExtra();
23020 if (empty($extra['class'])) {
23021 throw new \UnexpectedValueException('Error while installing '.$target->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
23022 }
23023
23024 parent::update($repo, $initial, $target);
23025 $this->composer->getPluginManager()->registerPackage($target, true);
23026 }
23027 }
23028 <?php
23029
23030
23031
23032
23033
23034
23035
23036
23037
23038
23039
23040 namespace Composer\Installer;
23041
23042 use Composer\Package\PackageInterface;
23043 use Composer\Downloader\DownloadManager;
23044 use Composer\Repository\InstalledRepositoryInterface;
23045 use Composer\Util\Filesystem;
23046
23047
23048
23049
23050
23051
23052
23053 class ProjectInstaller implements InstallerInterface
23054 {
23055 private $installPath;
23056 private $downloadManager;
23057 private $filesystem;
23058
23059 public function __construct($installPath, DownloadManager $dm)
23060 {
23061 $this->installPath = rtrim(strtr($installPath, '\\', '/'), '/').'/';
23062 $this->downloadManager = $dm;
23063 $this->filesystem = new Filesystem;
23064 }
23065
23066
23067
23068
23069
23070
23071
23072 public function supports($packageType)
23073 {
23074 return true;
23075 }
23076
23077
23078
23079
23080 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
23081 {
23082 return false;
23083 }
23084
23085
23086
23087
23088 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
23089 {
23090 $installPath = $this->installPath;
23091 if (file_exists($installPath) && !$this->filesystem->isDirEmpty($installPath)) {
23092 throw new \InvalidArgumentException("Project directory $installPath is not empty.");
23093 }
23094 if (!is_dir($installPath)) {
23095 mkdir($installPath, 0777, true);
23096 }
23097 $this->downloadManager->download($package, $installPath);
23098 }
23099
23100
23101
23102
23103 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23104 {
23105 throw new \InvalidArgumentException("not supported");
23106 }
23107
23108
23109
23110
23111 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
23112 {
23113 throw new \InvalidArgumentException("not supported");
23114 }
23115
23116
23117
23118
23119
23120
23121
23122 public function getInstallPath(PackageInterface $package)
23123 {
23124 return $this->installPath;
23125 }
23126 }
23127 <?php
23128
23129
23130
23131
23132
23133
23134
23135
23136
23137
23138
23139 namespace Composer\Installer;
23140
23141 use Composer\IO\IOInterface;
23142 use Composer\Package\PackageInterface;
23143 use Composer\Repository\RepositoryInterface;
23144 use Symfony\Component\Console\Formatter\OutputFormatter;
23145
23146
23147
23148
23149
23150
23151 class SuggestedPackagesReporter
23152 {
23153
23154
23155
23156 protected $suggestedPackages = array();
23157
23158
23159
23160
23161 private $io;
23162
23163 public function __construct(IOInterface $io)
23164 {
23165 $this->io = $io;
23166 }
23167
23168
23169
23170
23171 public function getPackages()
23172 {
23173 return $this->suggestedPackages;
23174 }
23175
23176
23177
23178
23179
23180
23181
23182
23183
23184
23185
23186
23187 public function addPackage($source, $target, $reason)
23188 {
23189 $this->suggestedPackages[] = array(
23190 'source' => $source,
23191 'target' => $target,
23192 'reason' => $reason,
23193 );
23194
23195 return $this;
23196 }
23197
23198
23199
23200
23201
23202
23203
23204 public function addSuggestionsFromPackage(PackageInterface $package)
23205 {
23206 $source = $package->getPrettyName();
23207 foreach ($package->getSuggests() as $target => $reason) {
23208 $this->addPackage(
23209 $source,
23210 $target,
23211 $reason
23212 );
23213 }
23214
23215 return $this;
23216 }
23217
23218
23219
23220
23221
23222
23223
23224
23225 public function output(RepositoryInterface $installedRepo = null)
23226 {
23227 $suggestedPackages = $this->getPackages();
23228 $installedPackages = array();
23229 if (null !== $installedRepo && ! empty($suggestedPackages)) {
23230 foreach ($installedRepo->getPackages() as $package) {
23231 $installedPackages = array_merge(
23232 $installedPackages,
23233 $package->getNames()
23234 );
23235 }
23236 }
23237
23238 foreach ($suggestedPackages as $suggestion) {
23239 if (in_array($suggestion['target'], $installedPackages)) {
23240 continue;
23241 }
23242
23243 $this->io->writeError(sprintf(
23244 '%s suggests installing %s (%s)',
23245 $suggestion['source'],
23246 $this->escapeOutput($suggestion['target']),
23247 $this->escapeOutput($suggestion['reason'])
23248 ));
23249 }
23250
23251 return $this;
23252 }
23253
23254
23255
23256
23257
23258 private function escapeOutput($string)
23259 {
23260 return OutputFormatter::escape(
23261 $this->removeControlCharacters($string)
23262 );
23263 }
23264
23265
23266
23267
23268
23269 private function removeControlCharacters($string)
23270 {
23271 return preg_replace(
23272 '/[[:cntrl:]]/',
23273 '',
23274 str_replace("\n", ' ', $string)
23275 );
23276 }
23277 }
23278 <?php
23279
23280
23281
23282
23283
23284
23285
23286
23287
23288
23289
23290 namespace Composer\Json;
23291
23292 use JsonSchema\Validator;
23293 use Seld\JsonLint\JsonParser;
23294 use Seld\JsonLint\ParsingException;
23295 use Composer\Util\RemoteFilesystem;
23296 use Composer\IO\IOInterface;
23297 use Composer\Downloader\TransportException;
23298
23299
23300
23301
23302
23303
23304
23305 class JsonFile
23306 {
23307 const LAX_SCHEMA = 1;
23308 const STRICT_SCHEMA = 2;
23309
23310 const JSON_UNESCAPED_SLASHES = 64;
23311 const JSON_PRETTY_PRINT = 128;
23312 const JSON_UNESCAPED_UNICODE = 256;
23313
23314 private $path;
23315 private $rfs;
23316 private $io;
23317
23318
23319
23320
23321
23322
23323
23324
23325
23326 public function __construct($path, RemoteFilesystem $rfs = null, IOInterface $io = null)
23327 {
23328 $this->path = $path;
23329
23330 if (null === $rfs && preg_match('{^https?://}i', $path)) {
23331 throw new \InvalidArgumentException('http urls require a RemoteFilesystem instance to be passed');
23332 }
23333 $this->rfs = $rfs;
23334 $this->io = $io;
23335 }
23336
23337
23338
23339
23340 public function getPath()
23341 {
23342 return $this->path;
23343 }
23344
23345
23346
23347
23348
23349
23350 public function exists()
23351 {
23352 return is_file($this->path);
23353 }
23354
23355
23356
23357
23358
23359
23360
23361 public function read()
23362 {
23363 try {
23364 if ($this->rfs) {
23365 $json = $this->rfs->getContents($this->path, $this->path, false);
23366 } else {
23367 if ($this->io && $this->io->isDebug()) {
23368 $this->io->writeError('Reading ' . $this->path);
23369 }
23370 $json = file_get_contents($this->path);
23371 }
23372 } catch (TransportException $e) {
23373 throw new \RuntimeException($e->getMessage(), 0, $e);
23374 } catch (\Exception $e) {
23375 throw new \RuntimeException('Could not read '.$this->path."\n\n".$e->getMessage());
23376 }
23377
23378 return static::parseJson($json, $this->path);
23379 }
23380
23381
23382
23383
23384
23385
23386
23387
23388 public function write(array $hash, $options = 448)
23389 {
23390 $dir = dirname($this->path);
23391 if (!is_dir($dir)) {
23392 if (file_exists($dir)) {
23393 throw new \UnexpectedValueException(
23394 $dir.' exists and is not a directory.'
23395 );
23396 }
23397 if (!@mkdir($dir, 0777, true)) {
23398 throw new \UnexpectedValueException(
23399 $dir.' does not exist and could not be created.'
23400 );
23401 }
23402 }
23403
23404 $retries = 3;
23405 while ($retries--) {
23406 try {
23407 file_put_contents($this->path, static::encode($hash, $options). ($options & self::JSON_PRETTY_PRINT ? "\n" : ''));
23408 break;
23409 } catch (\Exception $e) {
23410 if ($retries) {
23411 usleep(500000);
23412 continue;
23413 }
23414
23415 throw $e;
23416 }
23417 }
23418 }
23419
23420
23421
23422
23423
23424
23425
23426
23427 public function validateSchema($schema = self::STRICT_SCHEMA)
23428 {
23429 $content = file_get_contents($this->path);
23430 $data = json_decode($content);
23431
23432 if (null === $data && 'null' !== $content) {
23433 self::validateSyntax($content, $this->path);
23434 }
23435
23436 $schemaFile = __DIR__ . '/../../../res/composer-schema.json';
23437
23438
23439  if (false === strpos($schemaFile, '://')) {
23440 $schemaFile = 'file://' . $schemaFile;
23441 }
23442
23443 $schemaData = (object) array('$ref' => $schemaFile);
23444
23445 if ($schema === self::LAX_SCHEMA) {
23446 $schemaData->additionalProperties = true;
23447 $schemaData->required = array();
23448 }
23449
23450 $validator = new Validator();
23451 $validator->check($data, $schemaData);
23452
23453
23454
23455 if (!$validator->isValid()) {
23456 $errors = array();
23457 foreach ((array) $validator->getErrors() as $error) {
23458 $errors[] = ($error['property'] ? $error['property'].' : ' : '').$error['message'];
23459 }
23460 throw new JsonValidationException('"'.$this->path.'" does not match the expected JSON schema', $errors);
23461 }
23462
23463 return true;
23464 }
23465
23466
23467
23468
23469
23470
23471
23472
23473 public static function encode($data, $options = 448)
23474 {
23475 if (PHP_VERSION_ID >= 50400) {
23476 $json = json_encode($data, $options);
23477 if (false === $json) {
23478 self::throwEncodeError(json_last_error());
23479 }
23480
23481
23482  if (PHP_VERSION_ID < 50428 || (PHP_VERSION_ID >= 50500 && PHP_VERSION_ID < 50512) || (defined('JSON_C_VERSION') && version_compare(phpversion('json'), '1.3.6', '<'))) {
23483 $json = preg_replace('/\[\s+\]/', '[]', $json);
23484 $json = preg_replace('/\{\s+\}/', '{}', $json);
23485 }
23486
23487 return $json;
23488 }
23489
23490 $json = json_encode($data);
23491 if (false === $json) {
23492 self::throwEncodeError(json_last_error());
23493 }
23494
23495 $prettyPrint = (bool) ($options & self::JSON_PRETTY_PRINT);
23496 $unescapeUnicode = (bool) ($options & self::JSON_UNESCAPED_UNICODE);
23497 $unescapeSlashes = (bool) ($options & self::JSON_UNESCAPED_SLASHES);
23498
23499 if (!$prettyPrint && !$unescapeUnicode && !$unescapeSlashes) {
23500 return $json;
23501 }
23502
23503 $result = JsonFormatter::format($json, $unescapeUnicode, $unescapeSlashes);
23504
23505 return $result;
23506 }
23507
23508
23509
23510
23511
23512
23513
23514 private static function throwEncodeError($code)
23515 {
23516 switch ($code) {
23517 case JSON_ERROR_DEPTH:
23518 $msg = 'Maximum stack depth exceeded';
23519 break;
23520 case JSON_ERROR_STATE_MISMATCH:
23521 $msg = 'Underflow or the modes mismatch';
23522 break;
23523 case JSON_ERROR_CTRL_CHAR:
23524 $msg = 'Unexpected control character found';
23525 break;
23526 case JSON_ERROR_UTF8:
23527 $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
23528 break;
23529 default:
23530 $msg = 'Unknown error';
23531 }
23532
23533 throw new \RuntimeException('JSON encoding failed: '.$msg);
23534 }
23535
23536
23537
23538
23539
23540
23541
23542
23543
23544 public static function parseJson($json, $file = null)
23545 {
23546 if (null === $json) {
23547 return;
23548 }
23549 $data = json_decode($json, true);
23550 if (null === $data && JSON_ERROR_NONE !== json_last_error()) {
23551 self::validateSyntax($json, $file);
23552 }
23553
23554 return $data;
23555 }
23556
23557
23558
23559
23560
23561
23562
23563
23564
23565
23566
23567 protected static function validateSyntax($json, $file = null)
23568 {
23569 $parser = new JsonParser();
23570 $result = $parser->lint($json);
23571 if (null === $result) {
23572 if (defined('JSON_ERROR_UTF8') && JSON_ERROR_UTF8 === json_last_error()) {
23573 throw new \UnexpectedValueException('"'.$file.'" is not UTF-8, could not parse as JSON');
23574 }
23575
23576 return true;
23577 }
23578
23579 throw new ParsingException('"'.$file.'" does not contain valid JSON'."\n".$result->getMessage(), $result->getDetails());
23580 }
23581 }
23582 <?php
23583
23584
23585
23586
23587
23588
23589
23590
23591
23592
23593
23594 namespace Composer\Json;
23595
23596
23597
23598
23599
23600
23601
23602
23603
23604 class JsonFormatter
23605 {
23606
23607
23608
23609
23610
23611
23612
23613
23614
23615
23616
23617
23618 public static function format($json, $unescapeUnicode, $unescapeSlashes)
23619 {
23620 $result = '';
23621 $pos = 0;
23622 $strLen = strlen($json);
23623 $indentStr = '    ';
23624 $newLine = "\n";
23625 $outOfQuotes = true;
23626 $buffer = '';
23627 $noescape = true;
23628
23629 for ($i = 0; $i < $strLen; $i++) {
23630
23631  $char = substr($json, $i, 1);
23632
23633
23634  if ('"' === $char && $noescape) {
23635 $outOfQuotes = !$outOfQuotes;
23636 }
23637
23638 if (!$outOfQuotes) {
23639 $buffer .= $char;
23640 $noescape = '\\' === $char ? !$noescape : true;
23641 continue;
23642 } elseif ('' !== $buffer) {
23643 if ($unescapeSlashes) {
23644 $buffer = str_replace('\\/', '/', $buffer);
23645 }
23646
23647 if ($unescapeUnicode && function_exists('mb_convert_encoding')) {
23648
23649  $buffer = preg_replace_callback('/(\\\\+)u([0-9a-f]{4})/i', function ($match) {
23650 $l = strlen($match[1]);
23651
23652 if ($l % 2) {
23653 return str_repeat('\\', $l - 1) . mb_convert_encoding(
23654 pack('H*', $match[2]),
23655 'UTF-8',
23656 'UCS-2BE'
23657 );
23658 }
23659
23660 return $match[0];
23661 }, $buffer);
23662 }
23663
23664 $result .= $buffer.$char;
23665 $buffer = '';
23666 continue;
23667 }
23668
23669 if (':' === $char) {
23670
23671  $char .= ' ';
23672 } elseif (('}' === $char || ']' === $char)) {
23673 $pos--;
23674 $prevChar = substr($json, $i - 1, 1);
23675
23676 if ('{' !== $prevChar && '[' !== $prevChar) {
23677
23678  
23679  $result .= $newLine;
23680 for ($j = 0; $j < $pos; $j++) {
23681 $result .= $indentStr;
23682 }
23683 } else {
23684
23685  $result = rtrim($result);
23686 }
23687 }
23688
23689 $result .= $char;
23690
23691
23692  
23693  if (',' === $char || '{' === $char || '[' === $char) {
23694 $result .= $newLine;
23695
23696 if ('{' === $char || '[' === $char) {
23697 $pos++;
23698 }
23699
23700 for ($j = 0; $j < $pos; $j++) {
23701 $result .= $indentStr;
23702 }
23703 }
23704 }
23705
23706 return $result;
23707 }
23708 }
23709 <?php
23710
23711
23712
23713
23714
23715
23716
23717
23718
23719
23720
23721 namespace Composer\Json;
23722
23723 use Composer\Repository\PlatformRepository;
23724
23725
23726
23727
23728 class JsonManipulator
23729 {
23730 private static $DEFINES = '(?(DEFINE)
23731        (?<number>   -? (?= [1-9]|0(?!\d) ) \d+ (\.\d+)? ([eE] [+-]? \d+)? )
23732        (?<boolean>   true | false | null )
23733        (?<string>    " ([^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9a-f]{4} )* " )
23734        (?<array>     \[  (?:  (?&json) \s* (?: , (?&json) \s* )*  )?  \s* \] )
23735        (?<pair>      \s* (?&string) \s* : (?&json) \s* )
23736        (?<object>    \{  (?:  (?&pair)  (?: , (?&pair)  )*  )?  \s* \} )
23737        (?<json>   \s* (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) )
23738     )';
23739
23740 private $contents;
23741 private $newline;
23742 private $indent;
23743
23744 public function __construct($contents)
23745 {
23746 $contents = trim($contents);
23747 if ($contents === '') {
23748 $contents = '{}';
23749 }
23750 if (!$this->pregMatch('#^\{(.*)\}$#s', $contents)) {
23751 throw new \InvalidArgumentException('The json file must be an object ({})');
23752 }
23753 $this->newline = false !== strpos($contents, "\r\n") ? "\r\n" : "\n";
23754 $this->contents = $contents === '{}' ? '{' . $this->newline . '}' : $contents;
23755 $this->detectIndenting();
23756 }
23757
23758 public function getContents()
23759 {
23760 return $this->contents . $this->newline;
23761 }
23762
23763 public function addLink($type, $package, $constraint, $sortPackages = false)
23764 {
23765 $decoded = JsonFile::parseJson($this->contents);
23766
23767
23768  if (!isset($decoded[$type])) {
23769 return $this->addMainKey($type, array($package => $constraint));
23770 }
23771
23772 $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
23773 '(?P<property>'.preg_quote(JsonFile::encode($type)).'\s*:\s*)(?P<value>(?&json))(?P<end>.*)}sx';
23774 if (!$this->pregMatch($regex, $this->contents, $matches)) {
23775 return false;
23776 }
23777
23778 $links = $matches['value'];
23779
23780
23781  $packageRegex = str_replace('/', '\\\\?/', preg_quote($package));
23782 $regex = '{'.self::$DEFINES.'"(?P<package>'.$packageRegex.')"(\s*:\s*)(?&string)}ix';
23783 if ($this->pregMatch($regex, $links, $packageMatches)) {
23784
23785  $existingPackage = $packageMatches['package'];
23786 $packageRegex = str_replace('/', '\\\\?/', preg_quote($existingPackage));
23787 $links = preg_replace_callback('{'.self::$DEFINES.'"'.$packageRegex.'"(?P<separator>\s*:\s*)(?&string)}ix', function ($m) use ($existingPackage, $constraint) {
23788 return JsonFile::encode(str_replace('\\/', '/', $existingPackage)) . $m['separator'] . '"' . $constraint . '"';
23789 }, $links);
23790 } else {
23791 if ($this->pregMatch('#^\s*\{\s*\S+.*?(\s*\}\s*)$#s', $links, $match)) {
23792
23793  $links = preg_replace(
23794 '{'.preg_quote($match[1]).'$}',
23795
23796  addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $match[1], '\\$'),
23797 $links
23798 );
23799 } else {
23800
23801  $links = '{' . $this->newline .
23802 $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $this->newline .
23803 $this->indent . '}';
23804 }
23805 }
23806
23807 if (true === $sortPackages) {
23808 $requirements = json_decode($links, true);
23809 $this->sortPackages($requirements);
23810 $links = $this->format($requirements);
23811 }
23812
23813 $this->contents = $matches['start'] . $matches['property'] . $links . $matches['end'];
23814
23815 return true;
23816 }
23817
23818
23819
23820
23821
23822
23823
23824
23825 private function sortPackages(array &$packages = array())
23826 {
23827 $prefix = function ($requirement) {
23828 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $requirement)) {
23829 return preg_replace(
23830 array(
23831 '/^php/',
23832 '/^hhvm/',
23833 '/^ext/',
23834 '/^lib/',
23835 '/^\D/',
23836 ),
23837 array(
23838 '0-$0',
23839 '1-$0',
23840 '2-$0',
23841 '3-$0',
23842 '4-$0',
23843 ),
23844 $requirement
23845 );
23846 }
23847
23848 return '5-'.$requirement;
23849 };
23850
23851 uksort($packages, function ($a, $b) use ($prefix) {
23852 return strnatcmp($prefix($a), $prefix($b));
23853 });
23854 }
23855
23856 public function addRepository($name, $config)
23857 {
23858 return $this->addSubNode('repositories', $name, $config);
23859 }
23860
23861 public function removeRepository($name)
23862 {
23863 return $this->removeSubNode('repositories', $name);
23864 }
23865
23866 public function addConfigSetting($name, $value)
23867 {
23868 return $this->addSubNode('config', $name, $value);
23869 }
23870
23871 public function removeConfigSetting($name)
23872 {
23873 return $this->removeSubNode('config', $name);
23874 }
23875
23876 public function addProperty($name, $value)
23877 {
23878 if (substr($name, 0, 6) === 'extra.') {
23879 return $this->addSubNode('extra', substr($name, 6), $value);
23880 }
23881
23882 return $this->addMainKey($name, $value);
23883 }
23884
23885 public function removeProperty($name)
23886 {
23887 if (substr($name, 0, 6) === 'extra.') {
23888 return $this->removeSubNode('extra', substr($name, 6));
23889 }
23890
23891 return $this->removeMainKey($name);
23892 }
23893
23894 public function addSubNode($mainNode, $name, $value)
23895 {
23896 $decoded = JsonFile::parseJson($this->contents);
23897
23898 $subName = null;
23899 if (in_array($mainNode, array('config', 'extra')) && false !== strpos($name, '.')) {
23900 list($name, $subName) = explode('.', $name, 2);
23901 }
23902
23903
23904  if (!isset($decoded[$mainNode])) {
23905 if ($subName !== null) {
23906 $this->addMainKey($mainNode, array($name => array($subName => $value)));
23907 } else {
23908 $this->addMainKey($mainNode, array($name => $value));
23909 }
23910
23911 return true;
23912 }
23913
23914
23915  $nodeRegex = '{'.self::$DEFINES.'^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
23916 preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
23917
23918 try {
23919 if (!$this->pregMatch($nodeRegex, $this->contents, $match)) {
23920 return false;
23921 }
23922 } catch (\RuntimeException $e) {
23923 if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
23924 return false;
23925 }
23926 throw $e;
23927 }
23928
23929 $children = $match['content'];
23930
23931  if (!@json_decode($children)) {
23932 return false;
23933 }
23934
23935 $that = $this;
23936
23937
23938  $childRegex = '{'.self::$DEFINES.'(?P<start>"'.preg_quote($name).'"\s*:\s*)(?P<content>(?&json))(?P<end>,?)}x';
23939 if ($this->pregMatch($childRegex, $children, $matches)) {
23940 $children = preg_replace_callback($childRegex, function ($matches) use ($name, $subName, $value, $that) {
23941 if ($subName !== null) {
23942 $curVal = json_decode($matches['content'], true);
23943 if (!is_array($curVal)) {
23944 $curVal = array();
23945 }
23946 $curVal[$subName] = $value;
23947 $value = $curVal;
23948 }
23949
23950 return $matches['start'] . $that->format($value, 1) . $matches['end'];
23951 }, $children);
23952 } else {
23953 $this->pregMatch('#^{ \s*? (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $children, $match);
23954
23955 $whitespace = '';
23956 if (!empty($match['trailingspace'])) {
23957 $whitespace = $match['trailingspace'];
23958 }
23959
23960 if (!empty($match['content'])) {
23961 if ($subName !== null) {
23962 $value = array($subName => $value);
23963 }
23964
23965
23966  $children = preg_replace(
23967 '#'.$whitespace.'}$#',
23968 addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $whitespace . '}', '\\$'),
23969 $children
23970 );
23971 } else {
23972 if ($subName !== null) {
23973 $value = array($subName => $value);
23974 }
23975
23976
23977  $children = '{' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $whitespace . '}';
23978 }
23979 }
23980
23981 $this->contents = preg_replace_callback($nodeRegex, function ($m) use ($children) {
23982 return $m['start'] . $children . $m['end'];
23983 }, $this->contents);
23984
23985 return true;
23986 }
23987
23988 public function removeSubNode($mainNode, $name)
23989 {
23990 $decoded = JsonFile::parseJson($this->contents);
23991
23992
23993  if (empty($decoded[$mainNode])) {
23994 return true;
23995 }
23996
23997
23998  $nodeRegex = '{'.self::$DEFINES.'^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
23999 preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
24000 try {
24001 if (!$this->pregMatch($nodeRegex, $this->contents, $match)) {
24002 return false;
24003 }
24004 } catch (\RuntimeException $e) {
24005 if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
24006 return false;
24007 }
24008 throw $e;
24009 }
24010
24011 $children = $match['content'];
24012
24013
24014  if (!@json_decode($children, true)) {
24015 return false;
24016 }
24017
24018 $subName = null;
24019 if (in_array($mainNode, array('config', 'extra')) && false !== strpos($name, '.')) {
24020 list($name, $subName) = explode('.', $name, 2);
24021 }
24022
24023
24024  if (!isset($decoded[$mainNode][$name]) || ($subName && !isset($decoded[$mainNode][$name][$subName]))) {
24025 return true;
24026 }
24027
24028
24029  if ($this->pregMatch('{"'.preg_quote($name).'"\s*:}i', $children)) {
24030
24031  if (preg_match_all('{'.self::$DEFINES.'"'.preg_quote($name).'"\s*:\s*(?:(?&json))}x', $children, $matches)) {
24032 $bestMatch = '';
24033 foreach ($matches[0] as $match) {
24034 if (strlen($bestMatch) < strlen($match)) {
24035 $bestMatch = $match;
24036 }
24037 }
24038 $childrenClean = preg_replace('{,\s*'.preg_quote($bestMatch).'}i', '', $children, -1, $count);
24039 if (1 !== $count) {
24040 $childrenClean = preg_replace('{'.preg_quote($bestMatch).'\s*,?\s*}i', '', $childrenClean, -1, $count);
24041 if (1 !== $count) {
24042 return false;
24043 }
24044 }
24045 }
24046 } else {
24047 $childrenClean = $children;
24048 }
24049
24050
24051  $this->pregMatch('#^{ \s*? (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $childrenClean, $match);
24052 if (empty($match['content'])) {
24053 $newline = $this->newline;
24054 $indent = $this->indent;
24055
24056 $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($indent, $newline) {
24057 return $matches['start'] . '{' . $newline . $indent . '}' . $matches['end'];
24058 }, $this->contents);
24059
24060
24061  if ($subName !== null) {
24062 $curVal = json_decode($children, true);
24063 unset($curVal[$name][$subName]);
24064 $this->addSubNode($mainNode, $name, $curVal[$name]);
24065 }
24066
24067 return true;
24068 }
24069
24070 $that = $this;
24071 $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($that, $name, $subName, $childrenClean) {
24072 if ($subName !== null) {
24073 $curVal = json_decode($matches['content'], true);
24074 unset($curVal[$name][$subName]);
24075 $childrenClean = $that->format($curVal, 0);
24076 }
24077
24078 return $matches['start'] . $childrenClean . $matches['end'];
24079 }, $this->contents);
24080
24081 return true;
24082 }
24083
24084 public function addMainKey($key, $content)
24085 {
24086 $decoded = JsonFile::parseJson($this->contents);
24087 $content = $this->format($content);
24088
24089
24090  $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
24091 '(?P<key>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))(?P<end>.*)}sx';
24092 if (isset($decoded[$key]) && $this->pregMatch($regex, $this->contents, $matches)) {
24093
24094  if (!@json_decode('{'.$matches['key'].'}')) {
24095 return false;
24096 }
24097
24098 $this->contents = $matches['start'] . JsonFile::encode($key).': '.$content . $matches['end'];
24099
24100 return true;
24101 }
24102
24103
24104  if ($this->pregMatch('#[^{\s](\s*)\}$#', $this->contents, $match)) {
24105 $this->contents = preg_replace(
24106 '#'.$match[1].'\}$#',
24107 addcslashes(',' . $this->newline . $this->indent . JsonFile::encode($key). ': '. $content . $this->newline . '}', '\\$'),
24108 $this->contents
24109 );
24110
24111 return true;
24112 }
24113
24114
24115  $this->contents = preg_replace(
24116 '#\}$#',
24117 addcslashes($this->indent . JsonFile::encode($key). ': '.$content . $this->newline . '}', '\\$'),
24118 $this->contents
24119 );
24120
24121 return true;
24122 }
24123
24124 public function removeMainKey($key)
24125 {
24126 $decoded = JsonFile::parseJson($this->contents);
24127
24128 if (!isset($decoded[$key])) {
24129 return true;
24130 }
24131
24132
24133  $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
24134 '(?P<removal>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))\s*,?\s*(?P<end>.*)}sx';
24135 if ($this->pregMatch($regex, $this->contents, $matches)) {
24136
24137  if (!@json_decode('{'.$matches['removal'].'}')) {
24138 return false;
24139 }
24140
24141
24142  if (preg_match('#,\s*$#', $matches['start']) && preg_match('#^\}$#', $matches['end'])) {
24143 $matches['start'] = rtrim(preg_replace('#,(\s*)$#', '$1', $matches['start']), $this->indent);
24144 }
24145
24146 $this->contents = $matches['start'] . $matches['end'];
24147 if (preg_match('#^\{\s*\}\s*$#', $this->contents)) {
24148 $this->contents = "{\n}";
24149 }
24150
24151 return true;
24152 }
24153
24154 return false;
24155 }
24156
24157 public function format($data, $depth = 0)
24158 {
24159 if (is_array($data)) {
24160 reset($data);
24161
24162 if (is_numeric(key($data))) {
24163 foreach ($data as $key => $val) {
24164 $data[$key] = $this->format($val, $depth + 1);
24165 }
24166
24167 return '['.implode(', ', $data).']';
24168 }
24169
24170 $out = '{' . $this->newline;
24171 $elems = array();
24172 foreach ($data as $key => $val) {
24173 $elems[] = str_repeat($this->indent, $depth + 2) . JsonFile::encode($key). ': '.$this->format($val, $depth + 1);
24174 }
24175
24176 return $out . implode(','.$this->newline, $elems) . $this->newline . str_repeat($this->indent, $depth + 1) . '}';
24177 }
24178
24179 return JsonFile::encode($data);
24180 }
24181
24182 protected function detectIndenting()
24183 {
24184 if ($this->pregMatch('{^([ \t]+)"}m', $this->contents, $match)) {
24185 $this->indent = $match[1];
24186 } else {
24187 $this->indent = '    ';
24188 }
24189 }
24190
24191 protected function pregMatch($re, $str, &$matches = array())
24192 {
24193 $count = preg_match($re, $str, $matches);
24194
24195 if ($count === false) {
24196 switch (preg_last_error()) {
24197 case PREG_NO_ERROR:
24198 throw new \RuntimeException('Failed to execute regex: PREG_NO_ERROR', PREG_NO_ERROR);
24199 case PREG_INTERNAL_ERROR:
24200 throw new \RuntimeException('Failed to execute regex: PREG_INTERNAL_ERROR', PREG_INTERNAL_ERROR);
24201 case PREG_BACKTRACK_LIMIT_ERROR:
24202 throw new \RuntimeException('Failed to execute regex: PREG_BACKTRACK_LIMIT_ERROR', PREG_BACKTRACK_LIMIT_ERROR);
24203 case PREG_RECURSION_LIMIT_ERROR:
24204 throw new \RuntimeException('Failed to execute regex: PREG_RECURSION_LIMIT_ERROR', PREG_RECURSION_LIMIT_ERROR);
24205 case PREG_BAD_UTF8_ERROR:
24206 throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_ERROR', PREG_BAD_UTF8_ERROR);
24207 case PREG_BAD_UTF8_OFFSET_ERROR:
24208 throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_OFFSET_ERROR', PREG_BAD_UTF8_OFFSET_ERROR);
24209 case 6: 
24210  if (PHP_VERSION_ID > 70000) {
24211 throw new \RuntimeException('Failed to execute regex: PREG_JIT_STACKLIMIT_ERROR', 6);
24212 }
24213
24214
24215 default:
24216 throw new \RuntimeException('Failed to execute regex: Unknown error');
24217 }
24218 }
24219
24220 return $count;
24221 }
24222 }
24223 <?php
24224
24225
24226
24227
24228
24229
24230
24231
24232
24233
24234
24235 namespace Composer\Json;
24236
24237 use Exception;
24238
24239
24240
24241
24242 class JsonValidationException extends Exception
24243 {
24244 protected $errors;
24245
24246 public function __construct($message, $errors = array(), Exception $previous = null)
24247 {
24248 $this->errors = $errors;
24249 parent::__construct($message, 0, $previous);
24250 }
24251
24252 public function getErrors()
24253 {
24254 return $this->errors;
24255 }
24256 }
24257 <?php
24258
24259
24260
24261
24262
24263
24264
24265
24266
24267
24268
24269 namespace Composer\Package;
24270
24271 use Composer\Semver\Constraint\Constraint;
24272 use Composer\Package\Version\VersionParser;
24273
24274
24275
24276
24277 class AliasPackage extends BasePackage implements CompletePackageInterface
24278 {
24279 protected $version;
24280 protected $prettyVersion;
24281 protected $dev;
24282 protected $rootPackageAlias = false;
24283 protected $stability;
24284
24285
24286 protected $aliasOf;
24287
24288 protected $requires;
24289
24290 protected $devRequires;
24291
24292 protected $conflicts;
24293
24294 protected $provides;
24295
24296 protected $replaces;
24297
24298
24299
24300
24301
24302
24303
24304
24305 public function __construct(PackageInterface $aliasOf, $version, $prettyVersion)
24306 {
24307 parent::__construct($aliasOf->getName());
24308
24309 $this->version = $version;
24310 $this->prettyVersion = $prettyVersion;
24311 $this->aliasOf = $aliasOf;
24312 $this->stability = VersionParser::parseStability($version);
24313 $this->dev = $this->stability === 'dev';
24314
24315 foreach (array('requires', 'devRequires', 'conflicts', 'provides', 'replaces') as $type) {
24316 $links = $aliasOf->{'get' . ucfirst($type)}();
24317 $this->$type = $this->replaceSelfVersionDependencies($links, $type);
24318 }
24319 }
24320
24321
24322
24323
24324 public function getAliasOf()
24325 {
24326 return $this->aliasOf;
24327 }
24328
24329
24330
24331
24332 public function getVersion()
24333 {
24334 return $this->version;
24335 }
24336
24337
24338
24339
24340 public function getStability()
24341 {
24342 return $this->stability;
24343 }
24344
24345
24346
24347
24348 public function getPrettyVersion()
24349 {
24350 return $this->prettyVersion;
24351 }
24352
24353
24354
24355
24356 public function isDev()
24357 {
24358 return $this->dev;
24359 }
24360
24361
24362
24363
24364 public function getRequires()
24365 {
24366 return $this->requires;
24367 }
24368
24369
24370
24371
24372 public function getConflicts()
24373 {
24374 return $this->conflicts;
24375 }
24376
24377
24378
24379
24380 public function getProvides()
24381 {
24382 return $this->provides;
24383 }
24384
24385
24386
24387
24388 public function getReplaces()
24389 {
24390 return $this->replaces;
24391 }
24392
24393
24394
24395
24396 public function getDevRequires()
24397 {
24398 return $this->devRequires;
24399 }
24400
24401
24402
24403
24404
24405
24406
24407
24408
24409
24410 public function setRootPackageAlias($value)
24411 {
24412 return $this->rootPackageAlias = $value;
24413 }
24414
24415
24416
24417
24418
24419 public function isRootPackageAlias()
24420 {
24421 return $this->rootPackageAlias;
24422 }
24423
24424
24425
24426
24427
24428
24429
24430 protected function replaceSelfVersionDependencies(array $links, $linkType)
24431 {
24432 if (in_array($linkType, array('conflicts', 'provides', 'replaces'), true)) {
24433 $newLinks = array();
24434 foreach ($links as $link) {
24435
24436  if ('self.version' === $link->getPrettyConstraint()) {
24437 $newLinks[] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
24438 }
24439 }
24440 $links = array_merge($links, $newLinks);
24441 } else {
24442 foreach ($links as $index => $link) {
24443 if ('self.version' === $link->getPrettyConstraint()) {
24444 $links[$index] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
24445 }
24446 }
24447 }
24448
24449 return $links;
24450 }
24451
24452
24453
24454
24455
24456 public function getType()
24457 {
24458 return $this->aliasOf->getType();
24459 }
24460
24461 public function getTargetDir()
24462 {
24463 return $this->aliasOf->getTargetDir();
24464 }
24465
24466 public function getExtra()
24467 {
24468 return $this->aliasOf->getExtra();
24469 }
24470
24471 public function setInstallationSource($type)
24472 {
24473 $this->aliasOf->setInstallationSource($type);
24474 }
24475
24476 public function getInstallationSource()
24477 {
24478 return $this->aliasOf->getInstallationSource();
24479 }
24480
24481 public function getSourceType()
24482 {
24483 return $this->aliasOf->getSourceType();
24484 }
24485
24486 public function getSourceUrl()
24487 {
24488 return $this->aliasOf->getSourceUrl();
24489 }
24490
24491 public function getSourceUrls()
24492 {
24493 return $this->aliasOf->getSourceUrls();
24494 }
24495
24496 public function getSourceReference()
24497 {
24498 return $this->aliasOf->getSourceReference();
24499 }
24500
24501 public function setSourceReference($reference)
24502 {
24503 return $this->aliasOf->setSourceReference($reference);
24504 }
24505
24506 public function setSourceMirrors($mirrors)
24507 {
24508 return $this->aliasOf->setSourceMirrors($mirrors);
24509 }
24510
24511 public function getSourceMirrors()
24512 {
24513 return $this->aliasOf->getSourceMirrors();
24514 }
24515
24516 public function getDistType()
24517 {
24518 return $this->aliasOf->getDistType();
24519 }
24520
24521 public function getDistUrl()
24522 {
24523 return $this->aliasOf->getDistUrl();
24524 }
24525
24526 public function getDistUrls()
24527 {
24528 return $this->aliasOf->getDistUrls();
24529 }
24530
24531 public function getDistReference()
24532 {
24533 return $this->aliasOf->getDistReference();
24534 }
24535
24536 public function setDistReference($reference)
24537 {
24538 return $this->aliasOf->setDistReference($reference);
24539 }
24540
24541 public function getDistSha1Checksum()
24542 {
24543 return $this->aliasOf->getDistSha1Checksum();
24544 }
24545
24546 public function setTransportOptions(array $options)
24547 {
24548 return $this->aliasOf->setTransportOptions($options);
24549 }
24550
24551 public function getTransportOptions()
24552 {
24553 return $this->aliasOf->getTransportOptions();
24554 }
24555
24556 public function setDistMirrors($mirrors)
24557 {
24558 return $this->aliasOf->setDistMirrors($mirrors);
24559 }
24560
24561 public function getDistMirrors()
24562 {
24563 return $this->aliasOf->getDistMirrors();
24564 }
24565
24566 public function getScripts()
24567 {
24568 return $this->aliasOf->getScripts();
24569 }
24570
24571 public function getLicense()
24572 {
24573 return $this->aliasOf->getLicense();
24574 }
24575
24576 public function getAutoload()
24577 {
24578 return $this->aliasOf->getAutoload();
24579 }
24580
24581 public function getDevAutoload()
24582 {
24583 return $this->aliasOf->getDevAutoload();
24584 }
24585
24586 public function getIncludePaths()
24587 {
24588 return $this->aliasOf->getIncludePaths();
24589 }
24590
24591 public function getRepositories()
24592 {
24593 return $this->aliasOf->getRepositories();
24594 }
24595
24596 public function getReleaseDate()
24597 {
24598 return $this->aliasOf->getReleaseDate();
24599 }
24600
24601 public function getBinaries()
24602 {
24603 return $this->aliasOf->getBinaries();
24604 }
24605
24606 public function getKeywords()
24607 {
24608 return $this->aliasOf->getKeywords();
24609 }
24610
24611 public function getDescription()
24612 {
24613 return $this->aliasOf->getDescription();
24614 }
24615
24616 public function getHomepage()
24617 {
24618 return $this->aliasOf->getHomepage();
24619 }
24620
24621 public function getSuggests()
24622 {
24623 return $this->aliasOf->getSuggests();
24624 }
24625
24626 public function getAuthors()
24627 {
24628 return $this->aliasOf->getAuthors();
24629 }
24630
24631 public function getSupport()
24632 {
24633 return $this->aliasOf->getSupport();
24634 }
24635
24636 public function getNotificationUrl()
24637 {
24638 return $this->aliasOf->getNotificationUrl();
24639 }
24640
24641 public function getArchiveExcludes()
24642 {
24643 return $this->aliasOf->getArchiveExcludes();
24644 }
24645
24646 public function isAbandoned()
24647 {
24648 return $this->aliasOf->isAbandoned();
24649 }
24650
24651 public function getReplacementPackage()
24652 {
24653 return $this->aliasOf->getReplacementPackage();
24654 }
24655
24656 public function __toString()
24657 {
24658 return parent::__toString().' (alias of '.$this->aliasOf->getVersion().')';
24659 }
24660 }
24661 <?php
24662
24663
24664
24665
24666
24667
24668
24669
24670
24671
24672
24673 namespace Composer\Package\Archiver;
24674
24675 use FilterIterator;
24676 use PharData;
24677
24678 class ArchivableFilesFilter extends FilterIterator
24679 {
24680 private $dirs = array();
24681
24682
24683
24684
24685 public function accept()
24686 {
24687 $file = $this->getInnerIterator()->current();
24688 if ($file->isDir()) {
24689 $this->dirs[] = (string) $file;
24690
24691 return false;
24692 }
24693
24694 return true;
24695 }
24696
24697 public function addEmptyDir(PharData $phar, $sources)
24698 {
24699 foreach ($this->dirs as $filepath) {
24700 $localname = str_replace($sources . "/", '', $filepath);
24701 $phar->addEmptyDir($localname);
24702 }
24703 }
24704 }
24705 <?php
24706
24707
24708
24709
24710
24711
24712
24713
24714
24715
24716
24717 namespace Composer\Package\Archiver;
24718
24719 use Composer\Util\Filesystem;
24720 use FilesystemIterator;
24721 use Symfony\Component\Finder\Finder;
24722 use Symfony\Component\Finder\SplFileInfo;
24723
24724
24725
24726
24727
24728
24729
24730
24731
24732 class ArchivableFilesFinder extends \FilterIterator
24733 {
24734
24735
24736
24737 protected $finder;
24738
24739
24740
24741
24742
24743
24744
24745
24746 public function __construct($sources, array $excludes, $ignoreFilters = false)
24747 {
24748 $fs = new Filesystem();
24749
24750 $sources = $fs->normalizePath($sources);
24751
24752 if ($ignoreFilters) {
24753 $filters = array();
24754 } else {
24755 $filters = array(
24756 new HgExcludeFilter($sources),
24757 new GitExcludeFilter($sources),
24758 new ComposerExcludeFilter($sources, $excludes),
24759 );
24760 }
24761
24762 $this->finder = new Finder();
24763
24764 $filter = function (\SplFileInfo $file) use ($sources, $filters, $fs) {
24765 if ($file->isLink() && strpos($file->getLinkTarget(), $sources) !== 0) {
24766 return false;
24767 }
24768
24769 $relativePath = preg_replace(
24770 '#^'.preg_quote($sources, '#').'#',
24771 '',
24772 $fs->normalizePath($file->getRealPath())
24773 );
24774
24775 $exclude = false;
24776 foreach ($filters as $filter) {
24777 $exclude = $filter->filter($relativePath, $exclude);
24778 }
24779
24780 return !$exclude;
24781 };
24782
24783 if (method_exists($filter, 'bindTo')) {
24784 $filter = $filter->bindTo(null);
24785 }
24786
24787 $this->finder
24788 ->in($sources)
24789 ->filter($filter)
24790 ->ignoreVCS(true)
24791 ->ignoreDotFiles(false);
24792
24793 parent::__construct($this->finder->getIterator());
24794 }
24795
24796 public function accept()
24797 {
24798
24799 $current = $this->getInnerIterator()->current();
24800
24801 if (!$current->isDir()) {
24802 return true;
24803 }
24804
24805 $iterator = new FilesystemIterator($current, FilesystemIterator::SKIP_DOTS);
24806
24807 return !$iterator->valid();
24808 }
24809 }
24810 <?php
24811
24812
24813
24814
24815
24816
24817
24818
24819
24820
24821
24822 namespace Composer\Package\Archiver;
24823
24824 use Composer\Downloader\DownloadManager;
24825 use Composer\Package\PackageInterface;
24826 use Composer\Package\RootPackageInterface;
24827 use Composer\Util\Filesystem;
24828 use Composer\Json\JsonFile;
24829
24830
24831
24832
24833
24834 class ArchiveManager
24835 {
24836 protected $downloadManager;
24837
24838 protected $archivers = array();
24839
24840
24841
24842
24843 protected $overwriteFiles = true;
24844
24845
24846
24847
24848 public function __construct(DownloadManager $downloadManager)
24849 {
24850 $this->downloadManager = $downloadManager;
24851 }
24852
24853
24854
24855
24856 public function addArchiver(ArchiverInterface $archiver)
24857 {
24858 $this->archivers[] = $archiver;
24859 }
24860
24861
24862
24863
24864
24865
24866
24867
24868 public function setOverwriteFiles($overwriteFiles)
24869 {
24870 $this->overwriteFiles = $overwriteFiles;
24871
24872 return $this;
24873 }
24874
24875
24876
24877
24878
24879
24880
24881
24882 public function getPackageFilename(PackageInterface $package)
24883 {
24884 $nameParts = array(preg_replace('#[^a-z0-9-_]#i', '-', $package->getName()));
24885
24886 if (preg_match('{^[a-f0-9]{40}$}', $package->getDistReference())) {
24887 $nameParts = array_merge($nameParts, array($package->getDistReference(), $package->getDistType()));
24888 } else {
24889 $nameParts = array_merge($nameParts, array($package->getPrettyVersion(), $package->getDistReference()));
24890 }
24891
24892 if ($package->getSourceReference()) {
24893 $nameParts[] = substr(sha1($package->getSourceReference()), 0, 6);
24894 }
24895
24896 $name = implode('-', array_filter($nameParts, function ($p) {
24897 return !empty($p);
24898 }));
24899
24900 return str_replace('/', '-', $name);
24901 }
24902
24903
24904
24905
24906
24907
24908
24909
24910
24911
24912
24913
24914
24915
24916 public function archive(PackageInterface $package, $format, $targetDir, $fileName = null, $ignoreFilters = false)
24917 {
24918 if (empty($format)) {
24919 throw new \InvalidArgumentException('Format must be specified');
24920 }
24921
24922
24923  $usableArchiver = null;
24924 foreach ($this->archivers as $archiver) {
24925 if ($archiver->supports($format, $package->getSourceType())) {
24926 $usableArchiver = $archiver;
24927 break;
24928 }
24929 }
24930
24931
24932  if (null === $usableArchiver) {
24933 throw new \RuntimeException(sprintf('No archiver found to support %s format', $format));
24934 }
24935
24936 $filesystem = new Filesystem();
24937 if (null === $fileName) {
24938 $packageName = $this->getPackageFilename($package);
24939 } else {
24940 $packageName = $fileName;
24941 }
24942
24943
24944  $filesystem->ensureDirectoryExists($targetDir);
24945 $target = realpath($targetDir).'/'.$packageName.'.'.$format;
24946 $filesystem->ensureDirectoryExists(dirname($target));
24947
24948 if (!$this->overwriteFiles && file_exists($target)) {
24949 return $target;
24950 }
24951
24952 if ($package instanceof RootPackageInterface) {
24953 $sourcePath = realpath('.');
24954 } else {
24955
24956  $sourcePath = sys_get_temp_dir().'/composer_archive'.uniqid();
24957 $filesystem->ensureDirectoryExists($sourcePath);
24958
24959
24960  $this->downloadManager->download($package, $sourcePath);
24961
24962
24963  if (file_exists($composerJsonPath = $sourcePath.'/composer.json')) {
24964 $jsonFile = new JsonFile($composerJsonPath);
24965 $jsonData = $jsonFile->read();
24966 if (!empty($jsonData['archive']['exclude'])) {
24967 $package->setArchiveExcludes($jsonData['archive']['exclude']);
24968 }
24969 }
24970 }
24971
24972
24973  $tempTarget = sys_get_temp_dir().'/composer_archive'.uniqid().'.'.$format;
24974 $filesystem->ensureDirectoryExists(dirname($tempTarget));
24975
24976 $archivePath = $usableArchiver->archive($sourcePath, $tempTarget, $format, $package->getArchiveExcludes(), $ignoreFilters);
24977 $filesystem->rename($archivePath, $target);
24978
24979
24980  if (!$package instanceof RootPackageInterface) {
24981 $filesystem->removeDirectory($sourcePath);
24982 }
24983 $filesystem->remove($tempTarget);
24984
24985 return $target;
24986 }
24987 }
24988 <?php
24989
24990
24991
24992
24993
24994
24995
24996
24997
24998
24999
25000 namespace Composer\Package\Archiver;
25001
25002
25003
25004
25005
25006
25007 interface ArchiverInterface
25008 {
25009
25010
25011
25012
25013
25014
25015
25016
25017
25018
25019 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false);
25020
25021
25022
25023
25024
25025
25026
25027
25028
25029 public function supports($format, $sourceType);
25030 }
25031 <?php
25032
25033
25034
25035
25036
25037
25038
25039
25040
25041
25042
25043 namespace Composer\Package\Archiver;
25044
25045 use Symfony\Component\Finder;
25046
25047
25048
25049
25050 abstract class BaseExcludeFilter
25051 {
25052
25053
25054
25055 protected $sourcePath;
25056
25057
25058
25059
25060 protected $excludePatterns;
25061
25062
25063
25064
25065 public function __construct($sourcePath)
25066 {
25067 $this->sourcePath = $sourcePath;
25068 $this->excludePatterns = array();
25069 }
25070
25071
25072
25073
25074
25075
25076
25077
25078
25079
25080
25081 public function filter($relativePath, $exclude)
25082 {
25083 foreach ($this->excludePatterns as $patternData) {
25084 list($pattern, $negate, $stripLeadingSlash) = $patternData;
25085
25086 if ($stripLeadingSlash) {
25087 $path = substr($relativePath, 1);
25088 } else {
25089 $path = $relativePath;
25090 }
25091
25092 if (preg_match($pattern, $path)) {
25093 $exclude = !$negate;
25094 }
25095 }
25096
25097 return $exclude;
25098 }
25099
25100
25101
25102
25103
25104
25105
25106
25107
25108 protected function parseLines(array $lines, $lineParser)
25109 {
25110 return array_filter(
25111 array_map(
25112 function ($line) use ($lineParser) {
25113 $line = trim($line);
25114
25115 if (!$line || 0 === strpos($line, '#')) {
25116 return null;
25117 }
25118
25119 return call_user_func($lineParser, $line);
25120 },
25121 $lines
25122 ),
25123 function ($pattern) {
25124 return $pattern !== null;
25125 }
25126 );
25127 }
25128
25129
25130
25131
25132
25133
25134
25135
25136 protected function generatePatterns($rules)
25137 {
25138 $patterns = array();
25139 foreach ($rules as $rule) {
25140 $patterns[] = $this->generatePattern($rule);
25141 }
25142
25143 return $patterns;
25144 }
25145
25146
25147
25148
25149
25150
25151
25152
25153 protected function generatePattern($rule)
25154 {
25155 $negate = false;
25156 $pattern = '{';
25157
25158 if (strlen($rule) && $rule[0] === '!') {
25159 $negate = true;
25160 $rule = substr($rule, 1);
25161 }
25162
25163 if (strlen($rule) && $rule[0] === '/') {
25164 $pattern .= '^/';
25165 $rule = substr($rule, 1);
25166 } elseif (strlen($rule) - 1 === strpos($rule, '/')) {
25167 $pattern .= '/';
25168 $rule = substr($rule, 0, -1);
25169 } elseif (false === strpos($rule, '/')) {
25170 $pattern .= '/';
25171 }
25172
25173
25174  $pattern .= substr(Finder\Glob::toRegex($rule), 2, -2) . '(?=$|/)';
25175
25176 return array($pattern . '}', $negate, false);
25177 }
25178 }
25179 <?php
25180
25181
25182
25183
25184
25185
25186
25187
25188
25189
25190
25191 namespace Composer\Package\Archiver;
25192
25193
25194
25195
25196
25197
25198 class ComposerExcludeFilter extends BaseExcludeFilter
25199 {
25200
25201
25202
25203
25204 public function __construct($sourcePath, array $excludeRules)
25205 {
25206 parent::__construct($sourcePath);
25207 $this->excludePatterns = $this->generatePatterns($excludeRules);
25208 }
25209 }
25210 <?php
25211
25212
25213
25214
25215
25216
25217
25218
25219
25220
25221
25222 namespace Composer\Package\Archiver;
25223
25224
25225
25226
25227
25228
25229
25230
25231 class GitExcludeFilter extends BaseExcludeFilter
25232 {
25233
25234
25235
25236
25237
25238 public function __construct($sourcePath)
25239 {
25240 parent::__construct($sourcePath);
25241
25242 if (file_exists($sourcePath.'/.gitignore')) {
25243 $this->excludePatterns = $this->parseLines(
25244 file($sourcePath.'/.gitignore'),
25245 array($this, 'parseGitIgnoreLine')
25246 );
25247 }
25248 if (file_exists($sourcePath.'/.gitattributes')) {
25249 $this->excludePatterns = array_merge(
25250 $this->excludePatterns,
25251 $this->parseLines(
25252 file($sourcePath.'/.gitattributes'),
25253 array($this, 'parseGitAttributesLine')
25254 ));
25255 }
25256 }
25257
25258
25259
25260
25261
25262
25263
25264
25265 public function parseGitIgnoreLine($line)
25266 {
25267 return $this->generatePattern($line);
25268 }
25269
25270
25271
25272
25273
25274
25275
25276
25277 public function parseGitAttributesLine($line)
25278 {
25279 $parts = preg_split('#\s+#', $line);
25280
25281 if (count($parts) == 2 && $parts[1] === 'export-ignore') {
25282 return $this->generatePattern($parts[0]);
25283 }
25284
25285 return null;
25286 }
25287 }
25288 <?php
25289
25290
25291
25292
25293
25294
25295
25296
25297
25298
25299
25300 namespace Composer\Package\Archiver;
25301
25302 use Symfony\Component\Finder;
25303
25304
25305
25306
25307
25308
25309 class HgExcludeFilter extends BaseExcludeFilter
25310 {
25311 const HG_IGNORE_REGEX = 1;
25312 const HG_IGNORE_GLOB = 2;
25313
25314
25315
25316
25317
25318 protected $patternMode;
25319
25320
25321
25322
25323
25324
25325 public function __construct($sourcePath)
25326 {
25327 parent::__construct($sourcePath);
25328
25329 $this->patternMode = self::HG_IGNORE_REGEX;
25330
25331 if (file_exists($sourcePath.'/.hgignore')) {
25332 $this->excludePatterns = $this->parseLines(
25333 file($sourcePath.'/.hgignore'),
25334 array($this, 'parseHgIgnoreLine')
25335 );
25336 }
25337 }
25338
25339
25340
25341
25342
25343
25344
25345
25346 public function parseHgIgnoreLine($line)
25347 {
25348 if (preg_match('#^syntax\s*:\s*(glob|regexp)$#', $line, $matches)) {
25349 if ($matches[1] === 'glob') {
25350 $this->patternMode = self::HG_IGNORE_GLOB;
25351 } else {
25352 $this->patternMode = self::HG_IGNORE_REGEX;
25353 }
25354
25355 return null;
25356 }
25357
25358 if ($this->patternMode == self::HG_IGNORE_GLOB) {
25359 return $this->patternFromGlob($line);
25360 } else {
25361 return $this->patternFromRegex($line);
25362 }
25363 }
25364
25365
25366
25367
25368
25369
25370
25371
25372 protected function patternFromGlob($line)
25373 {
25374 $pattern = '#'.substr(Finder\Glob::toRegex($line), 2, -1).'#';
25375 $pattern = str_replace('[^/]*', '.*', $pattern);
25376
25377 return array($pattern, false, true);
25378 }
25379
25380
25381
25382
25383
25384
25385
25386
25387 public function patternFromRegex($line)
25388 {
25389
25390  $pattern = '#'.preg_replace('/((?:\\\\\\\\)*)(\\\\?)#/', '\1\2\2\\#', $line).'#';
25391
25392 return array($pattern, false, true);
25393 }
25394 }
25395 <?php
25396
25397
25398
25399
25400
25401
25402
25403
25404
25405
25406
25407 namespace Composer\Package\Archiver;
25408
25409
25410
25411
25412
25413
25414 class PharArchiver implements ArchiverInterface
25415 {
25416 protected static $formats = array(
25417 'zip' => \Phar::ZIP,
25418 'tar' => \Phar::TAR,
25419 'tar.gz' => \Phar::TAR,
25420 'tar.bz2' => \Phar::TAR,
25421 );
25422
25423 protected static $compressFormats = array(
25424 'tar.gz' => \Phar::GZ,
25425 'tar.bz2' => \Phar::BZ2,
25426 );
25427
25428
25429
25430
25431 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false)
25432 {
25433 $sources = realpath($sources);
25434
25435
25436  if (file_exists($target)) {
25437 unlink($target);
25438 }
25439
25440 try {
25441 $filename = substr($target, 0, strrpos($target, $format) - 1);
25442
25443
25444  if (isset(static::$compressFormats[$format])) {
25445
25446  $target = $filename . '.tar';
25447 }
25448
25449 $phar = new \PharData($target, null, null, static::$formats[$format]);
25450 $files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
25451 $filesOnly = new ArchivableFilesFilter($files);
25452 $phar->buildFromIterator($filesOnly, $sources);
25453 $filesOnly->addEmptyDir($phar, $sources);
25454
25455 if (isset(static::$compressFormats[$format])) {
25456
25457  if (!$phar->canCompress(static::$compressFormats[$format])) {
25458 throw new \RuntimeException(sprintf('Can not compress to %s format', $format));
25459 }
25460
25461
25462  unlink($target);
25463
25464
25465  $phar->compress(static::$compressFormats[$format]);
25466
25467
25468  $target = $filename . '.' . $format;
25469 }
25470
25471 return $target;
25472 } catch (\UnexpectedValueException $e) {
25473 $message = sprintf("Could not create archive '%s' from '%s': %s",
25474 $target,
25475 $sources,
25476 $e->getMessage()
25477 );
25478
25479 throw new \RuntimeException($message, $e->getCode(), $e);
25480 }
25481 }
25482
25483
25484
25485
25486 public function supports($format, $sourceType)
25487 {
25488 return isset(static::$formats[$format]);
25489 }
25490 }
25491 <?php
25492
25493
25494
25495
25496
25497
25498
25499
25500
25501
25502
25503 namespace Composer\Package\Archiver;
25504
25505 use ZipArchive;
25506 use Composer\Util\Filesystem;
25507
25508
25509
25510
25511 class ZipArchiver implements ArchiverInterface
25512 {
25513 protected static $formats = array(
25514 'zip' => 1,
25515 );
25516
25517
25518
25519
25520 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false)
25521 {
25522 $fs = new Filesystem();
25523 $sources = $fs->normalizePath($sources);
25524
25525 $zip = new ZipArchive();
25526 $res = $zip->open($target, ZipArchive::CREATE);
25527 if ($res === true) {
25528 $files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
25529 foreach ($files as $file) {
25530
25531 $filepath = strtr($file->getPath()."/".$file->getFilename(), '\\', '/');
25532 $localname = str_replace($sources.'/', '', $filepath);
25533 if ($file->isDir()) {
25534 $zip->addEmptyDir($localname);
25535 } else {
25536 $zip->addFile($filepath, $localname);
25537 }
25538 }
25539 if ($zip->close()) {
25540 return $target;
25541 }
25542 }
25543 $message = sprintf("Could not create archive '%s' from '%s': %s",
25544 $target,
25545 $sources,
25546 $zip->getStatusString()
25547 );
25548 throw new \RuntimeException($message);
25549 }
25550
25551
25552
25553
25554 public function supports($format, $sourceType)
25555 {
25556 return isset(static::$formats[$format]) && $this->compressionAvailable();
25557 }
25558
25559 private function compressionAvailable()
25560 {
25561 return class_exists('ZipArchive');
25562 }
25563 }
25564 <?php
25565
25566
25567
25568
25569
25570
25571
25572
25573
25574
25575
25576 namespace Composer\Package;
25577
25578 use Composer\Repository\RepositoryInterface;
25579 use Composer\Repository\PlatformRepository;
25580
25581
25582
25583
25584
25585
25586 abstract class BasePackage implements PackageInterface
25587 {
25588 public static $supportedLinkTypes = array(
25589 'require' => array('description' => 'requires', 'method' => 'requires'),
25590 'conflict' => array('description' => 'conflicts', 'method' => 'conflicts'),
25591 'provide' => array('description' => 'provides', 'method' => 'provides'),
25592 'replace' => array('description' => 'replaces', 'method' => 'replaces'),
25593 'require-dev' => array('description' => 'requires (for development)', 'method' => 'devRequires'),
25594 );
25595
25596 const STABILITY_STABLE = 0;
25597 const STABILITY_RC = 5;
25598 const STABILITY_BETA = 10;
25599 const STABILITY_ALPHA = 15;
25600 const STABILITY_DEV = 20;
25601
25602 public static $stabilities = array(
25603 'stable' => self::STABILITY_STABLE,
25604 'RC' => self::STABILITY_RC,
25605 'beta' => self::STABILITY_BETA,
25606 'alpha' => self::STABILITY_ALPHA,
25607 'dev' => self::STABILITY_DEV,
25608 );
25609
25610
25611
25612
25613
25614 public $id;
25615
25616 protected $name;
25617
25618 protected $prettyName;
25619
25620 protected $repository;
25621
25622 protected $transportOptions = array();
25623
25624
25625
25626
25627
25628
25629 public function __construct($name)
25630 {
25631 $this->prettyName = $name;
25632 $this->name = strtolower($name);
25633 $this->id = -1;
25634 }
25635
25636
25637
25638
25639 public function getName()
25640 {
25641 return $this->name;
25642 }
25643
25644
25645
25646
25647 public function getPrettyName()
25648 {
25649 return $this->prettyName;
25650 }
25651
25652
25653
25654
25655 public function getNames()
25656 {
25657 $names = array(
25658 $this->getName() => true,
25659 );
25660
25661 foreach ($this->getProvides() as $link) {
25662 $names[$link->getTarget()] = true;
25663 }
25664
25665 foreach ($this->getReplaces() as $link) {
25666 $names[$link->getTarget()] = true;
25667 }
25668
25669 return array_keys($names);
25670 }
25671
25672
25673
25674
25675 public function setId($id)
25676 {
25677 $this->id = $id;
25678 }
25679
25680
25681
25682
25683 public function getId()
25684 {
25685 return $this->id;
25686 }
25687
25688
25689
25690
25691 public function setRepository(RepositoryInterface $repository)
25692 {
25693 if ($this->repository && $repository !== $this->repository) {
25694 throw new \LogicException('A package can only be added to one repository');
25695 }
25696 $this->repository = $repository;
25697 }
25698
25699
25700
25701
25702 public function getRepository()
25703 {
25704 return $this->repository;
25705 }
25706
25707
25708
25709
25710 public function getTransportOptions()
25711 {
25712 return $this->transportOptions;
25713 }
25714
25715
25716
25717
25718
25719
25720 public function setTransportOptions(array $options)
25721 {
25722 $this->transportOptions = $options;
25723 }
25724
25725
25726
25727
25728
25729
25730 public function isPlatform()
25731 {
25732 return $this->getRepository() instanceof PlatformRepository;
25733 }
25734
25735
25736
25737
25738
25739
25740 public function getUniqueName()
25741 {
25742 return $this->getName().'-'.$this->getVersion();
25743 }
25744
25745 public function equals(PackageInterface $package)
25746 {
25747 $self = $this;
25748 if ($this instanceof AliasPackage) {
25749 $self = $this->getAliasOf();
25750 }
25751 if ($package instanceof AliasPackage) {
25752 $package = $package->getAliasOf();
25753 }
25754
25755 return $package === $self;
25756 }
25757
25758
25759
25760
25761
25762
25763 public function __toString()
25764 {
25765 return $this->getUniqueName();
25766 }
25767
25768 public function getPrettyString()
25769 {
25770 return $this->getPrettyName().' '.$this->getPrettyVersion();
25771 }
25772
25773
25774
25775
25776 public function getFullPrettyVersion($truncate = true)
25777 {
25778 if (!$this->isDev() || !in_array($this->getSourceType(), array('hg', 'git'))) {
25779 return $this->getPrettyVersion();
25780 }
25781
25782
25783  if ($truncate && strlen($this->getSourceReference()) === 40) {
25784 return $this->getPrettyVersion() . ' ' . substr($this->getSourceReference(), 0, 7);
25785 }
25786
25787 return $this->getPrettyVersion() . ' ' . $this->getSourceReference();
25788 }
25789
25790 public function getStabilityPriority()
25791 {
25792 return self::$stabilities[$this->getStability()];
25793 }
25794
25795 public function __clone()
25796 {
25797 $this->repository = null;
25798 $this->id = -1;
25799 }
25800 }
25801 <?php
25802
25803
25804
25805
25806
25807
25808
25809
25810
25811
25812
25813 namespace Composer\Package;
25814
25815
25816
25817
25818
25819
25820 class CompletePackage extends Package implements CompletePackageInterface
25821 {
25822 protected $repositories;
25823 protected $license = array();
25824 protected $keywords;
25825 protected $authors;
25826 protected $description;
25827 protected $homepage;
25828 protected $scripts = array();
25829 protected $support = array();
25830 protected $abandoned = false;
25831
25832
25833
25834
25835 public function setScripts(array $scripts)
25836 {
25837 $this->scripts = $scripts;
25838 }
25839
25840
25841
25842
25843 public function getScripts()
25844 {
25845 return $this->scripts;
25846 }
25847
25848
25849
25850
25851
25852
25853 public function setRepositories($repositories)
25854 {
25855 $this->repositories = $repositories;
25856 }
25857
25858
25859
25860
25861 public function getRepositories()
25862 {
25863 return $this->repositories;
25864 }
25865
25866
25867
25868
25869
25870
25871 public function setLicense(array $license)
25872 {
25873 $this->license = $license;
25874 }
25875
25876
25877
25878
25879 public function getLicense()
25880 {
25881 return $this->license;
25882 }
25883
25884
25885
25886
25887
25888
25889 public function setKeywords(array $keywords)
25890 {
25891 $this->keywords = $keywords;
25892 }
25893
25894
25895
25896
25897 public function getKeywords()
25898 {
25899 return $this->keywords;
25900 }
25901
25902
25903
25904
25905
25906
25907 public function setAuthors(array $authors)
25908 {
25909 $this->authors = $authors;
25910 }
25911
25912
25913
25914
25915 public function getAuthors()
25916 {
25917 return $this->authors;
25918 }
25919
25920
25921
25922
25923
25924
25925 public function setDescription($description)
25926 {
25927 $this->description = $description;
25928 }
25929
25930
25931
25932
25933 public function getDescription()
25934 {
25935 return $this->description;
25936 }
25937
25938
25939
25940
25941
25942
25943 public function setHomepage($homepage)
25944 {
25945 $this->homepage = $homepage;
25946 }
25947
25948
25949
25950
25951 public function getHomepage()
25952 {
25953 return $this->homepage;
25954 }
25955
25956
25957
25958
25959
25960
25961 public function setSupport(array $support)
25962 {
25963 $this->support = $support;
25964 }
25965
25966
25967
25968
25969 public function getSupport()
25970 {
25971 return $this->support;
25972 }
25973
25974
25975
25976
25977 public function isAbandoned()
25978 {
25979 return (bool) $this->abandoned;
25980 }
25981
25982
25983
25984
25985 public function setAbandoned($abandoned)
25986 {
25987 $this->abandoned = $abandoned;
25988 }
25989
25990
25991
25992
25993
25994
25995 public function getReplacementPackage()
25996 {
25997 return is_string($this->abandoned) ? $this->abandoned : null;
25998 }
25999 }
26000 <?php
26001
26002
26003
26004
26005
26006
26007
26008
26009
26010
26011
26012 namespace Composer\Package;
26013
26014
26015
26016
26017
26018
26019 interface CompletePackageInterface extends PackageInterface
26020 {
26021
26022
26023
26024
26025
26026 public function getScripts();
26027
26028
26029
26030
26031
26032
26033
26034
26035 public function getRepositories();
26036
26037
26038
26039
26040
26041
26042 public function getLicense();
26043
26044
26045
26046
26047
26048
26049 public function getKeywords();
26050
26051
26052
26053
26054
26055
26056 public function getDescription();
26057
26058
26059
26060
26061
26062
26063 public function getHomepage();
26064
26065
26066
26067
26068
26069
26070
26071
26072 public function getAuthors();
26073
26074
26075
26076
26077
26078
26079 public function getSupport();
26080
26081
26082
26083
26084
26085
26086 public function isAbandoned();
26087
26088
26089
26090
26091
26092
26093 public function getReplacementPackage();
26094 }
26095 <?php
26096
26097
26098
26099
26100
26101
26102
26103
26104
26105
26106
26107 namespace Composer\Package\Dumper;
26108
26109 use Composer\Package\BasePackage;
26110 use Composer\Package\PackageInterface;
26111 use Composer\Package\CompletePackageInterface;
26112 use Composer\Package\RootPackageInterface;
26113
26114
26115
26116
26117
26118 class ArrayDumper
26119 {
26120 public function dump(PackageInterface $package)
26121 {
26122 $keys = array(
26123 'binaries' => 'bin',
26124 'type',
26125 'extra',
26126 'installationSource' => 'installation-source',
26127 'autoload',
26128 'devAutoload' => 'autoload-dev',
26129 'notificationUrl' => 'notification-url',
26130 'includePaths' => 'include-path',
26131 );
26132
26133 $data = array();
26134 $data['name'] = $package->getPrettyName();
26135 $data['version'] = $package->getPrettyVersion();
26136 $data['version_normalized'] = $package->getVersion();
26137
26138 if ($package->getTargetDir()) {
26139 $data['target-dir'] = $package->getTargetDir();
26140 }
26141
26142 if ($package->getSourceType()) {
26143 $data['source']['type'] = $package->getSourceType();
26144 $data['source']['url'] = $package->getSourceUrl();
26145 $data['source']['reference'] = $package->getSourceReference();
26146 if ($mirrors = $package->getSourceMirrors()) {
26147 $data['source']['mirrors'] = $mirrors;
26148 }
26149 }
26150
26151 if ($package->getDistType()) {
26152 $data['dist']['type'] = $package->getDistType();
26153 $data['dist']['url'] = $package->getDistUrl();
26154 $data['dist']['reference'] = $package->getDistReference();
26155 $data['dist']['shasum'] = $package->getDistSha1Checksum();
26156 if ($mirrors = $package->getDistMirrors()) {
26157 $data['dist']['mirrors'] = $mirrors;
26158 }
26159 }
26160
26161 if ($package->getArchiveExcludes()) {
26162 $data['archive']['exclude'] = $package->getArchiveExcludes();
26163 }
26164
26165 foreach (BasePackage::$supportedLinkTypes as $type => $opts) {
26166 if ($links = $package->{'get'.ucfirst($opts['method'])}()) {
26167 foreach ($links as $link) {
26168 $data[$type][$link->getTarget()] = $link->getPrettyConstraint();
26169 }
26170 ksort($data[$type]);
26171 }
26172 }
26173
26174 if ($packages = $package->getSuggests()) {
26175 ksort($packages);
26176 $data['suggest'] = $packages;
26177 }
26178
26179 if ($package->getReleaseDate()) {
26180 $data['time'] = $package->getReleaseDate()->format(DATE_RFC3339);
26181 }
26182
26183 $data = $this->dumpValues($package, $keys, $data);
26184
26185 if ($package instanceof CompletePackageInterface) {
26186 $keys = array(
26187 'scripts',
26188 'license',
26189 'authors',
26190 'description',
26191 'homepage',
26192 'keywords',
26193 'repositories',
26194 'support',
26195 );
26196
26197 $data = $this->dumpValues($package, $keys, $data);
26198
26199 if (isset($data['keywords']) && is_array($data['keywords'])) {
26200 sort($data['keywords']);
26201 }
26202
26203 if ($package->isAbandoned()) {
26204 $data['abandoned'] = $package->getReplacementPackage() ?: true;
26205 }
26206 }
26207
26208 if ($package instanceof RootPackageInterface) {
26209 $minimumStability = $package->getMinimumStability();
26210 if ($minimumStability) {
26211 $data['minimum-stability'] = $minimumStability;
26212 }
26213 }
26214
26215 if (count($package->getTransportOptions()) > 0) {
26216 $data['transport-options'] = $package->getTransportOptions();
26217 }
26218
26219 return $data;
26220 }
26221
26222 private function dumpValues(PackageInterface $package, array $keys, array $data)
26223 {
26224 foreach ($keys as $method => $key) {
26225 if (is_numeric($method)) {
26226 $method = $key;
26227 }
26228
26229 $getter = 'get'.ucfirst($method);
26230 $value = $package->$getter();
26231
26232 if (null !== $value && !(is_array($value) && 0 === count($value))) {
26233 $data[$key] = $value;
26234 }
26235 }
26236
26237 return $data;
26238 }
26239 }
26240 <?php
26241
26242
26243
26244
26245
26246
26247
26248
26249
26250
26251
26252 namespace Composer\Package;
26253
26254 use Composer\Semver\Constraint\ConstraintInterface;
26255
26256
26257
26258
26259
26260
26261 class Link
26262 {
26263
26264
26265
26266 protected $source;
26267
26268
26269
26270
26271 protected $target;
26272
26273
26274
26275
26276 protected $constraint;
26277
26278
26279
26280
26281 protected $description;
26282
26283
26284
26285
26286 protected $prettyConstraint;
26287
26288
26289
26290
26291
26292
26293
26294
26295
26296
26297 public function __construct($source, $target, ConstraintInterface $constraint = null, $description = 'relates to', $prettyConstraint = null)
26298 {
26299 $this->source = strtolower($source);
26300 $this->target = strtolower($target);
26301 $this->constraint = $constraint;
26302 $this->description = $description;
26303 $this->prettyConstraint = $prettyConstraint;
26304 }
26305
26306
26307
26308
26309 public function getDescription()
26310 {
26311 return $this->description;
26312 }
26313
26314
26315
26316
26317 public function getSource()
26318 {
26319 return $this->source;
26320 }
26321
26322
26323
26324
26325 public function getTarget()
26326 {
26327 return $this->target;
26328 }
26329
26330
26331
26332
26333 public function getConstraint()
26334 {
26335 return $this->constraint;
26336 }
26337
26338
26339
26340
26341
26342 public function getPrettyConstraint()
26343 {
26344 if (null === $this->prettyConstraint) {
26345 throw new \UnexpectedValueException(sprintf('Link %s has been misconfigured and had no prettyConstraint given.', $this));
26346 }
26347
26348 return $this->prettyConstraint;
26349 }
26350
26351
26352
26353
26354 public function __toString()
26355 {
26356 return $this->source.' '.$this->description.' '.$this->target.' ('.$this->constraint.')';
26357 }
26358
26359
26360
26361
26362
26363 public function getPrettyString(PackageInterface $sourcePackage)
26364 {
26365 return $sourcePackage->getPrettyString().' '.$this->description.' '.$this->target.' '.$this->constraint->getPrettyString().'';
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\EmptyConstraint as SemverEmptyConstraint;
26383
26384 trigger_error('The ' . __NAMESPACE__ . '\EmptyConstraint class is deprecated, use Composer\Semver\Constraint\EmptyConstraint instead.', E_USER_DEPRECATED);
26385
26386
26387
26388
26389 class EmptyConstraint extends SemverEmptyConstraint implements LinkConstraintInterface
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\ConstraintInterface;
26407
26408 trigger_error('The ' . __NAMESPACE__ . '\LinkConstraintInterface interface is deprecated, use Composer\Semver\Constraint\ConstraintInterface instead.', E_USER_DEPRECATED);
26409
26410
26411
26412
26413 interface LinkConstraintInterface extends ConstraintInterface
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\MultiConstraint as SemverMultiConstraint;
26431
26432 trigger_error('The ' . __NAMESPACE__ . '\MultiConstraint class is deprecated, use Composer\Semver\Constraint\MultiConstraint instead.', E_USER_DEPRECATED);
26433
26434
26435
26436
26437 class MultiConstraint extends SemverMultiConstraint 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\AbstractConstraint;
26455
26456 trigger_error('The ' . __NAMESPACE__ . '\SpecificConstraint abstract class is deprecated, there is no replacement for it.', E_USER_DEPRECATED);
26457
26458
26459
26460
26461 abstract class SpecificConstraint extends AbstractConstraint implements LinkConstraintInterface
26462 {
26463 }
26464 <?php
26465
26466
26467
26468
26469
26470
26471
26472
26473
26474
26475
26476 namespace Composer\Package\LinkConstraint;
26477
26478 use Composer\Semver\Constraint\Constraint;
26479
26480 trigger_error('The ' . __NAMESPACE__ . '\VersionConstraint class is deprecated, use Composer\Semver\Constraint\Constraint instead.', E_USER_DEPRECATED);
26481
26482
26483
26484
26485 class VersionConstraint extends Constraint implements LinkConstraintInterface
26486 {
26487 }
26488 <?php
26489
26490
26491
26492
26493
26494
26495
26496
26497
26498
26499
26500 namespace Composer\Package\Loader;
26501
26502 use Composer\Package;
26503 use Composer\Package\AliasPackage;
26504 use Composer\Package\Link;
26505 use Composer\Package\RootAliasPackage;
26506 use Composer\Package\RootPackageInterface;
26507 use Composer\Package\Version\VersionParser;
26508 use Composer\Semver\VersionParser as SemverVersionParser;
26509
26510
26511
26512
26513
26514 class ArrayLoader implements LoaderInterface
26515 {
26516 protected $versionParser;
26517 protected $loadOptions;
26518
26519 public function __construct(SemverVersionParser $parser = null, $loadOptions = false)
26520 {
26521 if (!$parser) {
26522 $parser = new VersionParser;
26523 }
26524 $this->versionParser = $parser;
26525 $this->loadOptions = $loadOptions;
26526 }
26527
26528 public function load(array $config, $class = 'Composer\Package\CompletePackage')
26529 {
26530 if (!isset($config['name'])) {
26531 throw new \UnexpectedValueException('Unknown package has no name defined ('.json_encode($config).').');
26532 }
26533 if (!isset($config['version'])) {
26534 throw new \UnexpectedValueException('Package '.$config['name'].' has no version defined.');
26535 }
26536
26537
26538  if (isset($config['version_normalized'])) {
26539 $version = $config['version_normalized'];
26540 } else {
26541 $version = $this->versionParser->normalize($config['version']);
26542 }
26543 $package = new $class($config['name'], $version, $config['version']);
26544 $package->setType(isset($config['type']) ? strtolower($config['type']) : 'library');
26545
26546 if (isset($config['target-dir'])) {
26547 $package->setTargetDir($config['target-dir']);
26548 }
26549
26550 if (isset($config['extra']) && is_array($config['extra'])) {
26551 $package->setExtra($config['extra']);
26552 }
26553
26554 if (isset($config['bin'])) {
26555 if (!is_array($config['bin'])) {
26556 throw new \UnexpectedValueException('Package '.$config['name'].'\'s bin key should be an array, '.gettype($config['bin']).' given.');
26557 }
26558 foreach ($config['bin'] as $key => $bin) {
26559 $config['bin'][$key] = ltrim($bin, '/');
26560 }
26561 $package->setBinaries($config['bin']);
26562 }
26563
26564 if (isset($config['installation-source'])) {
26565 $package->setInstallationSource($config['installation-source']);
26566 }
26567
26568 if (isset($config['source'])) {
26569 if (!isset($config['source']['type']) || !isset($config['source']['url']) || !isset($config['source']['reference'])) {
26570 throw new \UnexpectedValueException(sprintf(
26571 "Package %s's source key should be specified as {\"type\": ..., \"url\": ..., \"reference\": ...},\n%s given.",
26572 $config['name'],
26573 json_encode($config['source'])
26574 ));
26575 }
26576 $package->setSourceType($config['source']['type']);
26577 $package->setSourceUrl($config['source']['url']);
26578 $package->setSourceReference($config['source']['reference']);
26579 if (isset($config['source']['mirrors'])) {
26580 $package->setSourceMirrors($config['source']['mirrors']);
26581 }
26582 }
26583
26584 if (isset($config['dist'])) {
26585 if (!isset($config['dist']['type'])
26586 || !isset($config['dist']['url'])) {
26587 throw new \UnexpectedValueException(sprintf(
26588 "Package %s's dist key should be specified as ".
26589 "{\"type\": ..., \"url\": ..., \"reference\": ..., \"shasum\": ...},\n%s given.",
26590 $config['name'],
26591 json_encode($config['dist'])
26592 ));
26593 }
26594 $package->setDistType($config['dist']['type']);
26595 $package->setDistUrl($config['dist']['url']);
26596 $package->setDistReference(isset($config['dist']['reference']) ? $config['dist']['reference'] : null);
26597 $package->setDistSha1Checksum(isset($config['dist']['shasum']) ? $config['dist']['shasum'] : null);
26598 if (isset($config['dist']['mirrors'])) {
26599 $package->setDistMirrors($config['dist']['mirrors']);
26600 }
26601 }
26602
26603 foreach (Package\BasePackage::$supportedLinkTypes as $type => $opts) {
26604 if (isset($config[$type])) {
26605 $method = 'set'.ucfirst($opts['method']);
26606 $package->{$method}(
26607 $this->parseLinks(
26608 $package->getName(),
26609 $package->getPrettyVersion(),
26610 $opts['description'],
26611 $config[$type]
26612 )
26613 );
26614 }
26615 }
26616
26617 if (isset($config['suggest']) && is_array($config['suggest'])) {
26618 foreach ($config['suggest'] as $target => $reason) {
26619 if ('self.version' === trim($reason)) {
26620 $config['suggest'][$target] = $package->getPrettyVersion();
26621 }
26622 }
26623 $package->setSuggests($config['suggest']);
26624 }
26625
26626 if (isset($config['autoload'])) {
26627 $package->setAutoload($config['autoload']);
26628 }
26629
26630 if (isset($config['autoload-dev'])) {
26631 $package->setDevAutoload($config['autoload-dev']);
26632 }
26633
26634 if (isset($config['include-path'])) {
26635 $package->setIncludePaths($config['include-path']);
26636 }
26637
26638 if (!empty($config['time'])) {
26639 $time = preg_match('/^\d++$/D', $config['time']) ? '@'.$config['time'] : $config['time'];
26640
26641 try {
26642 $date = new \DateTime($time, new \DateTimeZone('UTC'));
26643 $package->setReleaseDate($date);
26644 } catch (\Exception $e) {
26645 }
26646 }
26647
26648 if (!empty($config['notification-url'])) {
26649 $package->setNotificationUrl($config['notification-url']);
26650 }
26651
26652 if (!empty($config['archive']['exclude'])) {
26653 $package->setArchiveExcludes($config['archive']['exclude']);
26654 }
26655
26656 if ($package instanceof Package\CompletePackageInterface) {
26657 if (isset($config['scripts']) && is_array($config['scripts'])) {
26658 foreach ($config['scripts'] as $event => $listeners) {
26659 $config['scripts'][$event] = (array) $listeners;
26660 }
26661 if (isset($config['scripts']['composer'])) {
26662 trigger_error('The `composer` script name is reserved for internal use, please avoid defining it', E_USER_DEPRECATED);
26663 }
26664 $package->setScripts($config['scripts']);
26665 }
26666
26667 if (!empty($config['description']) && is_string($config['description'])) {
26668 $package->setDescription($config['description']);
26669 }
26670
26671 if (!empty($config['homepage']) && is_string($config['homepage'])) {
26672 $package->setHomepage($config['homepage']);
26673 }
26674
26675 if (!empty($config['keywords']) && is_array($config['keywords'])) {
26676 $package->setKeywords($config['keywords']);
26677 }
26678
26679 if (!empty($config['license'])) {
26680 $package->setLicense(is_array($config['license']) ? $config['license'] : array($config['license']));
26681 }
26682
26683 if (!empty($config['authors']) && is_array($config['authors'])) {
26684 $package->setAuthors($config['authors']);
26685 }
26686
26687 if (isset($config['support'])) {
26688 $package->setSupport($config['support']);
26689 }
26690
26691 if (isset($config['abandoned'])) {
26692 $package->setAbandoned($config['abandoned']);
26693 }
26694 }
26695
26696 if ($aliasNormalized = $this->getBranchAlias($config)) {
26697 if ($package instanceof RootPackageInterface) {
26698 $package = new RootAliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
26699 } else {
26700 $package = new AliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
26701 }
26702 }
26703
26704 if ($this->loadOptions && isset($config['transport-options'])) {
26705 $package->setTransportOptions($config['transport-options']);
26706 }
26707
26708 return $package;
26709 }
26710
26711
26712
26713
26714
26715
26716
26717
26718 public function parseLinks($source, $sourceVersion, $description, $links)
26719 {
26720 $res = array();
26721 foreach ($links as $target => $constraint) {
26722 if (!is_string($constraint)) {
26723 throw new \UnexpectedValueException('Link constraint in '.$source.' '.$description.' > '.$target.' should be a string, got '.gettype($constraint) . ' (' . var_export($constraint, true) . ')');
26724 }
26725 if ('self.version' === $constraint) {
26726 $parsedConstraint = $this->versionParser->parseConstraints($sourceVersion);
26727 } else {
26728 $parsedConstraint = $this->versionParser->parseConstraints($constraint);
26729 }
26730
26731 $res[strtolower($target)] = new Link($source, $target, $parsedConstraint, $description, $constraint);
26732 }
26733
26734 return $res;
26735 }
26736
26737
26738
26739
26740
26741
26742
26743 public function getBranchAlias(array $config)
26744 {
26745 if (('dev-' !== substr($config['version'], 0, 4) && '-dev' !== substr($config['version'], -4))
26746 || !isset($config['extra']['branch-alias'])
26747 || !is_array($config['extra']['branch-alias'])
26748 ) {
26749 return;
26750 }
26751
26752 foreach ($config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
26753
26754  if ('-dev' !== substr($targetBranch, -4)) {
26755 continue;
26756 }
26757
26758
26759  $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
26760 if ('-dev' !== substr($validatedTargetBranch, -4)) {
26761 continue;
26762 }
26763
26764
26765  if (strtolower($config['version']) !== strtolower($sourceBranch)) {
26766 continue;
26767 }
26768
26769
26770  if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
26771 && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
26772 && (stripos($targetPrefix, $sourcePrefix) !== 0)
26773 ) {
26774 continue;
26775 }
26776
26777 return $validatedTargetBranch;
26778 }
26779 }
26780 }
26781 <?php
26782
26783
26784
26785
26786
26787
26788
26789
26790
26791
26792
26793 namespace Composer\Package\Loader;
26794
26795
26796
26797
26798 class InvalidPackageException extends \Exception
26799 {
26800 private $errors;
26801 private $warnings;
26802 private $data;
26803
26804 public function __construct(array $errors, array $warnings, array $data)
26805 {
26806 $this->errors = $errors;
26807 $this->warnings = $warnings;
26808 $this->data = $data;
26809 parent::__construct("Invalid package information: \n".implode("\n", array_merge($errors, $warnings)));
26810 }
26811
26812 public function getData()
26813 {
26814 return $this->data;
26815 }
26816
26817 public function getErrors()
26818 {
26819 return $this->errors;
26820 }
26821
26822 public function getWarnings()
26823 {
26824 return $this->warnings;
26825 }
26826 }
26827 <?php
26828
26829
26830
26831
26832
26833
26834
26835
26836
26837
26838
26839 namespace Composer\Package\Loader;
26840
26841 use Composer\Json\JsonFile;
26842
26843
26844
26845
26846 class JsonLoader
26847 {
26848 private $loader;
26849
26850 public function __construct(LoaderInterface $loader)
26851 {
26852 $this->loader = $loader;
26853 }
26854
26855
26856
26857
26858
26859 public function load($json)
26860 {
26861 if ($json instanceof JsonFile) {
26862 $config = $json->read();
26863 } elseif (file_exists($json)) {
26864 $config = JsonFile::parseJson(file_get_contents($json), $json);
26865 } elseif (is_string($json)) {
26866 $config = JsonFile::parseJson($json);
26867 }
26868
26869 return $this->loader->load($config);
26870 }
26871 }
26872 <?php
26873
26874
26875
26876
26877
26878
26879
26880
26881
26882
26883
26884 namespace Composer\Package\Loader;
26885
26886
26887
26888
26889
26890
26891 interface LoaderInterface
26892 {
26893
26894
26895
26896
26897
26898
26899
26900 public function load(array $package, $class = 'Composer\Package\CompletePackage');
26901 }
26902 <?php
26903
26904
26905
26906
26907
26908
26909
26910
26911
26912
26913
26914 namespace Composer\Package\Loader;
26915
26916 use Composer\Package\BasePackage;
26917 use Composer\Package\AliasPackage;
26918 use Composer\Config;
26919 use Composer\Package\RootPackageInterface;
26920 use Composer\Repository\RepositoryFactory;
26921 use Composer\Package\Version\VersionGuesser;
26922 use Composer\Package\Version\VersionParser;
26923 use Composer\Repository\RepositoryManager;
26924 use Composer\Util\ProcessExecutor;
26925
26926
26927
26928
26929
26930
26931
26932
26933 class RootPackageLoader extends ArrayLoader
26934 {
26935
26936
26937
26938 private $manager;
26939
26940
26941
26942
26943 private $config;
26944
26945
26946
26947
26948 private $versionGuesser;
26949
26950 public function __construct(RepositoryManager $manager, Config $config, VersionParser $parser = null, VersionGuesser $versionGuesser = null)
26951 {
26952 parent::__construct($parser);
26953
26954 $this->manager = $manager;
26955 $this->config = $config;
26956 $this->versionGuesser = $versionGuesser ?: new VersionGuesser($config, new ProcessExecutor(), $this->versionParser);
26957 }
26958
26959
26960
26961
26962
26963
26964
26965 public function load(array $config, $class = 'Composer\Package\RootPackage', $cwd = null)
26966 {
26967 if (!isset($config['name'])) {
26968 $config['name'] = '__root__';
26969 }
26970 $autoVersioned = false;
26971 if (!isset($config['version'])) {
26972 $commit = null;
26973
26974
26975  if (getenv('COMPOSER_ROOT_VERSION')) {
26976 $config['version'] = getenv('COMPOSER_ROOT_VERSION');
26977 } else {
26978 $versionData = $this->versionGuesser->guessVersion($config, $cwd ?: getcwd());
26979 if ($versionData) {
26980 $config['version'] = $versionData['pretty_version'];
26981 $config['version_normalized'] = $versionData['version'];
26982 $commit = $versionData['commit'];
26983 }
26984 }
26985
26986 if (!isset($config['version'])) {
26987 $config['version'] = '1.0.0';
26988 $autoVersioned = true;
26989 }
26990
26991 if ($commit) {
26992 $config['source'] = array(
26993 'type' => '',
26994 'url' => '',
26995 'reference' => $commit,
26996 );
26997 $config['dist'] = array(
26998 'type' => '',
26999 'url' => '',
27000 'reference' => $commit,
27001 );
27002 }
27003 }
27004
27005 $realPackage = $package = parent::load($config, $class);
27006 if ($realPackage instanceof AliasPackage) {
27007 $realPackage = $package->getAliasOf();
27008 }
27009
27010 if ($autoVersioned) {
27011 $realPackage->replaceVersion($realPackage->getVersion(), 'No version set (parsed as 1.0.0)');
27012 }
27013
27014 if (isset($config['minimum-stability'])) {
27015 $realPackage->setMinimumStability(VersionParser::normalizeStability($config['minimum-stability']));
27016 }
27017
27018 $aliases = array();
27019 $stabilityFlags = array();
27020 $references = array();
27021 foreach (array('require', 'require-dev') as $linkType) {
27022 if (isset($config[$linkType])) {
27023 $linkInfo = BasePackage::$supportedLinkTypes[$linkType];
27024 $method = 'get'.ucfirst($linkInfo['method']);
27025 $links = array();
27026 foreach ($realPackage->$method() as $link) {
27027 $links[$link->getTarget()] = $link->getConstraint()->getPrettyString();
27028 }
27029 $aliases = $this->extractAliases($links, $aliases);
27030 $stabilityFlags = $this->extractStabilityFlags($links, $stabilityFlags, $realPackage->getMinimumStability());
27031 $references = $this->extractReferences($links, $references);
27032 }
27033 }
27034
27035 if (isset($links[$config['name']])) {
27036 throw new \InvalidArgumentException(sprintf('Root package \'%s\' cannot require itself in its composer.json' . PHP_EOL .
27037 'Did you accidentally name your root package after an external package?', $config['name']));
27038 }
27039
27040 $realPackage->setAliases($aliases);
27041 $realPackage->setStabilityFlags($stabilityFlags);
27042 $realPackage->setReferences($references);
27043
27044 if (isset($config['prefer-stable'])) {
27045 $realPackage->setPreferStable((bool) $config['prefer-stable']);
27046 }
27047
27048 if (isset($config['config'])) {
27049 $realPackage->setConfig($config['config']);
27050 }
27051
27052 $repos = RepositoryFactory::defaultRepos(null, $this->config, $this->manager);
27053 foreach ($repos as $repo) {
27054 $this->manager->addRepository($repo);
27055 }
27056 $realPackage->setRepositories($this->config->getRepositories());
27057
27058 return $package;
27059 }
27060
27061 private function extractAliases(array $requires, array $aliases)
27062 {
27063 foreach ($requires as $reqName => $reqVersion) {
27064 if (preg_match('{^([^,\s#]+)(?:#[^ ]+)? +as +([^,\s]+)$}', $reqVersion, $match)) {
27065 $aliases[] = array(
27066 'package' => strtolower($reqName),
27067 'version' => $this->versionParser->normalize($match[1], $reqVersion),
27068 'alias' => $match[2],
27069 'alias_normalized' => $this->versionParser->normalize($match[2], $reqVersion),
27070 );
27071 }
27072 }
27073
27074 return $aliases;
27075 }
27076
27077 private function extractStabilityFlags(array $requires, array $stabilityFlags, $minimumStability)
27078 {
27079 $stabilities = BasePackage::$stabilities;
27080 $minimumStability = $stabilities[$minimumStability];
27081 foreach ($requires as $reqName => $reqVersion) {
27082 $constraints = array();
27083
27084
27085  $orSplit = preg_split('{\s*\|\|?\s*}', trim($reqVersion));
27086 foreach ($orSplit as $orConstraint) {
27087 $andSplit = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $orConstraint);
27088 foreach ($andSplit as $andConstraint) {
27089 $constraints[] = $andConstraint;
27090 }
27091 }
27092
27093
27094  $match = false;
27095 foreach ($constraints as $constraint) {
27096 if (preg_match('{^[^@]*?@('.implode('|', array_keys($stabilities)).')$}i', $constraint, $match)) {
27097 $name = strtolower($reqName);
27098 $stability = $stabilities[VersionParser::normalizeStability($match[1])];
27099
27100 if (isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) {
27101 continue;
27102 }
27103 $stabilityFlags[$name] = $stability;
27104 $match = true;
27105 }
27106 }
27107
27108 if ($match) {
27109 continue;
27110 }
27111
27112 foreach ($constraints as $constraint) {
27113
27114  
27115  $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $constraint);
27116 if (preg_match('{^[^,\s@]+$}', $reqVersion) && 'stable' !== ($stabilityName = VersionParser::parseStability($reqVersion))) {
27117 $name = strtolower($reqName);
27118 $stability = $stabilities[$stabilityName];
27119 if ((isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) || ($minimumStability > $stability)) {
27120 continue;
27121 }
27122 $stabilityFlags[$name] = $stability;
27123 }
27124 }
27125 }
27126
27127 return $stabilityFlags;
27128 }
27129
27130 private function extractReferences(array $requires, array $references)
27131 {
27132 foreach ($requires as $reqName => $reqVersion) {
27133 $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $reqVersion);
27134 if (preg_match('{^[^,\s@]+?#([a-f0-9]+)$}', $reqVersion, $match) && 'dev' === ($stabilityName = VersionParser::parseStability($reqVersion))) {
27135 $name = strtolower($reqName);
27136 $references[$name] = $match[1];
27137 }
27138 }
27139
27140 return $references;
27141 }
27142 }
27143 <?php
27144
27145
27146
27147
27148
27149
27150
27151
27152
27153
27154
27155 namespace Composer\Package\Loader;
27156
27157 use Composer\Package;
27158 use Composer\Package\BasePackage;
27159 use Composer\Semver\Constraint\Constraint;
27160 use Composer\Package\Version\VersionParser;
27161 use Composer\Repository\PlatformRepository;
27162
27163
27164
27165
27166 class ValidatingArrayLoader implements LoaderInterface
27167 {
27168 const CHECK_ALL = 3;
27169 const CHECK_UNBOUND_CONSTRAINTS = 1;
27170 const CHECK_STRICT_CONSTRAINTS = 2;
27171
27172 private $loader;
27173 private $versionParser;
27174 private $errors;
27175 private $warnings;
27176 private $config;
27177 private $strictName;
27178 private $flags;
27179
27180 public function __construct(LoaderInterface $loader, $strictName = true, VersionParser $parser = null, $flags = 0)
27181 {
27182 $this->loader = $loader;
27183 $this->versionParser = $parser ?: new VersionParser();
27184 $this->strictName = $strictName;
27185 $this->flags = $flags;
27186 }
27187
27188 public function load(array $config, $class = 'Composer\Package\CompletePackage')
27189 {
27190 $this->errors = array();
27191 $this->warnings = array();
27192 $this->config = $config;
27193
27194 if ($this->strictName) {
27195 $this->validateRegex('name', '[A-Za-z0-9][A-Za-z0-9_.-]*/[A-Za-z0-9][A-Za-z0-9_.-]*', true);
27196 } else {
27197 $this->validateString('name', true);
27198 }
27199
27200 if (!empty($this->config['version'])) {
27201 try {
27202 $this->versionParser->normalize($this->config['version']);
27203 } catch (\Exception $e) {
27204 $this->errors[] = 'version : invalid value ('.$this->config['version'].'): '.$e->getMessage();
27205 unset($this->config['version']);
27206 }
27207 }
27208
27209 if (!empty($this->config['config']['platform'])) {
27210 foreach ((array) $this->config['config']['platform'] as $key => $platform) {
27211 try {
27212 $this->versionParser->normalize($platform);
27213 } catch (\Exception $e) {
27214 $this->errors[] = 'config.platform.' . $key . ' : invalid value ('.$platform.'): '.$e->getMessage();
27215 }
27216 }
27217 }
27218
27219 $this->validateRegex('type', '[A-Za-z0-9-]+');
27220 $this->validateString('target-dir');
27221 $this->validateArray('extra');
27222 $this->validateFlatArray('bin');
27223 $this->validateArray('scripts'); 
27224  $this->validateString('description');
27225 $this->validateUrl('homepage');
27226 $this->validateFlatArray('keywords', '[\p{N}\p{L} ._-]+');
27227
27228 if (isset($this->config['license'])) {
27229 if (is_string($this->config['license'])) {
27230 $this->validateRegex('license', '[A-Za-z0-9+. ()-]+');
27231 } else {
27232 $this->validateFlatArray('license', '[A-Za-z0-9+. ()-]+');
27233 }
27234 }
27235
27236 $this->validateString('time');
27237 if (!empty($this->config['time'])) {
27238 try {
27239 $date = new \DateTime($this->config['time'], new \DateTimeZone('UTC'));
27240 } catch (\Exception $e) {
27241 $this->errors[] = 'time : invalid value ('.$this->config['time'].'): '.$e->getMessage();
27242 unset($this->config['time']);
27243 }
27244 }
27245
27246 if ($this->validateArray('authors') && !empty($this->config['authors'])) {
27247 foreach ($this->config['authors'] as $key => $author) {
27248 if (!is_array($author)) {
27249 $this->errors[] = 'authors.'.$key.' : should be an array, '.gettype($author).' given';
27250 unset($this->config['authors'][$key]);
27251 continue;
27252 }
27253 foreach (array('homepage', 'email', 'name', 'role') as $authorData) {
27254 if (isset($author[$authorData]) && !is_string($author[$authorData])) {
27255 $this->errors[] = 'authors.'.$key.'.'.$authorData.' : invalid value, must be a string';
27256 unset($this->config['authors'][$key][$authorData]);
27257 }
27258 }
27259 if (isset($author['homepage']) && !$this->filterUrl($author['homepage'])) {
27260 $this->warnings[] = 'authors.'.$key.'.homepage : invalid value ('.$author['homepage'].'), must be an http/https URL';
27261 unset($this->config['authors'][$key]['homepage']);
27262 }
27263 if (isset($author['email']) && !filter_var($author['email'], FILTER_VALIDATE_EMAIL)) {
27264 $this->warnings[] = 'authors.'.$key.'.email : invalid value ('.$author['email'].'), must be a valid email address';
27265 unset($this->config['authors'][$key]['email']);
27266 }
27267 if (empty($this->config['authors'][$key])) {
27268 unset($this->config['authors'][$key]);
27269 }
27270 }
27271 if (empty($this->config['authors'])) {
27272 unset($this->config['authors']);
27273 }
27274 }
27275
27276 if ($this->validateArray('support') && !empty($this->config['support'])) {
27277 foreach (array('issues', 'forum', 'wiki', 'source', 'email', 'irc', 'docs', 'rss') as $key) {
27278 if (isset($this->config['support'][$key]) && !is_string($this->config['support'][$key])) {
27279 $this->errors[] = 'support.'.$key.' : invalid value, must be a string';
27280 unset($this->config['support'][$key]);
27281 }
27282 }
27283
27284 if (isset($this->config['support']['email']) && !filter_var($this->config['support']['email'], FILTER_VALIDATE_EMAIL)) {
27285 $this->warnings[] = 'support.email : invalid value ('.$this->config['support']['email'].'), must be a valid email address';
27286 unset($this->config['support']['email']);
27287 }
27288
27289 if (isset($this->config['support']['irc']) && !$this->filterUrl($this->config['support']['irc'], array('irc'))) {
27290 $this->warnings[] = 'support.irc : invalid value ('.$this->config['support']['irc'].'), must be a irc://<server>/<channel> URL';
27291 unset($this->config['support']['irc']);
27292 }
27293
27294 foreach (array('issues', 'forum', 'wiki', 'source', 'docs') as $key) {
27295 if (isset($this->config['support'][$key]) && !$this->filterUrl($this->config['support'][$key])) {
27296 $this->warnings[] = 'support.'.$key.' : invalid value ('.$this->config['support'][$key].'), must be an http/https URL';
27297 unset($this->config['support'][$key]);
27298 }
27299 }
27300 if (empty($this->config['support'])) {
27301 unset($this->config['support']);
27302 }
27303 }
27304
27305 $unboundConstraint = new Constraint('=', $this->versionParser->normalize('dev-master'));
27306 $stableConstraint = new Constraint('=', '1.0.0');
27307
27308 foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
27309 if ($this->validateArray($linkType) && isset($this->config[$linkType])) {
27310 foreach ($this->config[$linkType] as $package => $constraint) {
27311 if (!preg_match('{^[A-Za-z0-9_./-]+$}', $package)) {
27312 $this->warnings[] = $linkType.'.'.$package.' : invalid key, package names must be strings containing only [A-Za-z0-9_./-]';
27313 }
27314 if (!is_string($constraint)) {
27315 $this->errors[] = $linkType.'.'.$package.' : invalid value, must be a string containing a version constraint';
27316 unset($this->config[$linkType][$package]);
27317 } elseif ('self.version' !== $constraint) {
27318 try {
27319 $linkConstraint = $this->versionParser->parseConstraints($constraint);
27320 } catch (\Exception $e) {
27321 $this->errors[] = $linkType.'.'.$package.' : invalid version constraint ('.$e->getMessage().')';
27322 unset($this->config[$linkType][$package]);
27323 continue;
27324 }
27325
27326
27327  if (
27328 ($this->flags & self::CHECK_UNBOUND_CONSTRAINTS)
27329 && 'require' === $linkType
27330 && $linkConstraint->matches($unboundConstraint)
27331 && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $package)
27332 ) {
27333 $this->warnings[] = $linkType.'.'.$package.' : unbound version constraints ('.$constraint.') should be avoided';
27334 } elseif (
27335
27336  ($this->flags & self::CHECK_STRICT_CONSTRAINTS)
27337 && 'require' === $linkType
27338 && substr($linkConstraint, 0, 1) === '='
27339 && $stableConstraint->versionCompare($stableConstraint, $linkConstraint, '<=')
27340 ) {
27341 $this->warnings[] = $linkType.'.'.$package.' : exact version constraints ('.$constraint.') should be avoided if the package follows semantic versioning';
27342 }
27343 }
27344 }
27345 }
27346 }
27347
27348 if ($this->validateArray('suggest') && !empty($this->config['suggest'])) {
27349 foreach ($this->config['suggest'] as $package => $description) {
27350 if (!is_string($description)) {
27351 $this->errors[] = 'suggest.'.$package.' : invalid value, must be a string describing why the package is suggested';
27352 unset($this->config['suggest'][$package]);
27353 }
27354 }
27355 }
27356
27357 if ($this->validateString('minimum-stability') && !empty($this->config['minimum-stability'])) {
27358 if (!isset(BasePackage::$stabilities[$this->config['minimum-stability']])) {
27359 $this->errors[] = 'minimum-stability : invalid value ('.$this->config['minimum-stability'].'), must be one of '.implode(', ', array_keys(BasePackage::$stabilities));
27360 unset($this->config['minimum-stability']);
27361 }
27362 }
27363
27364 if ($this->validateArray('autoload') && !empty($this->config['autoload'])) {
27365 $types = array('psr-0', 'psr-4', 'classmap', 'files', 'exclude-from-classmap');
27366 foreach ($this->config['autoload'] as $type => $typeConfig) {
27367 if (!in_array($type, $types)) {
27368 $this->errors[] = 'autoload : invalid value ('.$type.'), must be one of '.implode(', ', $types);
27369 unset($this->config['autoload'][$type]);
27370 }
27371 if ($type === 'psr-4') {
27372 foreach ($typeConfig as $namespace => $dirs) {
27373 if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
27374 $this->errors[] = 'autoload.psr-4 : invalid value ('.$namespace.'), namespaces must end with a namespace separator, should be '.$namespace.'\\\\';
27375 }
27376 }
27377 }
27378 }
27379 }
27380
27381 if (!empty($this->config['autoload']['psr-4']) && !empty($this->config['target-dir'])) {
27382 $this->errors[] = 'target-dir : this can not be used together with the autoload.psr-4 setting, remove target-dir to upgrade to psr-4';
27383
27384  
27385  unset($this->config['autoload']['psr-4']);
27386 }
27387
27388
27389  
27390
27391
27392  
27393
27394 $this->validateFlatArray('include-path');
27395 $this->validateArray('transport-options');
27396
27397
27398  if (isset($this->config['extra']['branch-alias'])) {
27399 if (!is_array($this->config['extra']['branch-alias'])) {
27400 $this->errors[] = 'extra.branch-alias : must be an array of versions => aliases';
27401 } else {
27402 foreach ($this->config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
27403
27404  if ('-dev' !== substr($targetBranch, -4)) {
27405 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must end in -dev';
27406 unset($this->config['extra']['branch-alias'][$sourceBranch]);
27407
27408 continue;
27409 }
27410
27411
27412  $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
27413 if ('-dev' !== substr($validatedTargetBranch, -4)) {
27414 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must be a parseable number like 2.0-dev';
27415 unset($this->config['extra']['branch-alias'][$sourceBranch]);
27416
27417 continue;
27418 }
27419
27420
27421  if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
27422 && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
27423 && (stripos($targetPrefix, $sourcePrefix) !== 0)
27424 ) {
27425 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') is not a valid numeric alias for this version';
27426 unset($this->config['extra']['branch-alias'][$sourceBranch]);
27427 }
27428 }
27429 }
27430 }
27431
27432 if ($this->errors) {
27433 throw new InvalidPackageException($this->errors, $this->warnings, $config);
27434 }
27435
27436 $package = $this->loader->load($this->config, $class);
27437 $this->config = null;
27438
27439 return $package;
27440 }
27441
27442 public function getWarnings()
27443 {
27444 return $this->warnings;
27445 }
27446
27447 public function getErrors()
27448 {
27449 return $this->errors;
27450 }
27451
27452 private function validateRegex($property, $regex, $mandatory = false)
27453 {
27454 if (!$this->validateString($property, $mandatory)) {
27455 return false;
27456 }
27457
27458 if (!preg_match('{^'.$regex.'$}u', $this->config[$property])) {
27459 $message = $property.' : invalid value ('.$this->config[$property].'), must match '.$regex;
27460 if ($mandatory) {
27461 $this->errors[] = $message;
27462 } else {
27463 $this->warnings[] = $message;
27464 }
27465 unset($this->config[$property]);
27466
27467 return false;
27468 }
27469
27470 return true;
27471 }
27472
27473 private function validateString($property, $mandatory = false)
27474 {
27475 if (isset($this->config[$property]) && !is_string($this->config[$property])) {
27476 $this->errors[] = $property.' : should be a string, '.gettype($this->config[$property]).' given';
27477 unset($this->config[$property]);
27478
27479 return false;
27480 }
27481
27482 if (!isset($this->config[$property]) || trim($this->config[$property]) === '') {
27483 if ($mandatory) {
27484 $this->errors[] = $property.' : must be present';
27485 }
27486 unset($this->config[$property]);
27487
27488 return false;
27489 }
27490
27491 return true;
27492 }
27493
27494 private function validateArray($property, $mandatory = false)
27495 {
27496 if (isset($this->config[$property]) && !is_array($this->config[$property])) {
27497 $this->errors[] = $property.' : should be an array, '.gettype($this->config[$property]).' given';
27498 unset($this->config[$property]);
27499
27500 return false;
27501 }
27502
27503 if (!isset($this->config[$property]) || !count($this->config[$property])) {
27504 if ($mandatory) {
27505 $this->errors[] = $property.' : must be present and contain at least one element';
27506 }
27507 unset($this->config[$property]);
27508
27509 return false;
27510 }
27511
27512 return true;
27513 }
27514
27515 private function validateFlatArray($property, $regex = null, $mandatory = false)
27516 {
27517 if (!$this->validateArray($property, $mandatory)) {
27518 return false;
27519 }
27520
27521 $pass = true;
27522 foreach ($this->config[$property] as $key => $value) {
27523 if (!is_string($value) && !is_numeric($value)) {
27524 $this->errors[] = $property.'.'.$key.' : must be a string or int, '.gettype($value).' given';
27525 unset($this->config[$property][$key]);
27526 $pass = false;
27527
27528 continue;
27529 }
27530
27531 if ($regex && !preg_match('{^'.$regex.'$}u', $value)) {
27532 $this->warnings[] = $property.'.'.$key.' : invalid value ('.$value.'), must match '.$regex;
27533 unset($this->config[$property][$key]);
27534 $pass = false;
27535 }
27536 }
27537
27538 return $pass;
27539 }
27540
27541 private function validateUrl($property, $mandatory = false)
27542 {
27543 if (!$this->validateString($property, $mandatory)) {
27544 return false;
27545 }
27546
27547 if (!$this->filterUrl($this->config[$property])) {
27548 $this->warnings[] = $property.' : invalid value ('.$this->config[$property].'), must be an http/https URL';
27549 unset($this->config[$property]);
27550
27551 return false;
27552 }
27553
27554 return true;
27555 }
27556
27557 private function filterUrl($value, array $schemes = array('http', 'https'))
27558 {
27559 if ($value === '') {
27560 return true;
27561 }
27562
27563 $bits = parse_url($value);
27564 if (empty($bits['scheme']) || empty($bits['host'])) {
27565 return false;
27566 }
27567
27568 if (!in_array($bits['scheme'], $schemes, true)) {
27569 return false;
27570 }
27571
27572 return true;
27573 }
27574 }
27575 <?php
27576
27577
27578
27579
27580
27581
27582
27583
27584
27585
27586
27587 namespace Composer\Package;
27588
27589 use Composer\Json\JsonFile;
27590 use Composer\Installer\InstallationManager;
27591 use Composer\Repository\RepositoryManager;
27592 use Composer\Util\ProcessExecutor;
27593 use Composer\Repository\ArrayRepository;
27594 use Composer\Package\Dumper\ArrayDumper;
27595 use Composer\Package\Loader\ArrayLoader;
27596 use Composer\Util\Git as GitUtil;
27597 use Composer\IO\IOInterface;
27598 use Seld\JsonLint\ParsingException;
27599
27600
27601
27602
27603
27604
27605
27606 class Locker
27607 {
27608 private $lockFile;
27609 private $repositoryManager;
27610 private $installationManager;
27611 private $hash;
27612 private $contentHash;
27613 private $loader;
27614 private $dumper;
27615 private $process;
27616 private $lockDataCache;
27617
27618
27619
27620
27621
27622
27623
27624
27625
27626
27627 public function __construct(IOInterface $io, JsonFile $lockFile, RepositoryManager $repositoryManager, InstallationManager $installationManager, $composerFileContents)
27628 {
27629 $this->lockFile = $lockFile;
27630 $this->repositoryManager = $repositoryManager;
27631 $this->installationManager = $installationManager;
27632 $this->hash = md5($composerFileContents);
27633 $this->contentHash = self::getContentHash($composerFileContents);
27634 $this->loader = new ArrayLoader(null, true);
27635 $this->dumper = new ArrayDumper();
27636 $this->process = new ProcessExecutor($io);
27637 }
27638
27639
27640
27641
27642
27643
27644
27645
27646 public static function getContentHash($composerFileContents)
27647 {
27648 $content = json_decode($composerFileContents, true);
27649
27650 $relevantKeys = array(
27651 'name',
27652 'version',
27653 'require',
27654 'require-dev',
27655 'conflict',
27656 'replace',
27657 'provide',
27658 'minimum-stability',
27659 'prefer-stable',
27660 'repositories',
27661 'extra',
27662 );
27663
27664 $relevantContent = array();
27665
27666 foreach (array_intersect($relevantKeys, array_keys($content)) as $key) {
27667 $relevantContent[$key] = $content[$key];
27668 }
27669 if (isset($content['config']['platform'])) {
27670 $relevantContent['config']['platform'] = $content['config']['platform'];
27671 }
27672
27673 ksort($relevantContent);
27674
27675 return md5(json_encode($relevantContent));
27676 }
27677
27678
27679
27680
27681
27682
27683 public function isLocked()
27684 {
27685 if (!$this->lockFile->exists()) {
27686 return false;
27687 }
27688
27689 $data = $this->getLockData();
27690
27691 return isset($data['packages']);
27692 }
27693
27694
27695
27696
27697
27698
27699 public function isFresh()
27700 {
27701 $lock = $this->lockFile->read();
27702
27703 if (!empty($lock['content-hash'])) {
27704
27705  return $this->contentHash === $lock['content-hash'];
27706 }
27707
27708
27709  if (!empty($lock['hash'])) {
27710 return $this->hash === $lock['hash'];
27711 }
27712
27713
27714  return false;
27715 }
27716
27717
27718
27719
27720
27721
27722
27723
27724 public function getLockedRepository($withDevReqs = false)
27725 {
27726 $lockData = $this->getLockData();
27727 $packages = new ArrayRepository();
27728
27729 $lockedPackages = $lockData['packages'];
27730 if ($withDevReqs) {
27731 if (isset($lockData['packages-dev'])) {
27732 $lockedPackages = array_merge($lockedPackages, $lockData['packages-dev']);
27733 } else {
27734 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.');
27735 }
27736 }
27737
27738 if (empty($lockedPackages)) {
27739 return $packages;
27740 }
27741
27742 if (isset($lockedPackages[0]['name'])) {
27743 foreach ($lockedPackages as $info) {
27744 $packages->addPackage($this->loader->load($info));
27745 }
27746
27747 return $packages;
27748 }
27749
27750 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.');
27751 }
27752
27753
27754
27755
27756
27757
27758
27759 public function getPlatformRequirements($withDevReqs = false)
27760 {
27761 $lockData = $this->getLockData();
27762 $requirements = array();
27763
27764 if (!empty($lockData['platform'])) {
27765 $requirements = $this->loader->parseLinks(
27766 '__ROOT__',
27767 '1.0.0',
27768 'requires',
27769 isset($lockData['platform']) ? $lockData['platform'] : array()
27770 );
27771 }
27772
27773 if ($withDevReqs && !empty($lockData['platform-dev'])) {
27774 $devRequirements = $this->loader->parseLinks(
27775 '__ROOT__',
27776 '1.0.0',
27777 'requires',
27778 isset($lockData['platform-dev']) ? $lockData['platform-dev'] : array()
27779 );
27780
27781 $requirements = array_merge($requirements, $devRequirements);
27782 }
27783
27784 return $requirements;
27785 }
27786
27787 public function getMinimumStability()
27788 {
27789 $lockData = $this->getLockData();
27790
27791 return isset($lockData['minimum-stability']) ? $lockData['minimum-stability'] : 'stable';
27792 }
27793
27794 public function getStabilityFlags()
27795 {
27796 $lockData = $this->getLockData();
27797
27798 return isset($lockData['stability-flags']) ? $lockData['stability-flags'] : array();
27799 }
27800
27801 public function getPreferStable()
27802 {
27803 $lockData = $this->getLockData();
27804
27805
27806  
27807  return isset($lockData['prefer-stable']) ? $lockData['prefer-stable'] : null;
27808 }
27809
27810 public function getPreferLowest()
27811 {
27812 $lockData = $this->getLockData();
27813
27814
27815  
27816  return isset($lockData['prefer-lowest']) ? $lockData['prefer-lowest'] : null;
27817 }
27818
27819 public function getPlatformOverrides()
27820 {
27821 $lockData = $this->getLockData();
27822
27823 return isset($lockData['platform-overrides']) ? $lockData['platform-overrides'] : array();
27824 }
27825
27826 public function getAliases()
27827 {
27828 $lockData = $this->getLockData();
27829
27830 return isset($lockData['aliases']) ? $lockData['aliases'] : array();
27831 }
27832
27833 public function getLockData()
27834 {
27835 if (null !== $this->lockDataCache) {
27836 return $this->lockDataCache;
27837 }
27838
27839 if (!$this->lockFile->exists()) {
27840 throw new \LogicException('No lockfile found. Unable to read locked packages');
27841 }
27842
27843 return $this->lockDataCache = $this->lockFile->read();
27844 }
27845
27846
27847
27848
27849
27850
27851
27852
27853
27854
27855
27856
27857
27858
27859
27860
27861
27862 public function setLockData(array $packages, $devPackages, array $platformReqs, $platformDevReqs, array $aliases, $minimumStability, array $stabilityFlags, $preferStable, $preferLowest, array $platformOverrides)
27863 {
27864 $lock = array(
27865 '_readme' => array('This file locks the dependencies of your project to a known state',
27866 'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file',
27867 'This file is @gener'.'ated automatically', ),
27868 'content-hash' => $this->contentHash,
27869 'packages' => null,
27870 'packages-dev' => null,
27871 'aliases' => array(),
27872 'minimum-stability' => $minimumStability,
27873 'stability-flags' => $stabilityFlags,
27874 'prefer-stable' => $preferStable,
27875 'prefer-lowest' => $preferLowest,
27876 );
27877
27878 foreach ($aliases as $package => $versions) {
27879 foreach ($versions as $version => $alias) {
27880 $lock['aliases'][] = array(
27881 'alias' => $alias['alias'],
27882 'alias_normalized' => $alias['alias_normalized'],
27883 'version' => $version,
27884 'package' => $package,
27885 );
27886 }
27887 }
27888
27889 $lock['packages'] = $this->lockPackages($packages);
27890 if (null !== $devPackages) {
27891 $lock['packages-dev'] = $this->lockPackages($devPackages);
27892 }
27893
27894 $lock['platform'] = $platformReqs;
27895 $lock['platform-dev'] = $platformDevReqs;
27896 if ($platformOverrides) {
27897 $lock['platform-overrides'] = $platformOverrides;
27898 }
27899
27900 if (empty($lock['packages']) && empty($lock['packages-dev']) && empty($lock['platform']) && empty($lock['platform-dev'])) {
27901 if ($this->lockFile->exists()) {
27902 unlink($this->lockFile->getPath());
27903 }
27904
27905 return false;
27906 }
27907
27908 try {
27909 $isLocked = $this->isLocked();
27910 } catch (ParsingException $e) {
27911 $isLocked = false;
27912 }
27913 if (!$isLocked || $lock !== $this->getLockData()) {
27914 $this->lockFile->write($lock);
27915 $this->lockDataCache = null;
27916
27917 return true;
27918 }
27919
27920 return false;
27921 }
27922
27923 private function lockPackages(array $packages)
27924 {
27925 $locked = array();
27926
27927 foreach ($packages as $package) {
27928 if ($package instanceof AliasPackage) {
27929 continue;
27930 }
27931
27932 $name = $package->getPrettyName();
27933 $version = $package->getPrettyVersion();
27934
27935 if (!$name || !$version) {
27936 throw new \LogicException(sprintf(
27937 'Package "%s" has no version or name and can not be locked', $package
27938 ));
27939 }
27940
27941 $spec = $this->dumper->dump($package);
27942 unset($spec['version_normalized']);
27943
27944
27945  $time = isset($spec['time']) ? $spec['time'] : null;
27946 unset($spec['time']);
27947 if ($package->isDev() && $package->getInstallationSource() === 'source') {
27948
27949  $time = $this->getPackageTime($package) ?: $time;
27950 }
27951 if (null !== $time) {
27952 $spec['time'] = $time;
27953 }
27954
27955 unset($spec['installation-source']);
27956
27957 $locked[] = $spec;
27958 }
27959
27960 usort($locked, function ($a, $b) {
27961 $comparison = strcmp($a['name'], $b['name']);
27962
27963 if (0 !== $comparison) {
27964 return $comparison;
27965 }
27966
27967
27968  return strcmp($a['version'], $b['version']);
27969 });
27970
27971 return $locked;
27972 }
27973
27974
27975
27976
27977
27978
27979
27980 private function getPackageTime(PackageInterface $package)
27981 {
27982 if (!function_exists('proc_open')) {
27983 return null;
27984 }
27985
27986 $path = realpath($this->installationManager->getInstallPath($package));
27987 $sourceType = $package->getSourceType();
27988 $datetime = null;
27989
27990 if ($path && in_array($sourceType, array('git', 'hg'))) {
27991 $sourceRef = $package->getSourceReference() ?: $package->getDistReference();
27992 switch ($sourceType) {
27993 case 'git':
27994 GitUtil::cleanEnv();
27995
27996 if (0 === $this->process->execute('git log -n1 --pretty=%ct '.ProcessExecutor::escape($sourceRef), $output, $path) && preg_match('{^\s*\d+\s*$}', $output)) {
27997 $datetime = new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
27998 }
27999 break;
28000
28001 case 'hg':
28002 if (0 === $this->process->execute('hg log --template "{date|hgdate}" -r '.ProcessExecutor::escape($sourceRef), $output, $path) && preg_match('{^\s*(\d+)\s*}', $output, $match)) {
28003 $datetime = new \DateTime('@'.$match[1], new \DateTimeZone('UTC'));
28004 }
28005 break;
28006 }
28007 }
28008
28009 return $datetime ? $datetime->format(DATE_RFC3339) : null;
28010 }
28011 }
28012 <?php
28013
28014
28015
28016
28017
28018
28019
28020
28021
28022
28023
28024 namespace Composer\Package;
28025
28026 use Composer\Package\Version\VersionParser;
28027 use Composer\Util\ComposerMirror;
28028
28029
28030
28031
28032
28033
28034 class Package extends BasePackage
28035 {
28036 protected $type;
28037 protected $targetDir;
28038 protected $installationSource;
28039 protected $sourceType;
28040 protected $sourceUrl;
28041 protected $sourceReference;
28042 protected $sourceMirrors;
28043 protected $distType;
28044 protected $distUrl;
28045 protected $distReference;
28046 protected $distSha1Checksum;
28047 protected $distMirrors;
28048 protected $version;
28049 protected $prettyVersion;
28050 protected $releaseDate;
28051 protected $extra = array();
28052 protected $binaries = array();
28053 protected $dev;
28054 protected $stability;
28055 protected $notificationUrl;
28056
28057
28058 protected $requires = array();
28059
28060 protected $conflicts = array();
28061
28062 protected $provides = array();
28063
28064 protected $replaces = array();
28065
28066 protected $devRequires = array();
28067 protected $suggests = array();
28068 protected $autoload = array();
28069 protected $devAutoload = array();
28070 protected $includePaths = array();
28071 protected $archiveExcludes = array();
28072
28073
28074
28075
28076
28077
28078
28079
28080 public function __construct($name, $version, $prettyVersion)
28081 {
28082 parent::__construct($name);
28083
28084 $this->version = $version;
28085 $this->prettyVersion = $prettyVersion;
28086
28087 $this->stability = VersionParser::parseStability($version);
28088 $this->dev = $this->stability === 'dev';
28089 }
28090
28091
28092
28093
28094 public function isDev()
28095 {
28096 return $this->dev;
28097 }
28098
28099
28100
28101
28102 public function setType($type)
28103 {
28104 $this->type = $type;
28105 }
28106
28107
28108
28109
28110 public function getType()
28111 {
28112 return $this->type ?: 'library';
28113 }
28114
28115
28116
28117
28118 public function getStability()
28119 {
28120 return $this->stability;
28121 }
28122
28123
28124
28125
28126 public function setTargetDir($targetDir)
28127 {
28128 $this->targetDir = $targetDir;
28129 }
28130
28131
28132
28133
28134 public function getTargetDir()
28135 {
28136 if (null === $this->targetDir) {
28137 return;
28138 }
28139
28140 return ltrim(preg_replace('{ (?:^|[\\\\/]+) \.\.? (?:[\\\\/]+|$) (?:\.\.? (?:[\\\\/]+|$) )*}x', '/', $this->targetDir), '/');
28141 }
28142
28143
28144
28145
28146 public function setExtra(array $extra)
28147 {
28148 $this->extra = $extra;
28149 }
28150
28151
28152
28153
28154 public function getExtra()
28155 {
28156 return $this->extra;
28157 }
28158
28159
28160
28161
28162 public function setBinaries(array $binaries)
28163 {
28164 $this->binaries = $binaries;
28165 }
28166
28167
28168
28169
28170 public function getBinaries()
28171 {
28172 return $this->binaries;
28173 }
28174
28175
28176
28177
28178 public function setInstallationSource($type)
28179 {
28180 $this->installationSource = $type;
28181 }
28182
28183
28184
28185
28186 public function getInstallationSource()
28187 {
28188 return $this->installationSource;
28189 }
28190
28191
28192
28193
28194 public function setSourceType($type)
28195 {
28196 $this->sourceType = $type;
28197 }
28198
28199
28200
28201
28202 public function getSourceType()
28203 {
28204 return $this->sourceType;
28205 }
28206
28207
28208
28209
28210 public function setSourceUrl($url)
28211 {
28212 $this->sourceUrl = $url;
28213 }
28214
28215
28216
28217
28218 public function getSourceUrl()
28219 {
28220 return $this->sourceUrl;
28221 }
28222
28223
28224
28225
28226 public function setSourceReference($reference)
28227 {
28228 $this->sourceReference = $reference;
28229 }
28230
28231
28232
28233
28234 public function getSourceReference()
28235 {
28236 return $this->sourceReference;
28237 }
28238
28239
28240
28241
28242 public function setSourceMirrors($mirrors)
28243 {
28244 $this->sourceMirrors = $mirrors;
28245 }
28246
28247
28248
28249
28250 public function getSourceMirrors()
28251 {
28252 return $this->sourceMirrors;
28253 }
28254
28255
28256
28257
28258 public function getSourceUrls()
28259 {
28260 return $this->getUrls($this->sourceUrl, $this->sourceMirrors, $this->sourceReference, $this->sourceType, 'source');
28261 }
28262
28263
28264
28265
28266 public function setDistType($type)
28267 {
28268 $this->distType = $type;
28269 }
28270
28271
28272
28273
28274 public function getDistType()
28275 {
28276 return $this->distType;
28277 }
28278
28279
28280
28281
28282 public function setDistUrl($url)
28283 {
28284 $this->distUrl = $url;
28285 }
28286
28287
28288
28289
28290 public function getDistUrl()
28291 {
28292 return $this->distUrl;
28293 }
28294
28295
28296
28297
28298 public function setDistReference($reference)
28299 {
28300 $this->distReference = $reference;
28301 }
28302
28303
28304
28305
28306 public function getDistReference()
28307 {
28308 return $this->distReference;
28309 }
28310
28311
28312
28313
28314 public function setDistSha1Checksum($sha1checksum)
28315 {
28316 $this->distSha1Checksum = $sha1checksum;
28317 }
28318
28319
28320
28321
28322 public function getDistSha1Checksum()
28323 {
28324 return $this->distSha1Checksum;
28325 }
28326
28327
28328
28329
28330 public function setDistMirrors($mirrors)
28331 {
28332 $this->distMirrors = $mirrors;
28333 }
28334
28335
28336
28337
28338 public function getDistMirrors()
28339 {
28340 return $this->distMirrors;
28341 }
28342
28343
28344
28345
28346 public function getDistUrls()
28347 {
28348 return $this->getUrls($this->distUrl, $this->distMirrors, $this->distReference, $this->distType, 'dist');
28349 }
28350
28351
28352
28353
28354 public function getVersion()
28355 {
28356 return $this->version;
28357 }
28358
28359
28360
28361
28362 public function getPrettyVersion()
28363 {
28364 return $this->prettyVersion;
28365 }
28366
28367
28368
28369
28370
28371
28372 public function setReleaseDate(\DateTime $releaseDate)
28373 {
28374 $this->releaseDate = $releaseDate;
28375 }
28376
28377
28378
28379
28380 public function getReleaseDate()
28381 {
28382 return $this->releaseDate;
28383 }
28384
28385
28386
28387
28388
28389
28390 public function setRequires(array $requires)
28391 {
28392 $this->requires = $requires;
28393 }
28394
28395
28396
28397
28398 public function getRequires()
28399 {
28400 return $this->requires;
28401 }
28402
28403
28404
28405
28406
28407
28408 public function setConflicts(array $conflicts)
28409 {
28410 $this->conflicts = $conflicts;
28411 }
28412
28413
28414
28415
28416 public function getConflicts()
28417 {
28418 return $this->conflicts;
28419 }
28420
28421
28422
28423
28424
28425
28426 public function setProvides(array $provides)
28427 {
28428 $this->provides = $provides;
28429 }
28430
28431
28432
28433
28434 public function getProvides()
28435 {
28436 return $this->provides;
28437 }
28438
28439
28440
28441
28442
28443
28444 public function setReplaces(array $replaces)
28445 {
28446 $this->replaces = $replaces;
28447 }
28448
28449
28450
28451
28452 public function getReplaces()
28453 {
28454 return $this->replaces;
28455 }
28456
28457
28458
28459
28460
28461
28462 public function setDevRequires(array $devRequires)
28463 {
28464 $this->devRequires = $devRequires;
28465 }
28466
28467
28468
28469
28470 public function getDevRequires()
28471 {
28472 return $this->devRequires;
28473 }
28474
28475
28476
28477
28478
28479
28480 public function setSuggests(array $suggests)
28481 {
28482 $this->suggests = $suggests;
28483 }
28484
28485
28486
28487
28488 public function getSuggests()
28489 {
28490 return $this->suggests;
28491 }
28492
28493
28494
28495
28496
28497
28498 public function setAutoload(array $autoload)
28499 {
28500 $this->autoload = $autoload;
28501 }
28502
28503
28504
28505
28506 public function getAutoload()
28507 {
28508 return $this->autoload;
28509 }
28510
28511
28512
28513
28514
28515
28516 public function setDevAutoload(array $devAutoload)
28517 {
28518 $this->devAutoload = $devAutoload;
28519 }
28520
28521
28522
28523
28524 public function getDevAutoload()
28525 {
28526 return $this->devAutoload;
28527 }
28528
28529
28530
28531
28532
28533
28534 public function setIncludePaths(array $includePaths)
28535 {
28536 $this->includePaths = $includePaths;
28537 }
28538
28539
28540
28541
28542 public function getIncludePaths()
28543 {
28544 return $this->includePaths;
28545 }
28546
28547
28548
28549
28550
28551
28552 public function setNotificationUrl($notificationUrl)
28553 {
28554 $this->notificationUrl = $notificationUrl;
28555 }
28556
28557
28558
28559
28560 public function getNotificationUrl()
28561 {
28562 return $this->notificationUrl;
28563 }
28564
28565
28566
28567
28568
28569
28570 public function setArchiveExcludes(array $excludes)
28571 {
28572 $this->archiveExcludes = $excludes;
28573 }
28574
28575
28576
28577
28578 public function getArchiveExcludes()
28579 {
28580 return $this->archiveExcludes;
28581 }
28582
28583
28584
28585
28586
28587
28588
28589
28590 public function replaceVersion($version, $prettyVersion)
28591 {
28592 $this->version = $version;
28593 $this->prettyVersion = $prettyVersion;
28594
28595 $this->stability = VersionParser::parseStability($version);
28596 $this->dev = $this->stability === 'dev';
28597 }
28598
28599 protected function getUrls($url, $mirrors, $ref, $type, $urlType)
28600 {
28601 if (!$url) {
28602 return array();
28603 }
28604 $urls = array($url);
28605 if ($mirrors) {
28606 foreach ($mirrors as $mirror) {
28607 if ($urlType === 'dist') {
28608 $mirrorUrl = ComposerMirror::processUrl($mirror['url'], $this->name, $this->version, $ref, $type);
28609 } elseif ($urlType === 'source' && $type === 'git') {
28610 $mirrorUrl = ComposerMirror::processGitUrl($mirror['url'], $this->name, $url, $type);
28611 } elseif ($urlType === 'source' && $type === 'hg') {
28612 $mirrorUrl = ComposerMirror::processHgUrl($mirror['url'], $this->name, $url, $type);
28613 }
28614 if (!in_array($mirrorUrl, $urls)) {
28615 $func = $mirror['preferred'] ? 'array_unshift' : 'array_push';
28616 $func($urls, $mirrorUrl);
28617 }
28618 }
28619 }
28620
28621 return $urls;
28622 }
28623 }
28624 <?php
28625
28626
28627
28628
28629
28630
28631
28632
28633
28634
28635
28636 namespace Composer\Package;
28637
28638 use Composer\Repository\RepositoryInterface;
28639
28640
28641
28642
28643
28644
28645 interface PackageInterface
28646 {
28647
28648
28649
28650
28651
28652 public function getName();
28653
28654
28655
28656
28657
28658
28659 public function getPrettyName();
28660
28661
28662
28663
28664
28665
28666
28667
28668
28669 public function getNames();
28670
28671
28672
28673
28674
28675
28676 public function setId($id);
28677
28678
28679
28680
28681
28682
28683 public function getId();
28684
28685
28686
28687
28688
28689
28690 public function isDev();
28691
28692
28693
28694
28695
28696
28697 public function getType();
28698
28699
28700
28701
28702
28703
28704 public function getTargetDir();
28705
28706
28707
28708
28709
28710
28711 public function getExtra();
28712
28713
28714
28715
28716
28717
28718 public function setInstallationSource($type);
28719
28720
28721
28722
28723
28724
28725 public function getInstallationSource();
28726
28727
28728
28729
28730
28731
28732 public function getSourceType();
28733
28734
28735
28736
28737
28738
28739 public function getSourceUrl();
28740
28741
28742
28743
28744
28745
28746 public function getSourceUrls();
28747
28748
28749
28750
28751
28752
28753 public function getSourceReference();
28754
28755
28756
28757
28758
28759
28760 public function getSourceMirrors();
28761
28762
28763
28764
28765
28766
28767 public function getDistType();
28768
28769
28770
28771
28772
28773
28774 public function getDistUrl();
28775
28776
28777
28778
28779
28780
28781 public function getDistUrls();
28782
28783
28784
28785
28786
28787
28788 public function getDistReference();
28789
28790
28791
28792
28793
28794
28795 public function getDistSha1Checksum();
28796
28797
28798
28799
28800
28801
28802 public function getDistMirrors();
28803
28804
28805
28806
28807
28808
28809 public function getVersion();
28810
28811
28812
28813
28814
28815
28816 public function getPrettyVersion();
28817
28818
28819
28820
28821
28822
28823
28824
28825
28826 public function getFullPrettyVersion($truncate = true);
28827
28828
28829
28830
28831
28832
28833 public function getReleaseDate();
28834
28835
28836
28837
28838
28839
28840 public function getStability();
28841
28842
28843
28844
28845
28846
28847
28848 public function getRequires();
28849
28850
28851
28852
28853
28854
28855
28856 public function getConflicts();
28857
28858
28859
28860
28861
28862
28863
28864 public function getProvides();
28865
28866
28867
28868
28869
28870
28871
28872 public function getReplaces();
28873
28874
28875
28876
28877
28878
28879
28880 public function getDevRequires();
28881
28882
28883
28884
28885
28886
28887
28888 public function getSuggests();
28889
28890
28891
28892
28893
28894
28895
28896
28897
28898
28899
28900 public function getAutoload();
28901
28902
28903
28904
28905
28906
28907
28908
28909
28910
28911
28912 public function getDevAutoload();
28913
28914
28915
28916
28917
28918
28919
28920 public function getIncludePaths();
28921
28922
28923
28924
28925
28926
28927 public function setRepository(RepositoryInterface $repository);
28928
28929
28930
28931
28932
28933
28934 public function getRepository();
28935
28936
28937
28938
28939
28940
28941 public function getBinaries();
28942
28943
28944
28945
28946
28947
28948 public function getUniqueName();
28949
28950
28951
28952
28953
28954
28955 public function getNotificationUrl();
28956
28957
28958
28959
28960
28961
28962 public function __toString();
28963
28964
28965
28966
28967
28968
28969 public function getPrettyString();
28970
28971
28972
28973
28974
28975
28976 public function getArchiveExcludes();
28977
28978
28979
28980
28981
28982
28983 public function getTransportOptions();
28984 }
28985 <?php
28986
28987
28988
28989
28990
28991
28992
28993
28994
28995
28996
28997 namespace Composer\Package;
28998
28999
29000
29001
29002 class RootAliasPackage extends AliasPackage implements RootPackageInterface
29003 {
29004 public function __construct(RootPackageInterface $aliasOf, $version, $prettyVersion)
29005 {
29006 parent::__construct($aliasOf, $version, $prettyVersion);
29007 }
29008
29009
29010
29011
29012 public function getAliases()
29013 {
29014 return $this->aliasOf->getAliases();
29015 }
29016
29017
29018
29019
29020 public function getMinimumStability()
29021 {
29022 return $this->aliasOf->getMinimumStability();
29023 }
29024
29025
29026
29027
29028 public function getStabilityFlags()
29029 {
29030 return $this->aliasOf->getStabilityFlags();
29031 }
29032
29033
29034
29035
29036 public function getReferences()
29037 {
29038 return $this->aliasOf->getReferences();
29039 }
29040
29041
29042
29043
29044 public function getPreferStable()
29045 {
29046 return $this->aliasOf->getPreferStable();
29047 }
29048
29049
29050
29051
29052 public function getConfig()
29053 {
29054 return $this->aliasOf->getConfig();
29055 }
29056
29057
29058
29059
29060 public function setRequires(array $require)
29061 {
29062 $this->requires = $this->replaceSelfVersionDependencies($require, 'requires');
29063
29064 $this->aliasOf->setRequires($require);
29065 }
29066
29067
29068
29069
29070 public function setDevRequires(array $devRequire)
29071 {
29072 $this->devRequires = $this->replaceSelfVersionDependencies($devRequire, 'devRequires');
29073
29074 $this->aliasOf->setDevRequires($devRequire);
29075 }
29076
29077
29078
29079
29080 public function setConflicts(array $conflicts)
29081 {
29082 $this->conflicts = $this->replaceSelfVersionDependencies($conflicts, 'conflicts');
29083 $this->aliasOf->setConflicts($conflicts);
29084 }
29085
29086
29087
29088
29089 public function setProvides(array $provides)
29090 {
29091 $this->provides = $this->replaceSelfVersionDependencies($provides, 'provides');
29092 $this->aliasOf->setProvides($provides);
29093 }
29094
29095
29096
29097
29098 public function setReplaces(array $replaces)
29099 {
29100 $this->replaces = $this->replaceSelfVersionDependencies($replaces, 'replaces');
29101 $this->aliasOf->setReplaces($replaces);
29102 }
29103
29104
29105
29106
29107 public function setRepositories($repositories)
29108 {
29109 $this->aliasOf->setRepositories($repositories);
29110 }
29111
29112
29113
29114
29115 public function setAutoload(array $autoload)
29116 {
29117 $this->aliasOf->setAutoload($autoload);
29118 }
29119
29120
29121
29122
29123 public function setDevAutoload(array $devAutoload)
29124 {
29125 $this->aliasOf->setDevAutoload($devAutoload);
29126 }
29127
29128
29129
29130
29131 public function setStabilityFlags(array $stabilityFlags)
29132 {
29133 $this->aliasOf->setStabilityFlags($stabilityFlags);
29134 }
29135
29136
29137
29138
29139 public function setSuggests(array $suggests)
29140 {
29141 $this->aliasOf->setSuggests($suggests);
29142 }
29143
29144
29145
29146
29147 public function setExtra(array $extra)
29148 {
29149 $this->aliasOf->setExtra($extra);
29150 }
29151
29152 public function __clone()
29153 {
29154 parent::__clone();
29155 $this->aliasOf = clone $this->aliasOf;
29156 }
29157 }
29158 <?php
29159
29160
29161
29162
29163
29164
29165
29166
29167
29168
29169
29170 namespace Composer\Package;
29171
29172
29173
29174
29175
29176
29177 class RootPackage extends CompletePackage implements RootPackageInterface
29178 {
29179 protected $minimumStability = 'stable';
29180 protected $preferStable = false;
29181 protected $stabilityFlags = array();
29182 protected $config = array();
29183 protected $references = array();
29184 protected $aliases = array();
29185
29186
29187
29188
29189
29190
29191 public function setMinimumStability($minimumStability)
29192 {
29193 $this->minimumStability = $minimumStability;
29194 }
29195
29196
29197
29198
29199 public function getMinimumStability()
29200 {
29201 return $this->minimumStability;
29202 }
29203
29204
29205
29206
29207
29208
29209 public function setStabilityFlags(array $stabilityFlags)
29210 {
29211 $this->stabilityFlags = $stabilityFlags;
29212 }
29213
29214
29215
29216
29217 public function getStabilityFlags()
29218 {
29219 return $this->stabilityFlags;
29220 }
29221
29222
29223
29224
29225
29226
29227 public function setPreferStable($preferStable)
29228 {
29229 $this->preferStable = $preferStable;
29230 }
29231
29232
29233
29234
29235 public function getPreferStable()
29236 {
29237 return $this->preferStable;
29238 }
29239
29240
29241
29242
29243
29244
29245 public function setConfig(array $config)
29246 {
29247 $this->config = $config;
29248 }
29249
29250
29251
29252
29253 public function getConfig()
29254 {
29255 return $this->config;
29256 }
29257
29258
29259
29260
29261
29262
29263 public function setReferences(array $references)
29264 {
29265 $this->references = $references;
29266 }
29267
29268
29269
29270
29271 public function getReferences()
29272 {
29273 return $this->references;
29274 }
29275
29276
29277
29278
29279
29280
29281 public function setAliases(array $aliases)
29282 {
29283 $this->aliases = $aliases;
29284 }
29285
29286
29287
29288
29289 public function getAliases()
29290 {
29291 return $this->aliases;
29292 }
29293 }
29294 <?php
29295
29296
29297
29298
29299
29300
29301
29302
29303
29304
29305
29306 namespace Composer\Package;
29307
29308
29309
29310
29311
29312
29313 interface RootPackageInterface extends CompletePackageInterface
29314 {
29315
29316
29317
29318
29319
29320 public function getAliases();
29321
29322
29323
29324
29325
29326
29327 public function getMinimumStability();
29328
29329
29330
29331
29332
29333
29334
29335
29336 public function getStabilityFlags();
29337
29338
29339
29340
29341
29342
29343
29344
29345 public function getReferences();
29346
29347
29348
29349
29350
29351
29352 public function getPreferStable();
29353
29354
29355
29356
29357
29358
29359 public function getConfig();
29360
29361
29362
29363
29364
29365
29366 public function setRequires(array $requires);
29367
29368
29369
29370
29371
29372
29373 public function setDevRequires(array $devRequires);
29374
29375
29376
29377
29378
29379
29380 public function setConflicts(array $conflicts);
29381
29382
29383
29384
29385
29386
29387 public function setProvides(array $provides);
29388
29389
29390
29391
29392
29393
29394 public function setReplaces(array $replaces);
29395
29396
29397
29398
29399
29400
29401 public function setRepositories($repositories);
29402
29403
29404
29405
29406
29407
29408 public function setAutoload(array $autoload);
29409
29410
29411
29412
29413
29414
29415 public function setDevAutoload(array $devAutoload);
29416
29417
29418
29419
29420
29421
29422 public function setStabilityFlags(array $stabilityFlags);
29423
29424
29425
29426
29427
29428
29429 public function setSuggests(array $suggests);
29430
29431
29432
29433
29434 public function setExtra(array $extra);
29435 }
29436 <?php
29437
29438
29439
29440
29441
29442
29443
29444
29445
29446
29447
29448 namespace Composer\Package\Version;
29449
29450 use Composer\Config;
29451 use Composer\Repository\Vcs\HgDriver;
29452 use Composer\IO\NullIO;
29453 use Composer\Semver\VersionParser as SemverVersionParser;
29454 use Composer\Util\Git as GitUtil;
29455 use Composer\Util\ProcessExecutor;
29456 use Composer\Util\Svn as SvnUtil;
29457
29458
29459
29460
29461
29462
29463
29464 class VersionGuesser
29465 {
29466
29467
29468
29469 private $config;
29470
29471
29472
29473
29474 private $process;
29475
29476
29477
29478
29479 private $versionParser;
29480
29481
29482
29483
29484
29485
29486 public function __construct(Config $config, ProcessExecutor $process, SemverVersionParser $versionParser)
29487 {
29488 $this->config = $config;
29489 $this->process = $process;
29490 $this->versionParser = $versionParser;
29491 }
29492
29493
29494
29495
29496
29497
29498
29499 public function guessVersion(array $packageConfig, $path)
29500 {
29501 if (function_exists('proc_open')) {
29502 $versionData = $this->guessGitVersion($packageConfig, $path);
29503 if (null !== $versionData && null !== $versionData['version']) {
29504 return $this->postprocess($versionData);
29505 }
29506
29507 $versionData = $this->guessHgVersion($packageConfig, $path);
29508 if (null !== $versionData && null !== $versionData['version']) {
29509 return $this->postprocess($versionData);
29510 }
29511
29512 $versionData = $this->guessFossilVersion($packageConfig, $path);
29513 if (null !== $versionData && null !== $versionData['version']) {
29514 return $this->postprocess($versionData);
29515 }
29516
29517 $versionData = $this->guessSvnVersion($packageConfig, $path);
29518 if (null !== $versionData && null !== $versionData['version']) {
29519 return $this->postprocess($versionData);
29520 }
29521 }
29522 }
29523
29524 private function postprocess(array $versionData)
29525 {
29526
29527  if ('dev-' !== substr($versionData['version'], 0, 4)) {
29528 $versionData['pretty_version'] = preg_replace('{(\.9{7})+}', '.x', $versionData['version']);
29529 }
29530
29531 return $versionData;
29532 }
29533
29534 private function guessGitVersion(array $packageConfig, $path)
29535 {
29536 GitUtil::cleanEnv();
29537 $commit = null;
29538 $version = null;
29539 $prettyVersion = null;
29540 $isDetached = false;
29541
29542
29543  if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output, $path)) {
29544 $branches = array();
29545 $isFeatureBranch = false;
29546
29547
29548  foreach ($this->process->splitLines($output) as $branch) {
29549 if ($branch && preg_match('{^(?:\* ) *(\(no branch\)|\(detached from \S+\)|\(HEAD detached at \S+\)|\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
29550 if ($match[1] === '(no branch)' || substr($match[1], 0, 10) === '(detached ' || substr($match[1], 0, 17) === '(HEAD detached at') {
29551 $version = 'dev-' . $match[2];
29552 $prettyVersion = $version;
29553 $isFeatureBranch = true;
29554 $isDetached = true;
29555 } else {
29556 $version = $this->versionParser->normalizeBranch($match[1]);
29557 $prettyVersion = 'dev-' . $match[1];
29558 $isFeatureBranch = 0 === strpos($version, 'dev-');
29559 if ('9999999-dev' === $version) {
29560 $version = $prettyVersion;
29561 }
29562 }
29563
29564 if ($match[2]) {
29565 $commit = $match[2];
29566 }
29567 }
29568
29569 if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
29570 if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
29571 $branches[] = $match[1];
29572 }
29573 }
29574 }
29575
29576 if ($isFeatureBranch) {
29577
29578  $result = $this->guessFeatureVersion($packageConfig, $version, $branches, 'git rev-list %candidate%..%branch%', $path);
29579 $version = $result['version'];
29580 $prettyVersion = $result['pretty_version'];
29581 }
29582 }
29583
29584 if (!$version || $isDetached) {
29585 $result = $this->versionFromGitTags($path);
29586 if ($result) {
29587 $version = $result['version'];
29588 $prettyVersion = $result['pretty_version'];
29589 }
29590 }
29591
29592 if (!$commit) {
29593 $command = 'git log --pretty="%H" -n1 HEAD';
29594 if (0 === $this->process->execute($command, $output, $path)) {
29595 $commit = trim($output) ?: null;
29596 }
29597 }
29598
29599 return array('version' => $version, 'commit' => $commit, 'pretty_version' => $prettyVersion);
29600 }
29601
29602 private function versionFromGitTags($path)
29603 {
29604
29605  if (0 === $this->process->execute('git describe --exact-match --tags', $output, $path)) {
29606 try {
29607 $version = $this->versionParser->normalize(trim($output));
29608
29609 return array('version' => $version, 'pretty_version' => trim($output));
29610 } catch (\Exception $e) {
29611 }
29612 }
29613
29614 return null;
29615 }
29616
29617 private function guessHgVersion(array $packageConfig, $path)
29618 {
29619
29620  if (0 === $this->process->execute('hg branch', $output, $path)) {
29621 $branch = trim($output);
29622 $version = $this->versionParser->normalizeBranch($branch);
29623 $isFeatureBranch = 0 === strpos($version, 'dev-');
29624
29625 if ('9999999-dev' === $version) {
29626 $version = 'dev-' . $branch;
29627 }
29628
29629 if (!$isFeatureBranch) {
29630 return array('version' => $version, 'commit' => null, 'pretty_version' => $version);
29631 }
29632
29633
29634  $driver = new HgDriver(array('url' => $path), new NullIO(), $this->config, $this->process);
29635 $branches = array_keys($driver->getBranches());
29636
29637
29638  $result = $this->guessFeatureVersion($packageConfig, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"', $path);
29639 $result['commit'] = '';
29640
29641 return $result;
29642 }
29643 }
29644
29645 private function guessFeatureVersion(array $packageConfig, $version, array $branches, $scmCmdline, $path)
29646 {
29647 $prettyVersion = $version;
29648
29649
29650  
29651  if ((isset($packageConfig['extra']['branch-alias']) && !isset($packageConfig['extra']['branch-alias'][$version]))
29652 || strpos(json_encode($packageConfig), '"self.version"')
29653 ) {
29654 $branch = preg_replace('{^dev-}', '', $version);
29655 $length = PHP_INT_MAX;
29656
29657 $nonFeatureBranches = '';
29658 if (!empty($packageConfig['non-feature-branches'])) {
29659 $nonFeatureBranches = implode('|', $packageConfig['non-feature-branches']);
29660 }
29661
29662 foreach ($branches as $candidate) {
29663
29664  if ($candidate === $branch && preg_match('{^(' . $nonFeatureBranches . ')$}', $candidate)) {
29665 break;
29666 }
29667
29668
29669  if ($candidate === $branch || !preg_match('{^(' . $nonFeatureBranches . '|master|trunk|default|develop|\d+\..+)$}', $candidate, $match)) {
29670 continue;
29671 }
29672
29673 $cmdLine = str_replace(array('%candidate%', '%branch%'), array($candidate, $branch), $scmCmdline);
29674 if (0 !== $this->process->execute($cmdLine, $output, $path)) {
29675 continue;
29676 }
29677
29678 if (strlen($output) < $length) {
29679 $length = strlen($output);
29680 $version = $this->versionParser->normalizeBranch($candidate);
29681 $prettyVersion = 'dev-' . $match[1];
29682 if ('9999999-dev' === $version) {
29683 $version = $prettyVersion;
29684 }
29685 }
29686 }
29687 }
29688
29689 return array('version' => $version, 'pretty_version' => $prettyVersion);
29690 }
29691
29692 private function guessFossilVersion(array $packageConfig, $path)
29693 {
29694 $version = null;
29695 $prettyVersion = null;
29696
29697
29698  if (0 === $this->process->execute('fossil branch list', $output, $path)) {
29699 $branch = trim($output);
29700 $version = $this->versionParser->normalizeBranch($branch);
29701 $prettyVersion = 'dev-' . $branch;
29702
29703 if ('9999999-dev' === $version) {
29704 $version = $prettyVersion;
29705 }
29706 }
29707
29708
29709  if (0 === $this->process->execute('fossil tag list', $output, $path)) {
29710 try {
29711 $version = $this->versionParser->normalize(trim($output));
29712 $prettyVersion = trim($output);
29713 } catch (\Exception $e) {
29714 }
29715 }
29716
29717 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
29718 }
29719
29720 private function guessSvnVersion(array $packageConfig, $path)
29721 {
29722 SvnUtil::cleanEnv();
29723
29724
29725  if (0 === $this->process->execute('svn info --xml', $output, $path)) {
29726 $trunkPath = isset($packageConfig['trunk-path']) ? preg_quote($packageConfig['trunk-path'], '#') : 'trunk';
29727 $branchesPath = isset($packageConfig['branches-path']) ? preg_quote($packageConfig['branches-path'], '#') : 'branches';
29728 $tagsPath = isset($packageConfig['tags-path']) ? preg_quote($packageConfig['tags-path'], '#') : 'tags';
29729
29730 $urlPattern = '#<url>.*/(' . $trunkPath . '|(' . $branchesPath . '|' . $tagsPath . ')/(.*))</url>#';
29731
29732 if (preg_match($urlPattern, $output, $matches)) {
29733 if (isset($matches[2]) && ($branchesPath === $matches[2] || $tagsPath === $matches[2])) {
29734
29735  $version = $this->versionParser->normalizeBranch($matches[3]);
29736 $prettyVersion = 'dev-' . $matches[3];
29737 if ('9999999-dev' === $version) {
29738 $version = $prettyVersion;
29739 }
29740
29741 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
29742 }
29743
29744 $prettyVersion = trim($matches[1]);
29745 $version = $this->versionParser->normalize($prettyVersion);
29746
29747 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
29748 }
29749 }
29750 }
29751 }
29752 <?php
29753
29754
29755
29756
29757
29758
29759
29760
29761
29762
29763
29764 namespace Composer\Package\Version;
29765
29766 use Composer\Repository\PlatformRepository;
29767 use Composer\Semver\VersionParser as SemverVersionParser;
29768
29769 class VersionParser extends SemverVersionParser
29770 {
29771 private static $constraints = array();
29772
29773
29774
29775
29776 public function parseConstraints($constraints)
29777 {
29778 if (!isset(self::$constraints[$constraints])) {
29779 self::$constraints[$constraints] = parent::parseConstraints($constraints);
29780 }
29781
29782 return self::$constraints[$constraints];
29783 }
29784
29785
29786
29787
29788
29789
29790
29791
29792
29793
29794
29795 public function parseNameVersionPairs(array $pairs)
29796 {
29797 $pairs = array_values($pairs);
29798 $result = array();
29799
29800 for ($i = 0, $count = count($pairs); $i < $count; $i++) {
29801 $pair = preg_replace('{^([^=: ]+)[=: ](.*)$}', '$1 $2', trim($pairs[$i]));
29802 if (false === strpos($pair, ' ') && isset($pairs[$i + 1]) && false === strpos($pairs[$i + 1], '/') && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $pairs[$i + 1])) {
29803 $pair .= ' '.$pairs[$i + 1];
29804 $i++;
29805 }
29806
29807 if (strpos($pair, ' ')) {
29808 list($name, $version) = explode(" ", $pair, 2);
29809 $result[] = array('name' => $name, 'version' => $version);
29810 } else {
29811 $result[] = array('name' => $pair);
29812 }
29813 }
29814
29815 return $result;
29816 }
29817 }
29818 <?php
29819
29820
29821
29822
29823
29824
29825
29826
29827
29828
29829
29830 namespace Composer\Package\Version;
29831
29832 use Composer\DependencyResolver\Pool;
29833 use Composer\Package\BasePackage;
29834 use Composer\Package\PackageInterface;
29835 use Composer\Package\Loader\ArrayLoader;
29836 use Composer\Package\Dumper\ArrayDumper;
29837 use Composer\Semver\Constraint\Constraint;
29838
29839
29840
29841
29842
29843
29844
29845 class VersionSelector
29846 {
29847 private $pool;
29848
29849 private $parser;
29850
29851 public function __construct(Pool $pool)
29852 {
29853 $this->pool = $pool;
29854 }
29855
29856
29857
29858
29859
29860
29861
29862
29863
29864
29865
29866 public function findBestCandidate($packageName, $targetPackageVersion = null, $targetPhpVersion = null, $preferredStability = 'stable')
29867 {
29868 $constraint = $targetPackageVersion ? $this->getParser()->parseConstraints($targetPackageVersion) : null;
29869 $candidates = $this->pool->whatProvides(strtolower($packageName), $constraint, true);
29870
29871 if ($targetPhpVersion) {
29872 $phpConstraint = new Constraint('==', $this->getParser()->normalize($targetPhpVersion));
29873 $candidates = array_filter($candidates, function ($pkg) use ($phpConstraint) {
29874 $reqs = $pkg->getRequires();
29875
29876 return !isset($reqs['php']) || $reqs['php']->getConstraint()->matches($phpConstraint);
29877 });
29878 }
29879
29880 if (!$candidates) {
29881 return false;
29882 }
29883
29884
29885  $package = reset($candidates);
29886 $minPriority = BasePackage::$stabilities[$preferredStability];
29887 foreach ($candidates as $candidate) {
29888 $candidatePriority = $candidate->getStabilityPriority();
29889 $currentPriority = $package->getStabilityPriority();
29890
29891
29892  
29893  if ($minPriority < $candidatePriority && $currentPriority < $candidatePriority) {
29894 continue;
29895 }
29896
29897
29898  
29899  if ($minPriority < $candidatePriority && $candidatePriority < $currentPriority) {
29900 $package = $candidate;
29901 continue;
29902 }
29903
29904
29905  
29906  if ($minPriority >= $candidatePriority && $minPriority < $currentPriority) {
29907 $package = $candidate;
29908 continue;
29909 }
29910
29911
29912  if (version_compare($package->getVersion(), $candidate->getVersion(), '<')) {
29913 $package = $candidate;
29914 }
29915 }
29916
29917 return $package;
29918 }
29919
29920
29921
29922
29923
29924
29925
29926
29927
29928
29929
29930
29931
29932
29933
29934
29935 public function findRecommendedRequireVersion(PackageInterface $package)
29936 {
29937 $version = $package->getVersion();
29938 if (!$package->isDev()) {
29939 return $this->transformVersion($version, $package->getPrettyVersion(), $package->getStability());
29940 }
29941
29942 $loader = new ArrayLoader($this->getParser());
29943 $dumper = new ArrayDumper();
29944 $extra = $loader->getBranchAlias($dumper->dump($package));
29945 if ($extra) {
29946 $extra = preg_replace('{^(\d+\.\d+\.\d+)(\.9999999)-dev$}', '$1.0', $extra, -1, $count);
29947 if ($count) {
29948 $extra = str_replace('.9999999', '.0', $extra);
29949
29950 return $this->transformVersion($extra, $extra, 'dev');
29951 }
29952 }
29953
29954 return $package->getPrettyVersion();
29955 }
29956
29957 private function transformVersion($version, $prettyVersion, $stability)
29958 {
29959
29960  
29961  $semanticVersionParts = explode('.', $version);
29962
29963
29964  if (count($semanticVersionParts) == 4 && preg_match('{^0\D?}', $semanticVersionParts[3])) {
29965
29966  if ($semanticVersionParts[0] === '0') {
29967 unset($semanticVersionParts[3]);
29968 } else {
29969 unset($semanticVersionParts[2], $semanticVersionParts[3]);
29970 }
29971 $version = implode('.', $semanticVersionParts);
29972 } else {
29973 return $prettyVersion;
29974 }
29975
29976
29977  if ($stability != 'stable') {
29978 $version .= '@'.$stability;
29979 }
29980
29981
29982  return '^' . $version;
29983 }
29984
29985 private function getParser()
29986 {
29987 if ($this->parser === null) {
29988 $this->parser = new VersionParser();
29989 }
29990
29991 return $this->parser;
29992 }
29993 }
29994 <?php
29995
29996
29997
29998
29999
30000
30001
30002
30003
30004
30005
30006 namespace Composer\Plugin\Capability;
30007
30008
30009
30010
30011
30012
30013
30014 interface Capability
30015 {
30016 }
30017 <?php
30018
30019
30020
30021
30022
30023
30024
30025
30026
30027
30028
30029 namespace Composer\Plugin\Capability;
30030
30031
30032
30033
30034
30035
30036
30037
30038
30039
30040
30041 interface CommandProvider extends Capability
30042 {
30043
30044
30045
30046
30047
30048 public function getCommands();
30049 }
30050 <?php
30051
30052
30053
30054
30055
30056
30057
30058
30059
30060
30061
30062 namespace Composer\Plugin;
30063
30064
30065
30066
30067
30068
30069
30070
30071 interface Capable
30072 {
30073
30074
30075
30076
30077
30078
30079
30080
30081
30082
30083
30084
30085
30086
30087
30088
30089
30090
30091 public function getCapabilities();
30092 }
30093 <?php
30094
30095
30096
30097
30098
30099
30100
30101
30102
30103
30104
30105 namespace Composer\Plugin;
30106
30107 use Composer\EventDispatcher\Event;
30108 use Symfony\Component\Console\Input\InputInterface;
30109 use Symfony\Component\Console\Output\OutputInterface;
30110
30111
30112
30113
30114
30115
30116 class CommandEvent extends Event
30117 {
30118
30119
30120
30121 private $commandName;
30122
30123
30124
30125
30126 private $input;
30127
30128
30129
30130
30131 private $output;
30132
30133
30134
30135
30136
30137
30138
30139
30140
30141
30142
30143 public function __construct($name, $commandName, $input, $output, array $args = array(), array $flags = array())
30144 {
30145 parent::__construct($name, $args, $flags);
30146 $this->commandName = $commandName;
30147 $this->input = $input;
30148 $this->output = $output;
30149 }
30150
30151
30152
30153
30154
30155
30156 public function getInput()
30157 {
30158 return $this->input;
30159 }
30160
30161
30162
30163
30164
30165
30166 public function getOutput()
30167 {
30168 return $this->output;
30169 }
30170
30171
30172
30173
30174
30175
30176 public function getCommandName()
30177 {
30178 return $this->commandName;
30179 }
30180 }
30181 <?php
30182
30183
30184
30185
30186
30187
30188
30189
30190
30191
30192
30193 namespace Composer\Plugin;
30194
30195
30196
30197
30198
30199
30200 class PluginEvents
30201 {
30202
30203
30204
30205
30206
30207
30208
30209
30210 const INIT = 'init';
30211
30212
30213
30214
30215
30216
30217
30218
30219
30220 const COMMAND = 'command';
30221
30222
30223
30224
30225
30226
30227
30228
30229
30230 const PRE_FILE_DOWNLOAD = 'pre-file-download';
30231 }
30232 <?php
30233
30234
30235
30236
30237
30238
30239
30240
30241
30242
30243
30244 namespace Composer\Plugin;
30245
30246 use Composer\Composer;
30247 use Composer\IO\IOInterface;
30248
30249
30250
30251
30252
30253
30254 interface PluginInterface
30255 {
30256
30257
30258
30259
30260
30261 const PLUGIN_API_VERSION = '1.1.0';
30262
30263
30264
30265
30266
30267
30268
30269 public function activate(Composer $composer, IOInterface $io);
30270 }
30271 <?php
30272
30273
30274
30275
30276
30277
30278
30279
30280
30281
30282
30283 namespace Composer\Plugin;
30284
30285 use Composer\Composer;
30286 use Composer\EventDispatcher\EventSubscriberInterface;
30287 use Composer\IO\IOInterface;
30288 use Composer\Package\Package;
30289 use Composer\Package\Version\VersionParser;
30290 use Composer\Repository\RepositoryInterface;
30291 use Composer\Package\AliasPackage;
30292 use Composer\Package\PackageInterface;
30293 use Composer\Package\Link;
30294 use Composer\Semver\Constraint\Constraint;
30295 use Composer\DependencyResolver\Pool;
30296 use Composer\Plugin\Capability\Capability;
30297
30298
30299
30300
30301
30302
30303
30304 class PluginManager
30305 {
30306 protected $composer;
30307 protected $io;
30308 protected $globalComposer;
30309 protected $versionParser;
30310 protected $disablePlugins = false;
30311
30312 protected $plugins = array();
30313 protected $registeredPlugins = array();
30314
30315 private static $classCounter = 0;
30316
30317
30318
30319
30320
30321
30322
30323
30324
30325 public function __construct(IOInterface $io, Composer $composer, Composer $globalComposer = null, $disablePlugins = false)
30326 {
30327 $this->io = $io;
30328 $this->composer = $composer;
30329 $this->globalComposer = $globalComposer;
30330 $this->versionParser = new VersionParser();
30331 $this->disablePlugins = $disablePlugins;
30332 }
30333
30334
30335
30336
30337 public function loadInstalledPlugins()
30338 {
30339 if ($this->disablePlugins) {
30340 return;
30341 }
30342
30343 $repo = $this->composer->getRepositoryManager()->getLocalRepository();
30344 $globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
30345 if ($repo) {
30346 $this->loadRepository($repo);
30347 }
30348 if ($globalRepo) {
30349 $this->loadRepository($globalRepo);
30350 }
30351 }
30352
30353
30354
30355
30356
30357
30358 public function getPlugins()
30359 {
30360 return $this->plugins;
30361 }
30362
30363
30364
30365
30366
30367
30368 public function getGlobalComposer()
30369 {
30370 return $this->globalComposer;
30371 }
30372
30373
30374
30375
30376
30377
30378
30379
30380
30381
30382
30383
30384 public function registerPackage(PackageInterface $package, $failOnMissingClasses = false)
30385 {
30386 if ($this->disablePlugins) {
30387 return;
30388 }
30389
30390 if ($package->getType() === 'composer-plugin') {
30391 $requiresComposer = null;
30392 foreach ($package->getRequires() as $link) { 
30393 if ('composer-plugin-api' === $link->getTarget()) {
30394 $requiresComposer = $link->getConstraint();
30395 break;
30396 }
30397 }
30398
30399 if (!$requiresComposer) {
30400 throw new \RuntimeException("Plugin ".$package->getName()." is missing a require statement for a version of the composer-plugin-api package.");
30401 }
30402
30403 $currentPluginApiVersion = $this->getPluginApiVersion();
30404 $currentPluginApiConstraint = new Constraint('==', $this->versionParser->normalize($currentPluginApiVersion));
30405
30406 if ($requiresComposer->getPrettyString() === '1.0.0' && $this->getPluginApiVersion() === '1.0.0') {
30407 $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>');
30408 } elseif (!$requiresComposer->matches($currentPluginApiConstraint)) {
30409 $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>');
30410
30411 return;
30412 }
30413 }
30414
30415 $oldInstallerPlugin = ($package->getType() === 'composer-installer');
30416
30417 if (in_array($package->getName(), $this->registeredPlugins)) {
30418 return;
30419 }
30420
30421 $extra = $package->getExtra();
30422 if (empty($extra['class'])) {
30423 throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
30424 }
30425 $classes = is_array($extra['class']) ? $extra['class'] : array($extra['class']);
30426
30427 $localRepo = $this->composer->getRepositoryManager()->getLocalRepository();
30428 $globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
30429
30430 $pool = new Pool('dev');
30431 $pool->addRepository($localRepo);
30432 if ($globalRepo) {
30433 $pool->addRepository($globalRepo);
30434 }
30435
30436 $autoloadPackages = array($package->getName() => $package);
30437 $autoloadPackages = $this->collectDependencies($pool, $autoloadPackages, $package);
30438
30439 $generator = $this->composer->getAutoloadGenerator();
30440 $autoloads = array();
30441 foreach ($autoloadPackages as $autoloadPackage) {
30442 $downloadPath = $this->getInstallPath($autoloadPackage, ($globalRepo && $globalRepo->hasPackage($autoloadPackage)));
30443 $autoloads[] = array($autoloadPackage, $downloadPath);
30444 }
30445
30446 $map = $generator->parseAutoloads($autoloads, new Package('dummy', '1.0.0.0', '1.0.0'));
30447 $classLoader = $generator->createLoader($map);
30448 $classLoader->register();
30449
30450 foreach ($classes as $class) {
30451 if (class_exists($class, false)) {
30452 $class = trim($class, '\\');
30453 $path = $classLoader->findFile($class);
30454 $code = file_get_contents($path);
30455 $separatorPos = strrpos($class, '\\');
30456 $className = $class;
30457 if ($separatorPos) {
30458 $className = substr($class, $separatorPos + 1);
30459 }
30460 $code = preg_replace('{^((?:final\s+)?(?:\s*))class\s+('.preg_quote($className).')}mi', '$1class $2_composer_tmp'.self::$classCounter, $code, 1);
30461 $code = str_replace('__FILE__', var_export($path, true), $code);
30462 $code = str_replace('__DIR__', var_export(dirname($path), true), $code);
30463 $code = str_replace('__CLASS__', var_export($class, true), $code);
30464 $code = preg_replace('/^\s*<\?(php)?/i', '', $code, 1);
30465 eval($code);
30466 $class .= '_composer_tmp'.self::$classCounter;
30467 self::$classCounter++;
30468 }
30469
30470 if ($oldInstallerPlugin) {
30471 $installer = new $class($this->io, $this->composer);
30472 $this->composer->getInstallationManager()->addInstaller($installer);
30473 } elseif (class_exists($class)) {
30474 $plugin = new $class();
30475 $this->addPlugin($plugin);
30476 $this->registeredPlugins[] = $package->getName();
30477 } elseif ($failOnMissingClasses) {
30478 throw new \UnexpectedValueException('Plugin '.$package->getName().' could not be initialized, class not found: '.$class);
30479 }
30480 }
30481 }
30482
30483
30484
30485
30486
30487
30488 protected function getPluginApiVersion()
30489 {
30490 return PluginInterface::PLUGIN_API_VERSION;
30491 }
30492
30493
30494
30495
30496
30497
30498
30499
30500
30501
30502 public function addPlugin(PluginInterface $plugin)
30503 {
30504 $this->io->writeError('Loading plugin '.get_class($plugin), true, IOInterface::DEBUG);
30505 $this->plugins[] = $plugin;
30506 $plugin->activate($this->composer, $this->io);
30507
30508 if ($plugin instanceof EventSubscriberInterface) {
30509 $this->composer->getEventDispatcher()->addSubscriber($plugin);
30510 }
30511 }
30512
30513
30514
30515
30516
30517
30518
30519
30520
30521
30522
30523
30524 private function loadRepository(RepositoryInterface $repo)
30525 {
30526 foreach ($repo->getPackages() as $package) { 
30527 if ($package instanceof AliasPackage) {
30528 continue;
30529 }
30530 if ('composer-plugin' === $package->getType()) {
30531 $this->registerPackage($package);
30532
30533  } elseif ('composer-installer' === $package->getType()) {
30534 $this->registerPackage($package);
30535 }
30536 }
30537 }
30538
30539
30540
30541
30542
30543
30544
30545
30546
30547
30548 private function collectDependencies(Pool $pool, array $collected, PackageInterface $package)
30549 {
30550 $requires = array_merge(
30551 $package->getRequires(),
30552 $package->getDevRequires()
30553 );
30554
30555 foreach ($requires as $requireLink) {
30556 $requiredPackage = $this->lookupInstalledPackage($pool, $requireLink);
30557 if ($requiredPackage && !isset($collected[$requiredPackage->getName()])) {
30558 $collected[$requiredPackage->getName()] = $requiredPackage;
30559 $collected = $this->collectDependencies($pool, $collected, $requiredPackage);
30560 }
30561 }
30562
30563 return $collected;
30564 }
30565
30566
30567
30568
30569
30570
30571
30572
30573
30574
30575
30576 private function lookupInstalledPackage(Pool $pool, Link $link)
30577 {
30578 $packages = $pool->whatProvides($link->getTarget(), $link->getConstraint());
30579
30580 return (!empty($packages)) ? $packages[0] : null;
30581 }
30582
30583
30584
30585
30586
30587
30588
30589
30590
30591 private function getInstallPath(PackageInterface $package, $global = false)
30592 {
30593 if (!$global) {
30594 return $this->composer->getInstallationManager()->getInstallPath($package);
30595 }
30596
30597 return $this->globalComposer->getInstallationManager()->getInstallPath($package);
30598 }
30599
30600
30601
30602
30603
30604
30605
30606 protected function getCapabilityImplementationClassName(PluginInterface $plugin, $capability)
30607 {
30608 if (!($plugin instanceof Capable)) {
30609 return null;
30610 }
30611
30612 $capabilities = (array) $plugin->getCapabilities();
30613
30614 if (!empty($capabilities[$capability]) && is_string($capabilities[$capability]) && trim($capabilities[$capability])) {
30615 return trim($capabilities[$capability]);
30616 }
30617
30618 if (
30619 array_key_exists($capability, $capabilities)
30620 && (empty($capabilities[$capability]) || !is_string($capabilities[$capability]) || !trim($capabilities[$capability]))
30621 ) {
30622 throw new \UnexpectedValueException('Plugin '.get_class($plugin).' provided invalid capability class name(s), got '.var_export($capabilities[$capability], 1));
30623 }
30624 }
30625
30626
30627
30628
30629
30630
30631
30632
30633
30634 public function getPluginCapability(PluginInterface $plugin, $capabilityClassName, array $ctorArgs = array())
30635 {
30636 if ($capabilityClass = $this->getCapabilityImplementationClassName($plugin, $capabilityClassName)) {
30637 if (!class_exists($capabilityClass)) {
30638 throw new \RuntimeException("Cannot instantiate Capability, as class $capabilityClass from plugin ".get_class($plugin)." does not exist.");
30639 }
30640
30641 $ctorArgs['plugin'] = $plugin;
30642 $capabilityObj = new $capabilityClass($ctorArgs);
30643
30644
30645  if (!$capabilityObj instanceof Capability || !$capabilityObj instanceof $capabilityClassName) {
30646 throw new \RuntimeException(
30647 'Class ' . $capabilityClass . ' must implement both Composer\Plugin\Capability\Capability and '. $capabilityClassName . '.'
30648 );
30649 }
30650
30651 return $capabilityObj;
30652 }
30653 }
30654
30655
30656
30657
30658
30659
30660
30661
30662 public function getPluginCapabilities($capabilityClassName, array $ctorArgs = array())
30663 {
30664 $capabilities = array();
30665 foreach ($this->getPlugins() as $plugin) {
30666 if ($capability = $this->getPluginCapability($plugin, $capabilityClassName, $ctorArgs)) {
30667 $capabilities[] = $capability;
30668 }
30669 }
30670
30671 return $capabilities;
30672 }
30673 }
30674 <?php
30675
30676
30677
30678
30679
30680
30681
30682
30683
30684
30685
30686 namespace Composer\Plugin;
30687
30688 use Composer\EventDispatcher\Event;
30689 use Composer\Util\RemoteFilesystem;
30690
30691
30692
30693
30694
30695
30696 class PreFileDownloadEvent extends Event
30697 {
30698
30699
30700
30701 private $rfs;
30702
30703
30704
30705
30706 private $processedUrl;
30707
30708
30709
30710
30711
30712
30713
30714
30715 public function __construct($name, RemoteFilesystem $rfs, $processedUrl)
30716 {
30717 parent::__construct($name);
30718 $this->rfs = $rfs;
30719 $this->processedUrl = $processedUrl;
30720 }
30721
30722
30723
30724
30725
30726
30727 public function getRemoteFilesystem()
30728 {
30729 return $this->rfs;
30730 }
30731
30732
30733
30734
30735
30736
30737 public function setRemoteFilesystem(RemoteFilesystem $rfs)
30738 {
30739 $this->rfs = $rfs;
30740 }
30741
30742
30743
30744
30745
30746
30747 public function getProcessedUrl()
30748 {
30749 return $this->processedUrl;
30750 }
30751 }
30752 <?php
30753
30754
30755
30756
30757
30758
30759
30760
30761
30762
30763
30764 namespace Composer\Question;
30765
30766 use Symfony\Component\Console\Exception\InvalidArgumentException;
30767 use Symfony\Component\Console\Question\Question;
30768
30769
30770
30771
30772
30773
30774
30775
30776 class StrictConfirmationQuestion extends Question
30777 {
30778 private $trueAnswerRegex;
30779 private $falseAnswerRegex;
30780
30781
30782
30783
30784
30785
30786
30787
30788
30789 public function __construct($question, $default = true, $trueAnswerRegex = '/^y(?:es)?$/i', $falseAnswerRegex = '/^no?$/i')
30790 {
30791 parent::__construct($question, (bool) $default);
30792
30793 $this->trueAnswerRegex = $trueAnswerRegex;
30794 $this->falseAnswerRegex = $falseAnswerRegex;
30795 $this->setNormalizer($this->getDefaultNormalizer());
30796 $this->setValidator($this->getDefaultValidator());
30797 }
30798
30799
30800
30801
30802
30803
30804 private function getDefaultNormalizer()
30805 {
30806 $default = $this->getDefault();
30807 $trueRegex = $this->trueAnswerRegex;
30808 $falseRegex = $this->falseAnswerRegex;
30809
30810 return function ($answer) use ($default, $trueRegex, $falseRegex) {
30811 if (is_bool($answer)) {
30812 return $answer;
30813 }
30814 if (empty($answer) && !empty($default)) {
30815 return $default;
30816 }
30817
30818 if (preg_match($trueRegex, $answer)) {
30819 return true;
30820 }
30821
30822 if (preg_match($falseRegex, $answer)) {
30823 return false;
30824 }
30825
30826 return null;
30827 };
30828 }
30829
30830
30831
30832
30833
30834
30835 private function getDefaultValidator()
30836 {
30837 return function ($answer) {
30838 if (!is_bool($answer)) {
30839 throw new InvalidArgumentException('Please answer yes, y, no, or n.');
30840 }
30841
30842 return $answer;
30843 };
30844 }
30845 }
30846 <?php
30847
30848
30849
30850
30851
30852
30853
30854
30855
30856
30857
30858 namespace Composer\Repository;
30859
30860 use Composer\Package\AliasPackage;
30861 use Composer\Package\PackageInterface;
30862 use Composer\Package\CompletePackageInterface;
30863 use Composer\Package\Version\VersionParser;
30864 use Composer\Semver\Constraint\ConstraintInterface;
30865 use Composer\Semver\Constraint\Constraint;
30866
30867
30868
30869
30870
30871
30872 class ArrayRepository extends BaseRepository
30873 {
30874
30875 protected $packages;
30876
30877 public function __construct(array $packages = array())
30878 {
30879 foreach ($packages as $package) {
30880 $this->addPackage($package);
30881 }
30882 }
30883
30884
30885
30886
30887 public function findPackage($name, $constraint)
30888 {
30889 $name = strtolower($name);
30890
30891 if (!$constraint instanceof ConstraintInterface) {
30892 $versionParser = new VersionParser();
30893 $constraint = $versionParser->parseConstraints($constraint);
30894 }
30895
30896 foreach ($this->getPackages() as $package) {
30897 if ($name === $package->getName()) {
30898 $pkgConstraint = new Constraint('==', $package->getVersion());
30899 if ($constraint->matches($pkgConstraint)) {
30900 return $package;
30901 }
30902 }
30903 }
30904
30905 return null;
30906 }
30907
30908
30909
30910
30911 public function findPackages($name, $constraint = null)
30912 {
30913
30914  $name = strtolower($name);
30915 $packages = array();
30916
30917 if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
30918 $versionParser = new VersionParser();
30919 $constraint = $versionParser->parseConstraints($constraint);
30920 }
30921
30922 foreach ($this->getPackages() as $package) {
30923 if ($name === $package->getName()) {
30924 $pkgConstraint = new Constraint('==', $package->getVersion());
30925 if (null === $constraint || $constraint->matches($pkgConstraint)) {
30926 $packages[] = $package;
30927 }
30928 }
30929 }
30930
30931 return $packages;
30932 }
30933
30934
30935
30936
30937 public function search($query, $mode = 0, $type = null)
30938 {
30939 $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
30940
30941 $matches = array();
30942 foreach ($this->getPackages() as $package) {
30943 $name = $package->getName();
30944 if (isset($matches[$name])) {
30945 continue;
30946 }
30947 if (preg_match($regex, $name)
30948 || ($mode === self::SEARCH_FULLTEXT && $package instanceof CompletePackageInterface && preg_match($regex, implode(' ', (array) $package->getKeywords()) . ' ' . $package->getDescription()))
30949 ) {
30950 if (null !== $type && $package->getType() !== $type) {
30951 continue;
30952 }
30953
30954 $matches[$name] = array(
30955 'name' => $package->getPrettyName(),
30956 'description' => $package instanceof CompletePackageInterface ? $package->getDescription() : null,
30957 );
30958 }
30959 }
30960
30961 return array_values($matches);
30962 }
30963
30964
30965
30966
30967 public function hasPackage(PackageInterface $package)
30968 {
30969 $packageId = $package->getUniqueName();
30970
30971 foreach ($this->getPackages() as $repoPackage) {
30972 if ($packageId === $repoPackage->getUniqueName()) {
30973 return true;
30974 }
30975 }
30976
30977 return false;
30978 }
30979
30980
30981
30982
30983
30984
30985 public function addPackage(PackageInterface $package)
30986 {
30987 if (null === $this->packages) {
30988 $this->initialize();
30989 }
30990 $package->setRepository($this);
30991 $this->packages[] = $package;
30992
30993 if ($package instanceof AliasPackage) {
30994 $aliasedPackage = $package->getAliasOf();
30995 if (null === $aliasedPackage->getRepository()) {
30996 $this->addPackage($aliasedPackage);
30997 }
30998 }
30999 }
31000
31001 protected function createAliasPackage(PackageInterface $package, $alias, $prettyAlias)
31002 {
31003 return new AliasPackage($package instanceof AliasPackage ? $package->getAliasOf() : $package, $alias, $prettyAlias);
31004 }
31005
31006
31007
31008
31009
31010
31011 public function removePackage(PackageInterface $package)
31012 {
31013 $packageId = $package->getUniqueName();
31014
31015 foreach ($this->getPackages() as $key => $repoPackage) {
31016 if ($packageId === $repoPackage->getUniqueName()) {
31017 array_splice($this->packages, $key, 1);
31018
31019 return;
31020 }
31021 }
31022 }
31023
31024
31025
31026
31027 public function getPackages()
31028 {
31029 if (null === $this->packages) {
31030 $this->initialize();
31031 }
31032
31033 return $this->packages;
31034 }
31035
31036
31037
31038
31039
31040
31041 public function count()
31042 {
31043 return count($this->packages);
31044 }
31045
31046
31047
31048
31049 protected function initialize()
31050 {
31051 $this->packages = array();
31052 }
31053 }
31054 <?php
31055
31056
31057
31058
31059
31060
31061
31062
31063
31064
31065
31066 namespace Composer\Repository;
31067
31068 use Composer\IO\IOInterface;
31069 use Composer\Json\JsonFile;
31070 use Composer\Package\Loader\ArrayLoader;
31071 use Composer\Package\Loader\LoaderInterface;
31072
31073
31074
31075
31076 class ArtifactRepository extends ArrayRepository implements ConfigurableRepositoryInterface
31077 {
31078
31079 protected $loader;
31080
31081 protected $lookup;
31082 protected $repoConfig;
31083 private $io;
31084
31085 public function __construct(array $repoConfig, IOInterface $io)
31086 {
31087 parent::__construct();
31088 if (!extension_loaded('zip')) {
31089 throw new \RuntimeException('The artifact repository requires PHP\'s zip extension');
31090 }
31091
31092 $this->loader = new ArrayLoader();
31093 $this->lookup = $repoConfig['url'];
31094 $this->io = $io;
31095 $this->repoConfig = $repoConfig;
31096 }
31097
31098 public function getRepoConfig()
31099 {
31100 return $this->repoConfig;
31101 }
31102
31103 protected function initialize()
31104 {
31105 parent::initialize();
31106
31107 $this->scanDirectory($this->lookup);
31108 }
31109
31110 private function scanDirectory($path)
31111 {
31112 $io = $this->io;
31113
31114 $directory = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS);
31115 $iterator = new \RecursiveIteratorIterator($directory);
31116 $regex = new \RegexIterator($iterator, '/^.+\.(zip|phar)$/i');
31117 foreach ($regex as $file) {
31118
31119 if (!$file->isFile()) {
31120 continue;
31121 }
31122
31123 $package = $this->getComposerInformation($file);
31124 if (!$package) {
31125 $io->writeError("File <comment>{$file->getBasename()}</comment> doesn't seem to hold a package", true, IOInterface::VERBOSE);
31126 continue;
31127 }
31128
31129 $template = 'Found package <info>%s</info> (<comment>%s</comment>) in file <info>%s</info>';
31130 $io->writeError(sprintf($template, $package->getName(), $package->getPrettyVersion(), $file->getBasename()), true, IOInterface::VERBOSE);
31131
31132 $this->addPackage($package);
31133 }
31134 }
31135
31136
31137
31138
31139
31140
31141
31142
31143 private function locateFile(\ZipArchive $zip, $filename)
31144 {
31145 $indexOfShortestMatch = false;
31146 $lengthOfShortestMatch = -1;
31147
31148 for ($i = 0; $i < $zip->numFiles; $i++) {
31149 $stat = $zip->statIndex($i);
31150 if (strcmp(basename($stat['name']), $filename) === 0) {
31151 $directoryName = dirname($stat['name']);
31152 if ($directoryName == '.') {
31153
31154  
31155  return $i;
31156 }
31157
31158 if (strpos($directoryName, '\\') !== false ||
31159 strpos($directoryName, '/') !== false) {
31160
31161  continue;
31162 }
31163
31164 $length = strlen($stat['name']);
31165 if ($indexOfShortestMatch === false || $length < $lengthOfShortestMatch) {
31166
31167  $contents = $zip->getFromIndex($i);
31168 if ($contents !== false) {
31169 $indexOfShortestMatch = $i;
31170 $lengthOfShortestMatch = $length;
31171 }
31172 }
31173 }
31174 }
31175
31176 return $indexOfShortestMatch;
31177 }
31178
31179 private function getComposerInformation(\SplFileInfo $file)
31180 {
31181 $zip = new \ZipArchive();
31182 $zip->open($file->getPathname());
31183
31184 if (0 == $zip->numFiles) {
31185 return false;
31186 }
31187
31188 $foundFileIndex = $this->locateFile($zip, 'composer.json');
31189 if (false === $foundFileIndex) {
31190 return false;
31191 }
31192
31193 $configurationFileName = $zip->getNameIndex($foundFileIndex);
31194
31195 $composerFile = "zip://{$file->getPathname()}#$configurationFileName";
31196 $json = file_get_contents($composerFile);
31197
31198 $package = JsonFile::parseJson($json, $composerFile);
31199 $package['dist'] = array(
31200 'type' => 'zip',
31201 'url' => strtr($file->getPathname(), '\\', '/'),
31202 'shasum' => sha1_file($file->getRealPath()),
31203 );
31204
31205 try {
31206 $package = $this->loader->load($package);
31207 } catch (\UnexpectedValueException $e) {
31208 throw new \UnexpectedValueException('Failed loading package in '.$file.': '.$e->getMessage(), 0, $e);
31209 }
31210
31211 return $package;
31212 }
31213 }
31214 <?php
31215
31216
31217
31218
31219
31220
31221
31222
31223
31224
31225
31226 namespace Composer\Repository;
31227
31228 use Composer\Package\RootPackageInterface;
31229 use Composer\Semver\Constraint\ConstraintInterface;
31230 use Composer\Semver\Constraint\Constraint;
31231 use Composer\Package\Link;
31232
31233
31234
31235
31236
31237
31238 abstract class BaseRepository implements RepositoryInterface
31239 {
31240
31241
31242
31243
31244
31245
31246
31247
31248
31249
31250
31251
31252
31253 public function getDependents($needle, $constraint = null, $invert = false, $recurse = true, $packagesFound = null)
31254 {
31255 $needles = (array) $needle;
31256 $results = array();
31257
31258
31259  if (null === $packagesFound) {
31260 $packagesFound = $needles;
31261 }
31262
31263
31264  $rootPackage = null;
31265 foreach ($this->getPackages() as $package) {
31266 if ($package instanceof RootPackageInterface) {
31267 $rootPackage = $package;
31268 break;
31269 }
31270 }
31271
31272
31273  foreach ($this->getPackages() as $package) {
31274 $links = $package->getRequires();
31275
31276
31277  
31278  $packagesInTree = $packagesFound;
31279
31280
31281  if (!$invert) {
31282 $links += $package->getReplaces();
31283 }
31284
31285
31286  if ($package instanceof RootPackageInterface) {
31287 $links += $package->getDevRequires();
31288 }
31289
31290
31291  foreach ($links as $link) {
31292 foreach ($needles as $needle) {
31293 if ($link->getTarget() === $needle) {
31294 if (is_null($constraint) || (($link->getConstraint()->matches($constraint) === !$invert))) {
31295
31296  if (in_array($link->getSource(), $packagesInTree)) {
31297 $results[$link->getSource()] = array($package, $link, false);
31298 continue;
31299 }
31300 $packagesInTree[] = $link->getSource();
31301 $dependents = $recurse ? $this->getDependents($link->getSource(), null, false, true, $packagesInTree) : array();
31302 $results[$link->getSource()] = array($package, $link, $dependents);
31303 }
31304 }
31305 }
31306 }
31307
31308
31309  if ($invert && in_array($package->getName(), $needles)) {
31310 foreach ($package->getConflicts() as $link) {
31311 foreach ($this->findPackages($link->getTarget()) as $pkg) {
31312 $version = new Constraint('=', $pkg->getVersion());
31313 if ($link->getConstraint()->matches($version) === $invert) {
31314 $results[] = array($package, $link, false);
31315 }
31316 }
31317 }
31318 }
31319
31320
31321  if ($invert && $constraint && in_array($package->getName(), $needles) && $constraint->matches(new Constraint('=', $package->getVersion()))) {
31322 foreach ($package->getRequires() as $link) {
31323 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
31324 if ($this->findPackage($link->getTarget(), $link->getConstraint())) {
31325 continue;
31326 }
31327
31328 $platformPkg = $this->findPackage($link->getTarget(), '*');
31329 $description = $platformPkg ? 'but '.$platformPkg->getPrettyVersion().' is installed' : 'but it is missing';
31330 $results[] = array($package, new Link($package->getName(), $link->getTarget(), null, 'requires', $link->getPrettyConstraint().' '.$description), false);
31331
31332 continue;
31333 }
31334
31335 foreach ($this->getPackages() as $pkg) {
31336 if (!in_array($link->getTarget(), $pkg->getNames())) {
31337 continue;
31338 }
31339
31340 $version = new Constraint('=', $pkg->getVersion());
31341 if (!$link->getConstraint()->matches($version)) {
31342
31343  
31344  if ($rootPackage) {
31345 foreach (array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()) as $rootReq) {
31346 if (in_array($rootReq->getTarget(), $pkg->getNames()) && !$rootReq->getConstraint()->matches($link->getConstraint())) {
31347 $results[] = array($package, $link, false);
31348 $results[] = array($rootPackage, $rootReq, false);
31349 continue 3;
31350 }
31351 }
31352 $results[] = array($package, $link, false);
31353 $results[] = array($rootPackage, new Link($rootPackage->getName(), $link->getTarget(), null, 'does not require', 'but ' . $pkg->getPrettyVersion() . ' is installed'), false);
31354 } else {
31355
31356  $results[] = array($package, $link, false);
31357 }
31358 }
31359
31360 continue 2;
31361 }
31362 }
31363 }
31364 }
31365
31366 ksort($results);
31367
31368 return $results;
31369 }
31370 }
31371 <?php
31372
31373
31374
31375
31376
31377
31378
31379
31380
31381
31382
31383 namespace Composer\Repository;
31384
31385 use Composer\Package\Loader\ArrayLoader;
31386 use Composer\Package\PackageInterface;
31387 use Composer\Package\AliasPackage;
31388 use Composer\Package\Version\VersionParser;
31389 use Composer\DependencyResolver\Pool;
31390 use Composer\Json\JsonFile;
31391 use Composer\Cache;
31392 use Composer\Config;
31393 use Composer\Factory;
31394 use Composer\IO\IOInterface;
31395 use Composer\Util\RemoteFilesystem;
31396 use Composer\Plugin\PluginEvents;
31397 use Composer\Plugin\PreFileDownloadEvent;
31398 use Composer\EventDispatcher\EventDispatcher;
31399 use Composer\Downloader\TransportException;
31400 use Composer\Semver\Constraint\ConstraintInterface;
31401 use Composer\Semver\Constraint\Constraint;
31402
31403
31404
31405
31406 class ComposerRepository extends ArrayRepository implements ConfigurableRepositoryInterface
31407 {
31408 protected $config;
31409 protected $repoConfig;
31410 protected $options;
31411 protected $url;
31412 protected $baseUrl;
31413 protected $io;
31414 protected $rfs;
31415 protected $cache;
31416 protected $notifyUrl;
31417 protected $searchUrl;
31418 protected $hasProviders = false;
31419 protected $providersUrl;
31420 protected $lazyProvidersUrl;
31421 protected $providerListing;
31422 protected $providers = array();
31423 protected $providersByUid = array();
31424 protected $loader;
31425 protected $rootAliases;
31426 protected $allowSslDowngrade = false;
31427 protected $eventDispatcher;
31428 protected $sourceMirrors;
31429 protected $distMirrors;
31430 private $degradedMode = false;
31431 private $rootData;
31432 private $hasPartialPackages;
31433 private $partialPackagesByName;
31434
31435 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
31436 {
31437 parent::__construct();
31438 if (!preg_match('{^[\w.]+\??://}', $repoConfig['url'])) {
31439
31440  $repoConfig['url'] = 'http://'.$repoConfig['url'];
31441 }
31442 $repoConfig['url'] = rtrim($repoConfig['url'], '/');
31443
31444 if ('https?' === substr($repoConfig['url'], 0, 6)) {
31445 $repoConfig['url'] = (extension_loaded('openssl') ? 'https' : 'http') . substr($repoConfig['url'], 6);
31446 }
31447
31448 $urlBits = parse_url($repoConfig['url']);
31449 if ($urlBits === false || empty($urlBits['scheme'])) {
31450 throw new \UnexpectedValueException('Invalid url given for Composer repository: '.$repoConfig['url']);
31451 }
31452
31453 if (!isset($repoConfig['options'])) {
31454 $repoConfig['options'] = array();
31455 }
31456 if (isset($repoConfig['allow_ssl_downgrade']) && true === $repoConfig['allow_ssl_downgrade']) {
31457 $this->allowSslDowngrade = true;
31458 }
31459
31460 $this->config = $config;
31461 $this->options = $repoConfig['options'];
31462 $this->url = $repoConfig['url'];
31463 $this->baseUrl = rtrim(preg_replace('{(?:/[^/\\\\]+\.json)?(?:[?#].*)?$}', '', $this->url), '/');
31464 $this->io = $io;
31465 $this->cache = new Cache($io, $config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url), 'a-z0-9.$');
31466 $this->loader = new ArrayLoader();
31467 if ($rfs && $this->options) {
31468 $rfs = clone $rfs;
31469 $rfs->setOptions($this->options);
31470 }
31471 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $this->config, $this->options);
31472 $this->eventDispatcher = $eventDispatcher;
31473 $this->repoConfig = $repoConfig;
31474 }
31475
31476 public function getRepoConfig()
31477 {
31478 return $this->repoConfig;
31479 }
31480
31481 public function setRootAliases(array $rootAliases)
31482 {
31483 $this->rootAliases = $rootAliases;
31484 }
31485
31486
31487
31488
31489 public function findPackage($name, $constraint)
31490 {
31491 if (!$this->hasProviders()) {
31492 return parent::findPackage($name, $constraint);
31493 }
31494
31495 $name = strtolower($name);
31496 if (!$constraint instanceof ConstraintInterface) {
31497 $versionParser = new VersionParser();
31498 $constraint = $versionParser->parseConstraints($constraint);
31499 }
31500
31501 foreach ($this->getProviderNames() as $providerName) {
31502 if ($name === $providerName) {
31503 $packages = $this->whatProvides(new Pool('dev'), $providerName);
31504 foreach ($packages as $package) {
31505 if ($name === $package->getName()) {
31506 $pkgConstraint = new Constraint('==', $package->getVersion());
31507 if ($constraint->matches($pkgConstraint)) {
31508 return $package;
31509 }
31510 }
31511 }
31512 break;
31513 }
31514 }
31515 }
31516
31517
31518
31519
31520 public function findPackages($name, $constraint = null)
31521 {
31522 if (!$this->hasProviders()) {
31523 return parent::findPackages($name, $constraint);
31524 }
31525
31526  $name = strtolower($name);
31527
31528 if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
31529 $versionParser = new VersionParser();
31530 $constraint = $versionParser->parseConstraints($constraint);
31531 }
31532
31533 $packages = array();
31534
31535 foreach ($this->getProviderNames() as $providerName) {
31536 if ($name === $providerName) {
31537 $candidates = $this->whatProvides(new Pool('dev'), $providerName);
31538 foreach ($candidates as $package) {
31539 if ($name === $package->getName()) {
31540 $pkgConstraint = new Constraint('==', $package->getVersion());
31541 if (null === $constraint || $constraint->matches($pkgConstraint)) {
31542 $packages[] = $package;
31543 }
31544 }
31545 }
31546 break;
31547 }
31548 }
31549
31550 return $packages;
31551 }
31552
31553 public function getPackages()
31554 {
31555 if ($this->hasProviders()) {
31556 throw new \LogicException('Composer repositories that have providers can not load the complete list of packages, use getProviderNames instead.');
31557 }
31558
31559 return parent::getPackages();
31560 }
31561
31562
31563
31564
31565 public function search($query, $mode = 0, $type = null)
31566 {
31567 $this->loadRootServerFile();
31568
31569 if ($this->searchUrl && $mode === self::SEARCH_FULLTEXT) {
31570 $url = str_replace(array('%query%', '%type%'), array($query, $type), $this->searchUrl);
31571
31572 $hostname = parse_url($url, PHP_URL_HOST) ?: $url;
31573 $json = $this->rfs->getContents($hostname, $url, false);
31574 $results = JsonFile::parseJson($json, $url);
31575
31576 return $results['results'];
31577 }
31578
31579 if ($this->hasProviders()) {
31580 $results = array();
31581 $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
31582
31583 foreach ($this->getProviderNames() as $name) {
31584 if (preg_match($regex, $name)) {
31585 $results[] = array('name' => $name);
31586 }
31587 }
31588
31589 return $results;
31590 }
31591
31592 return parent::search($query, $mode);
31593 }
31594
31595 public function getProviderNames()
31596 {
31597 $this->loadRootServerFile();
31598
31599 if (null === $this->providerListing) {
31600 $this->loadProviderListings($this->loadRootServerFile());
31601 }
31602
31603 if ($this->lazyProvidersUrl) {
31604
31605  return array();
31606 }
31607
31608 if ($this->providersUrl) {
31609 return array_keys($this->providerListing);
31610 }
31611
31612 return array();
31613 }
31614
31615 protected function configurePackageTransportOptions(PackageInterface $package)
31616 {
31617 foreach ($package->getDistUrls() as $url) {
31618 if (strpos($url, $this->baseUrl) === 0) {
31619 $package->setTransportOptions($this->options);
31620
31621 return;
31622 }
31623 }
31624 }
31625
31626 public function hasProviders()
31627 {
31628 $this->loadRootServerFile();
31629
31630 return $this->hasProviders;
31631 }
31632
31633 public function resetPackageIds()
31634 {
31635 foreach ($this->providersByUid as $package) {
31636 if ($package instanceof AliasPackage) {
31637 $package->getAliasOf()->setId(-1);
31638 }
31639 $package->setId(-1);
31640 }
31641 }
31642
31643
31644
31645
31646
31647
31648
31649 public function whatProvides(Pool $pool, $name, $bypassFilters = false)
31650 {
31651 if (isset($this->providers[$name]) && !$bypassFilters) {
31652 return $this->providers[$name];
31653 }
31654
31655 if ($this->hasPartialPackages && null === $this->partialPackagesByName) {
31656 $this->initializePartialPackages();
31657 }
31658
31659 if (!$this->hasPartialPackages || !isset($this->partialPackagesByName[$name])) {
31660
31661  if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name) || '__root__' === $name || 'composer-plugin-api' === $name) {
31662 return array();
31663 }
31664
31665 if (null === $this->providerListing) {
31666 $this->loadProviderListings($this->loadRootServerFile());
31667 }
31668
31669 $useLastModifiedCheck = false;
31670 if ($this->lazyProvidersUrl && !isset($this->providerListing[$name])) {
31671 $hash = null;
31672 $url = str_replace('%package%', $name, $this->lazyProvidersUrl);
31673 $cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
31674 $useLastModifiedCheck = true;
31675 } elseif ($this->providersUrl) {
31676
31677  if (!isset($this->providerListing[$name])) {
31678 return array();
31679 }
31680
31681 $hash = $this->providerListing[$name]['sha256'];
31682 $url = str_replace(array('%package%', '%hash%'), array($name, $hash), $this->providersUrl);
31683 $cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
31684 } else {
31685 return array();
31686 }
31687
31688 $packages = null;
31689 if ($cacheKey) {
31690 if (!$useLastModifiedCheck && $hash && $this->cache->sha256($cacheKey) === $hash) {
31691 $packages = json_decode($this->cache->read($cacheKey), true);
31692 } elseif ($useLastModifiedCheck) {
31693 if ($contents = $this->cache->read($cacheKey)) {
31694 $contents = json_decode($contents, true);
31695 if (isset($contents['last-modified'])) {
31696 $response = $this->fetchFileIfLastModified($url, $cacheKey, $contents['last-modified']);
31697 if (true === $response) {
31698 $packages = $contents;
31699 } elseif ($response) {
31700 $packages = $response;
31701 }
31702 }
31703 }
31704 }
31705 }
31706
31707 if (!$packages) {
31708 try {
31709 $packages = $this->fetchFile($url, $cacheKey, $hash, $useLastModifiedCheck);
31710 } catch (TransportException $e) {
31711
31712  if ($e->getStatusCode() === 404 && $this->lazyProvidersUrl) {
31713 $packages = array('packages' => array());
31714 } else {
31715 throw $e;
31716 }
31717 }
31718 }
31719
31720 $loadingPartialPackage = false;
31721 } else {
31722 $packages = array('packages' => array('versions' => $this->partialPackagesByName[$name]));
31723 $loadingPartialPackage = true;
31724 }
31725
31726 $this->providers[$name] = array();
31727 foreach ($packages['packages'] as $versions) {
31728 foreach ($versions as $version) {
31729 if (!$loadingPartialPackage && $this->hasPartialPackages && isset($this->partialPackagesByName[$version['name']])) {
31730 continue;
31731 }
31732
31733
31734  if (isset($this->providersByUid[$version['uid']])) {
31735
31736  if (!isset($this->providers[$name][$version['uid']])) {
31737
31738  if ($this->providersByUid[$version['uid']] instanceof AliasPackage) {
31739 $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']]->getAliasOf();
31740 $this->providers[$name][$version['uid'].'-alias'] = $this->providersByUid[$version['uid']];
31741 } else {
31742 $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']];
31743 }
31744
31745  if (isset($this->providersByUid[$version['uid'].'-root'])) {
31746 $this->providers[$name][$version['uid'].'-root'] = $this->providersByUid[$version['uid'].'-root'];
31747 }
31748 }
31749 } else {
31750 if (!$bypassFilters && !$pool->isPackageAcceptable(strtolower($version['name']), VersionParser::parseStability($version['version']))) {
31751 continue;
31752 }
31753
31754
31755  $package = $this->createPackage($version, 'Composer\Package\CompletePackage');
31756 $package->setRepository($this);
31757
31758 if ($package instanceof AliasPackage) {
31759 $aliased = $package->getAliasOf();
31760 $aliased->setRepository($this);
31761
31762 $this->providers[$name][$version['uid']] = $aliased;
31763 $this->providers[$name][$version['uid'].'-alias'] = $package;
31764
31765
31766  $this->providersByUid[$version['uid']] = $package;
31767 } else {
31768 $this->providers[$name][$version['uid']] = $package;
31769 $this->providersByUid[$version['uid']] = $package;
31770 }
31771
31772
31773  unset($rootAliasData);
31774
31775 if (isset($this->rootAliases[$package->getName()][$package->getVersion()])) {
31776 $rootAliasData = $this->rootAliases[$package->getName()][$package->getVersion()];
31777 } elseif ($package instanceof AliasPackage && isset($this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()])) {
31778 $rootAliasData = $this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()];
31779 }
31780
31781 if (isset($rootAliasData)) {
31782 $alias = $this->createAliasPackage($package, $rootAliasData['alias_normalized'], $rootAliasData['alias']);
31783 $alias->setRepository($this);
31784
31785 $this->providers[$name][$version['uid'].'-root'] = $alias;
31786 $this->providersByUid[$version['uid'].'-root'] = $alias;
31787 }
31788 }
31789 }
31790 }
31791
31792 $result = $this->providers[$name];
31793
31794
31795  
31796  if ($bypassFilters) {
31797 foreach ($this->providers[$name] as $uid => $provider) {
31798 unset($this->providersByUid[$uid]);
31799 }
31800 unset($this->providers[$name]);
31801 }
31802
31803 return $result;
31804 }
31805
31806
31807
31808
31809 protected function initialize()
31810 {
31811 parent::initialize();
31812
31813 $repoData = $this->loadDataFromServer();
31814
31815 foreach ($repoData as $package) {
31816 $this->addPackage($this->createPackage($package, 'Composer\Package\CompletePackage'));
31817 }
31818 }
31819
31820
31821
31822
31823
31824
31825 public function addPackage(PackageInterface $package)
31826 {
31827 parent::addPackage($package);
31828 $this->configurePackageTransportOptions($package);
31829 }
31830
31831 protected function loadRootServerFile()
31832 {
31833 if (null !== $this->rootData) {
31834 return $this->rootData;
31835 }
31836
31837 if (!extension_loaded('openssl') && 'https' === substr($this->url, 0, 5)) {
31838 throw new \RuntimeException('You must enable the openssl extension in your php.ini to load information from '.$this->url);
31839 }
31840
31841 $jsonUrlParts = parse_url($this->url);
31842
31843 if (isset($jsonUrlParts['path']) && false !== strpos($jsonUrlParts['path'], '.json')) {
31844 $jsonUrl = $this->url;
31845 } else {
31846 $jsonUrl = $this->url . '/packages.json';
31847 }
31848
31849 $data = $this->fetchFile($jsonUrl, 'packages.json');
31850
31851 if (!empty($data['notify-batch'])) {
31852 $this->notifyUrl = $this->canonicalizeUrl($data['notify-batch']);
31853 } elseif (!empty($data['notify'])) {
31854 $this->notifyUrl = $this->canonicalizeUrl($data['notify']);
31855 }
31856
31857 if (!empty($data['search'])) {
31858 $this->searchUrl = $this->canonicalizeUrl($data['search']);
31859 }
31860
31861 if (!empty($data['mirrors'])) {
31862 foreach ($data['mirrors'] as $mirror) {
31863 if (!empty($mirror['git-url'])) {
31864 $this->sourceMirrors['git'][] = array('url' => $mirror['git-url'], 'preferred' => !empty($mirror['preferred']));
31865 }
31866 if (!empty($mirror['hg-url'])) {
31867 $this->sourceMirrors['hg'][] = array('url' => $mirror['hg-url'], 'preferred' => !empty($mirror['preferred']));
31868 }
31869 if (!empty($mirror['dist-url'])) {
31870 $this->distMirrors[] = array(
31871 'url' => $this->canonicalizeUrl($mirror['dist-url']),
31872 'preferred' => !empty($mirror['preferred']),
31873 );
31874 }
31875 }
31876 }
31877
31878 if (!empty($data['providers-lazy-url'])) {
31879 $this->lazyProvidersUrl = $this->canonicalizeUrl($data['providers-lazy-url']);
31880 $this->hasProviders = true;
31881
31882 $this->hasPartialPackages = !empty($data['packages']) && is_array($data['packages']);
31883 }
31884
31885 if ($this->allowSslDowngrade) {
31886 $this->url = str_replace('https://', 'http://', $this->url);
31887 $this->baseUrl = str_replace('https://', 'http://', $this->baseUrl);
31888 }
31889
31890 if (!empty($data['providers-url'])) {
31891 $this->providersUrl = $this->canonicalizeUrl($data['providers-url']);
31892 $this->hasProviders = true;
31893 }
31894
31895 if (!empty($data['providers']) || !empty($data['providers-includes'])) {
31896 $this->hasProviders = true;
31897 }
31898
31899
31900  if (preg_match('{^https?://packagist.org/?$}i', $this->url) && !empty($this->repoConfig['force-lazy-providers'])) {
31901 $this->url = 'https://packagist.org';
31902 $this->baseUrl = 'https://packagist.org';
31903 $this->lazyProvidersUrl = $this->canonicalizeUrl('https://packagist.org/p/%package%.json');
31904 $this->providersUrl = null;
31905 } elseif (!empty($this->repoConfig['force-lazy-providers'])) {
31906 $this->lazyProvidersUrl = $this->canonicalizeUrl('/p/%package%.json');
31907 $this->providersUrl = null;
31908 }
31909
31910 return $this->rootData = $data;
31911 }
31912
31913 protected function canonicalizeUrl($url)
31914 {
31915 if ('/' === $url[0]) {
31916 return preg_replace('{(https?://[^/]+).*}i', '$1' . $url, $this->url);
31917 }
31918
31919 return $url;
31920 }
31921
31922 protected function loadDataFromServer()
31923 {
31924 $data = $this->loadRootServerFile();
31925
31926 return $this->loadIncludes($data);
31927 }
31928
31929 protected function loadProviderListings($data)
31930 {
31931 if (isset($data['providers'])) {
31932 if (!is_array($this->providerListing)) {
31933 $this->providerListing = array();
31934 }
31935 $this->providerListing = array_merge($this->providerListing, $data['providers']);
31936 }
31937
31938 if ($this->providersUrl && isset($data['provider-includes'])) {
31939 $includes = $data['provider-includes'];
31940 foreach ($includes as $include => $metadata) {
31941 $url = $this->baseUrl . '/' . str_replace('%hash%', $metadata['sha256'], $include);
31942 $cacheKey = str_replace(array('%hash%','$'), '', $include);
31943 if ($this->cache->sha256($cacheKey) === $metadata['sha256']) {
31944 $includedData = json_decode($this->cache->read($cacheKey), true);
31945 } else {
31946 $includedData = $this->fetchFile($url, $cacheKey, $metadata['sha256']);
31947 }
31948
31949 $this->loadProviderListings($includedData);
31950 }
31951 }
31952 }
31953
31954 protected function loadIncludes($data)
31955 {
31956 $packages = array();
31957
31958
31959  if (!isset($data['packages']) && !isset($data['includes'])) {
31960 foreach ($data as $pkg) {
31961 foreach ($pkg['versions'] as $metadata) {
31962 $packages[] = $metadata;
31963 }
31964 }
31965
31966 return $packages;
31967 }
31968
31969 if (isset($data['packages'])) {
31970 foreach ($data['packages'] as $package => $versions) {
31971 foreach ($versions as $version => $metadata) {
31972 $packages[] = $metadata;
31973 }
31974 }
31975 }
31976
31977 if (isset($data['includes'])) {
31978 foreach ($data['includes'] as $include => $metadata) {
31979 if ($this->cache->sha1($include) === $metadata['sha1']) {
31980 $includedData = json_decode($this->cache->read($include), true);
31981 } else {
31982 $includedData = $this->fetchFile($include);
31983 }
31984 $packages = array_merge($packages, $this->loadIncludes($includedData));
31985 }
31986 }
31987
31988 return $packages;
31989 }
31990
31991 protected function createPackage(array $data, $class = 'Composer\Package\CompletePackage')
31992 {
31993 try {
31994 if (!isset($data['notification-url'])) {
31995 $data['notification-url'] = $this->notifyUrl;
31996 }
31997
31998 $package = $this->loader->load($data, $class);
31999 if (isset($this->sourceMirrors[$package->getSourceType()])) {
32000 $package->setSourceMirrors($this->sourceMirrors[$package->getSourceType()]);
32001 }
32002 $package->setDistMirrors($this->distMirrors);
32003 $this->configurePackageTransportOptions($package);
32004
32005 return $package;
32006 } catch (\Exception $e) {
32007 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);
32008 }
32009 }
32010
32011 protected function fetchFile($filename, $cacheKey = null, $sha256 = null, $storeLastModifiedTime = false)
32012 {
32013 if (null === $cacheKey) {
32014 $cacheKey = $filename;
32015 $filename = $this->baseUrl.'/'.$filename;
32016 }
32017
32018
32019  if (($pos = strpos($filename, '$')) && preg_match('{^https?://.*}i', $filename)) {
32020 $filename = substr($filename, 0, $pos) . '%24' . substr($filename, $pos + 1);
32021 }
32022
32023 $retries = 3;
32024 while ($retries--) {
32025 try {
32026 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename);
32027 if ($this->eventDispatcher) {
32028 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
32029 }
32030
32031 $hostname = parse_url($filename, PHP_URL_HOST) ?: $filename;
32032 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
32033
32034 $json = $rfs->getContents($hostname, $filename, false);
32035 if ($sha256 && $sha256 !== hash('sha256', $json)) {
32036
32037  if ($this->allowSslDowngrade) {
32038 $this->url = str_replace('http://', 'https://', $this->url);
32039 $this->baseUrl = str_replace('http://', 'https://', $this->baseUrl);
32040 $filename = str_replace('http://', 'https://', $filename);
32041 }
32042
32043 if ($retries) {
32044 usleep(100000);
32045
32046 continue;
32047 }
32048
32049
32050  throw new RepositorySecurityException('The contents of '.$filename.' do not match its signature. This could indicate a man-in-the-middle attack. Try running composer again and report this if you think it is a mistake.');
32051 }
32052
32053 $data = JsonFile::parseJson($json, $filename);
32054 if (!empty($data['warning'])) {
32055 $this->io->writeError('<warning>Warning from '.$this->url.': '.$data['warning'].'</warning>');
32056 }
32057 if (!empty($data['info'])) {
32058 $this->io->writeError('<info>Info from '.$this->url.': '.$data['info'].'</info>');
32059 }
32060
32061 if ($cacheKey) {
32062 if ($storeLastModifiedTime) {
32063 $lastModifiedDate = $rfs->findHeaderValue($rfs->getLastHeaders(), 'last-modified');
32064 if ($lastModifiedDate) {
32065 $data['last-modified'] = $lastModifiedDate;
32066 $json = json_encode($data);
32067 }
32068 }
32069 $this->cache->write($cacheKey, $json);
32070 }
32071
32072 break;
32073 } catch (\Exception $e) {
32074 if ($e instanceof TransportException && $e->getStatusCode() === 404) {
32075 throw $e;
32076 }
32077
32078 if ($retries) {
32079 usleep(100000);
32080 continue;
32081 }
32082
32083 if ($e instanceof RepositorySecurityException) {
32084 throw $e;
32085 }
32086
32087 if ($cacheKey && ($contents = $this->cache->read($cacheKey))) {
32088 if (!$this->degradedMode) {
32089 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
32090 $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>');
32091 }
32092 $this->degradedMode = true;
32093 $data = JsonFile::parseJson($contents, $this->cache->getRoot().$cacheKey);
32094
32095 break;
32096 }
32097
32098 throw $e;
32099 }
32100 }
32101
32102 return $data;
32103 }
32104
32105 protected function fetchFileIfLastModified($filename, $cacheKey, $lastModifiedTime)
32106 {
32107 $retries = 3;
32108 while ($retries--) {
32109 try {
32110 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename);
32111 if ($this->eventDispatcher) {
32112 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
32113 }
32114
32115 $hostname = parse_url($filename, PHP_URL_HOST) ?: $filename;
32116 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
32117 $options = array('http' => array('header' => array('If-Modified-Since: '.$lastModifiedTime)));
32118 $json = $rfs->getContents($hostname, $filename, false, $options);
32119 if ($json === '' && $rfs->findStatusCode($rfs->getLastHeaders()) === 304) {
32120 return true;
32121 }
32122
32123 $data = JsonFile::parseJson($json, $filename);
32124 if (!empty($data['warning'])) {
32125 $this->io->writeError('<warning>Warning from '.$this->url.': '.$data['warning'].'</warning>');
32126 }
32127 if (!empty($data['info'])) {
32128 $this->io->writeError('<info>Info from '.$this->url.': '.$data['info'].'</info>');
32129 }
32130
32131 $lastModifiedDate = $rfs->findHeaderValue($rfs->getLastHeaders(), 'last-modified');
32132 if ($lastModifiedDate) {
32133 $data['last-modified'] = $lastModifiedDate;
32134 $json = json_encode($data);
32135 }
32136 $this->cache->write($cacheKey, $json);
32137
32138 return $data;
32139 } catch (\Exception $e) {
32140 if ($e instanceof TransportException && $e->getStatusCode() === 404) {
32141 throw $e;
32142 }
32143
32144 if ($retries) {
32145 usleep(100000);
32146 continue;
32147 }
32148
32149 if (!$this->degradedMode) {
32150 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
32151 $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>');
32152 }
32153 $this->degradedMode = true;
32154
32155 return true;
32156 }
32157 }
32158 }
32159
32160
32161
32162
32163
32164
32165 private function initializePartialPackages()
32166 {
32167 $rootData = $this->loadRootServerFile();
32168
32169 $this->partialPackagesByName = array();
32170 foreach ($rootData['packages'] as $package => $versions) {
32171 $package = strtolower($package);
32172 foreach ($versions as $version) {
32173 $this->partialPackagesByName[$package][] = $version;
32174 if (!empty($version['provide']) && is_array($version['provide'])) {
32175 foreach ($version['provide'] as $provided => $providedVersion) {
32176 $this->partialPackagesByName[strtolower($provided)][] = $version;
32177 }
32178 }
32179 if (!empty($version['replace']) && is_array($version['replace'])) {
32180 foreach ($version['replace'] as $provided => $providedVersion) {
32181 $this->partialPackagesByName[strtolower($provided)][] = $version;
32182 }
32183 }
32184 }
32185 }
32186
32187
32188  $this->rootData = true;
32189 }
32190 }
32191 <?php
32192
32193
32194
32195
32196
32197
32198
32199
32200
32201
32202
32203 namespace Composer\Repository;
32204
32205 use Composer\Package\PackageInterface;
32206
32207
32208
32209
32210
32211
32212 class CompositeRepository extends BaseRepository
32213 {
32214
32215
32216
32217
32218 private $repositories;
32219
32220
32221
32222
32223
32224 public function __construct(array $repositories)
32225 {
32226 $this->repositories = array();
32227 foreach ($repositories as $repo) {
32228 $this->addRepository($repo);
32229 }
32230 }
32231
32232
32233
32234
32235
32236
32237 public function getRepositories()
32238 {
32239 return $this->repositories;
32240 }
32241
32242
32243
32244
32245 public function hasPackage(PackageInterface $package)
32246 {
32247 foreach ($this->repositories as $repository) {
32248
32249 if ($repository->hasPackage($package)) {
32250 return true;
32251 }
32252 }
32253
32254 return false;
32255 }
32256
32257
32258
32259
32260 public function findPackage($name, $constraint)
32261 {
32262 foreach ($this->repositories as $repository) {
32263
32264 $package = $repository->findPackage($name, $constraint);
32265 if (null !== $package) {
32266 return $package;
32267 }
32268 }
32269
32270 return null;
32271 }
32272
32273
32274
32275
32276 public function findPackages($name, $constraint = null)
32277 {
32278 $packages = array();
32279 foreach ($this->repositories as $repository) {
32280
32281 $packages[] = $repository->findPackages($name, $constraint);
32282 }
32283
32284 return $packages ? call_user_func_array('array_merge', $packages) : array();
32285 }
32286
32287
32288
32289
32290 public function search($query, $mode = 0, $type = null)
32291 {
32292 $matches = array();
32293 foreach ($this->repositories as $repository) {
32294
32295 $matches[] = $repository->search($query, $mode, $type);
32296 }
32297
32298 return $matches ? call_user_func_array('array_merge', $matches) : array();
32299 }
32300
32301
32302
32303
32304 public function getPackages()
32305 {
32306 $packages = array();
32307 foreach ($this->repositories as $repository) {
32308
32309 $packages[] = $repository->getPackages();
32310 }
32311
32312 return $packages ? call_user_func_array('array_merge', $packages) : array();
32313 }
32314
32315
32316
32317
32318 public function removePackage(PackageInterface $package)
32319 {
32320 foreach ($this->repositories as $repository) {
32321
32322 $repository->removePackage($package);
32323 }
32324 }
32325
32326
32327
32328
32329 public function count()
32330 {
32331 $total = 0;
32332 foreach ($this->repositories as $repository) {
32333
32334 $total += $repository->count();
32335 }
32336
32337 return $total;
32338 }
32339
32340
32341
32342
32343
32344 public function addRepository(RepositoryInterface $repository)
32345 {
32346 if ($repository instanceof self) {
32347 foreach ($repository->getRepositories() as $repo) {
32348 $this->addRepository($repo);
32349 }
32350 } else {
32351 $this->repositories[] = $repository;
32352 }
32353 }
32354 }
32355 <?php
32356
32357
32358
32359
32360
32361
32362
32363
32364
32365
32366
32367 namespace Composer\Repository;
32368
32369
32370
32371
32372
32373
32374 interface ConfigurableRepositoryInterface
32375 {
32376 public function getRepoConfig();
32377 }
32378 <?php
32379
32380
32381
32382
32383
32384
32385
32386
32387
32388
32389
32390 namespace Composer\Repository;
32391
32392 use Composer\Json\JsonFile;
32393 use Composer\Package\Loader\ArrayLoader;
32394 use Composer\Package\Dumper\ArrayDumper;
32395
32396
32397
32398
32399
32400
32401
32402 class FilesystemRepository extends WritableArrayRepository
32403 {
32404 private $file;
32405
32406
32407
32408
32409
32410
32411 public function __construct(JsonFile $repositoryFile)
32412 {
32413 parent::__construct();
32414 $this->file = $repositoryFile;
32415 }
32416
32417
32418
32419
32420 protected function initialize()
32421 {
32422 parent::initialize();
32423
32424 if (!$this->file->exists()) {
32425 return;
32426 }
32427
32428 try {
32429 $packages = $this->file->read();
32430
32431 if (!is_array($packages)) {
32432 throw new \UnexpectedValueException('Could not parse package list from the repository');
32433 }
32434 } catch (\Exception $e) {
32435 throw new InvalidRepositoryException('Invalid repository data in '.$this->file->getPath().', packages could not be loaded: ['.get_class($e).'] '.$e->getMessage());
32436 }
32437
32438 $loader = new ArrayLoader(null, true);
32439 foreach ($packages as $packageData) {
32440 $package = $loader->load($packageData);
32441 $this->addPackage($package);
32442 }
32443 }
32444
32445 public function reload()
32446 {
32447 $this->packages = null;
32448 $this->initialize();
32449 }
32450
32451
32452
32453
32454 public function write()
32455 {
32456 $data = array();
32457 $dumper = new ArrayDumper();
32458
32459 foreach ($this->getCanonicalPackages() as $package) {
32460 $data[] = $dumper->dump($package);
32461 }
32462
32463 $this->file->write($data);
32464 }
32465 }
32466 <?php
32467
32468
32469
32470
32471
32472
32473
32474
32475
32476
32477
32478 namespace Composer\Repository;
32479
32480
32481
32482
32483
32484
32485
32486
32487 class InstalledArrayRepository extends WritableArrayRepository implements InstalledRepositoryInterface
32488 {
32489 }
32490 <?php
32491
32492
32493
32494
32495
32496
32497
32498
32499
32500
32501
32502 namespace Composer\Repository;
32503
32504
32505
32506
32507
32508
32509 class InstalledFilesystemRepository extends FilesystemRepository implements InstalledRepositoryInterface
32510 {
32511 }
32512 <?php
32513
32514
32515
32516
32517
32518
32519
32520
32521
32522
32523
32524 namespace Composer\Repository;
32525
32526
32527
32528
32529
32530
32531
32532
32533 interface InstalledRepositoryInterface extends WritableRepositoryInterface
32534 {
32535 }
32536 <?php
32537
32538
32539
32540
32541
32542
32543
32544
32545
32546
32547
32548 namespace Composer\Repository;
32549
32550
32551
32552
32553
32554
32555 class InvalidRepositoryException extends \Exception
32556 {
32557 }
32558 <?php
32559
32560
32561
32562
32563
32564
32565
32566
32567
32568
32569
32570 namespace Composer\Repository;
32571
32572 use Composer\Package\Loader\ArrayLoader;
32573 use Composer\Package\Loader\ValidatingArrayLoader;
32574
32575
32576
32577
32578
32579
32580 class PackageRepository extends ArrayRepository
32581 {
32582 private $config;
32583
32584
32585
32586
32587
32588
32589 public function __construct(array $config)
32590 {
32591 parent::__construct();
32592 $this->config = $config['package'];
32593
32594
32595  if (!is_numeric(key($this->config))) {
32596 $this->config = array($this->config);
32597 }
32598 }
32599
32600
32601
32602
32603 protected function initialize()
32604 {
32605 parent::initialize();
32606
32607 $loader = new ValidatingArrayLoader(new ArrayLoader(null, true), false);
32608 foreach ($this->config as $package) {
32609 try {
32610 $package = $loader->load($package);
32611 } catch (\Exception $e) {
32612 throw new InvalidRepositoryException('A repository of type "package" contains an invalid package definition: '.$e->getMessage()."\n\nInvalid package definition:\n".json_encode($package));
32613 }
32614
32615 $this->addPackage($package);
32616 }
32617 }
32618 }
32619 <?php
32620
32621
32622
32623
32624
32625
32626
32627
32628
32629
32630
32631 namespace Composer\Repository;
32632
32633 use Composer\Config;
32634 use Composer\IO\IOInterface;
32635 use Composer\Json\JsonFile;
32636 use Composer\Package\Loader\ArrayLoader;
32637 use Composer\Package\Version\VersionGuesser;
32638 use Composer\Package\Version\VersionParser;
32639 use Composer\Util\Platform;
32640 use Composer\Util\ProcessExecutor;
32641
32642
32643
32644
32645
32646
32647
32648
32649
32650
32651
32652
32653
32654
32655
32656
32657
32658
32659
32660
32661
32662
32663
32664
32665
32666
32667
32668
32669
32670
32671
32672
32673
32674
32675
32676
32677 class PathRepository extends ArrayRepository implements ConfigurableRepositoryInterface
32678 {
32679
32680
32681
32682 private $loader;
32683
32684
32685
32686
32687 private $versionGuesser;
32688
32689
32690
32691
32692 private $url;
32693
32694
32695
32696
32697 private $repoConfig;
32698
32699
32700
32701
32702 private $process;
32703
32704
32705
32706
32707 private $options;
32708
32709
32710
32711
32712
32713
32714
32715
32716 public function __construct(array $repoConfig, IOInterface $io, Config $config)
32717 {
32718 if (!isset($repoConfig['url'])) {
32719 throw new \RuntimeException('You must specify the `url` configuration for the path repository');
32720 }
32721
32722 $this->loader = new ArrayLoader(null, true);
32723 $this->url = Platform::expandPath($repoConfig['url']);
32724 $this->process = new ProcessExecutor($io);
32725 $this->versionGuesser = new VersionGuesser($config, $this->process, new VersionParser());
32726 $this->repoConfig = $repoConfig;
32727 $this->options = isset($repoConfig['options']) ? $repoConfig['options'] : array();
32728
32729 parent::__construct();
32730 }
32731
32732 public function getRepoConfig()
32733 {
32734 return $this->repoConfig;
32735 }
32736
32737
32738
32739
32740
32741
32742 protected function initialize()
32743 {
32744 parent::initialize();
32745
32746 foreach ($this->getUrlMatches() as $url) {
32747 $path = realpath($url) . DIRECTORY_SEPARATOR;
32748 $composerFilePath = $path.'composer.json';
32749
32750 if (!file_exists($composerFilePath)) {
32751 continue;
32752 }
32753
32754 $json = file_get_contents($composerFilePath);
32755 $package = JsonFile::parseJson($json, $composerFilePath);
32756 $package['dist'] = array(
32757 'type' => 'path',
32758 'url' => $url,
32759 'reference' => sha1($json . serialize($this->options)),
32760 );
32761 $package['transport-options'] = $this->options;
32762
32763
32764  if (!isset($package['version']) && ($rootVersion = getenv('COMPOSER_ROOT_VERSION'))) {
32765 if (
32766 0 === $this->process->execute('git rev-parse HEAD', $ref1, $path)
32767 && 0 === $this->process->execute('git rev-parse HEAD', $ref2)
32768 && $ref1 === $ref2
32769 ) {
32770 $package['version'] = $rootVersion;
32771 }
32772 }
32773
32774 if (!isset($package['version'])) {
32775 $versionData = $this->versionGuesser->guessVersion($package, $path);
32776 $package['version'] = $versionData['version'] ?: 'dev-master';
32777 }
32778
32779 $output = '';
32780 if (is_dir($path . DIRECTORY_SEPARATOR . '.git') && 0 === $this->process->execute('git log -n1 --pretty=%H', $output, $path)) {
32781 $package['dist']['reference'] = trim($output);
32782 }
32783 $package = $this->loader->load($package);
32784 $this->addPackage($package);
32785 }
32786 }
32787
32788
32789
32790
32791
32792
32793 private function getUrlMatches()
32794 {
32795
32796  return array_map(function ($val) {
32797 return rtrim(str_replace(DIRECTORY_SEPARATOR, '/', $val), '/');
32798 }, glob($this->url, GLOB_MARK | GLOB_ONLYDIR));
32799 }
32800 }
32801 <?php
32802
32803
32804
32805
32806
32807
32808
32809
32810
32811
32812
32813 namespace Composer\Repository\Pear;
32814
32815 use Composer\Util\RemoteFilesystem;
32816
32817
32818
32819
32820
32821
32822
32823
32824 abstract class BaseChannelReader
32825 {
32826
32827
32828
32829 const CHANNEL_NS = 'http://pear.php.net/channel-1.0';
32830 const ALL_CATEGORIES_NS = 'http://pear.php.net/dtd/rest.allcategories';
32831 const CATEGORY_PACKAGES_INFO_NS = 'http://pear.php.net/dtd/rest.categorypackageinfo';
32832 const ALL_PACKAGES_NS = 'http://pear.php.net/dtd/rest.allpackages';
32833 const ALL_RELEASES_NS = 'http://pear.php.net/dtd/rest.allreleases';
32834 const PACKAGE_INFO_NS = 'http://pear.php.net/dtd/rest.package';
32835
32836
32837 private $rfs;
32838
32839 protected function __construct(RemoteFilesystem $rfs)
32840 {
32841 $this->rfs = $rfs;
32842 }
32843
32844
32845
32846
32847
32848
32849
32850
32851
32852 protected function requestContent($origin, $path)
32853 {
32854 $url = rtrim($origin, '/') . '/' . ltrim($path, '/');
32855 $content = $this->rfs->getContents($origin, $url, false);
32856 if (!$content) {
32857 throw new \UnexpectedValueException('The PEAR channel at ' . $url . ' did not respond.');
32858 }
32859
32860 return str_replace('http://pear.php.net/rest/', 'https://pear.php.net/rest/', $content);
32861 }
32862
32863
32864
32865
32866
32867
32868
32869
32870
32871 protected function requestXml($origin, $path)
32872 {
32873
32874  $xml = simplexml_load_string($this->requestContent($origin, $path), "SimpleXMLElement", LIBXML_NOERROR);
32875
32876 if (false === $xml) {
32877 throw new \UnexpectedValueException(sprintf('The PEAR channel at ' . $origin . ' is broken. (Invalid XML at file `%s`)', $path));
32878 }
32879
32880 return $xml;
32881 }
32882 }
32883 <?php
32884
32885
32886
32887
32888
32889
32890
32891
32892
32893
32894
32895 namespace Composer\Repository\Pear;
32896
32897
32898
32899
32900
32901
32902 class ChannelInfo
32903 {
32904 private $name;
32905 private $alias;
32906 private $packages;
32907
32908
32909
32910
32911
32912
32913 public function __construct($name, $alias, array $packages)
32914 {
32915 $this->name = $name;
32916 $this->alias = $alias;
32917 $this->packages = $packages;
32918 }
32919
32920
32921
32922
32923
32924
32925 public function getName()
32926 {
32927 return $this->name;
32928 }
32929
32930
32931
32932
32933
32934
32935 public function getAlias()
32936 {
32937 return $this->alias;
32938 }
32939
32940
32941
32942
32943
32944
32945 public function getPackages()
32946 {
32947 return $this->packages;
32948 }
32949 }
32950 <?php
32951
32952
32953
32954
32955
32956
32957
32958
32959
32960
32961
32962 namespace Composer\Repository\Pear;
32963
32964 use Composer\Util\RemoteFilesystem;
32965
32966
32967
32968
32969
32970
32971
32972
32973 class ChannelReader extends BaseChannelReader
32974 {
32975
32976 private $readerMap;
32977
32978 public function __construct(RemoteFilesystem $rfs)
32979 {
32980 parent::__construct($rfs);
32981
32982 $rest10reader = new ChannelRest10Reader($rfs);
32983 $rest11reader = new ChannelRest11Reader($rfs);
32984
32985 $this->readerMap = array(
32986 'REST1.3' => $rest11reader,
32987 'REST1.2' => $rest11reader,
32988 'REST1.1' => $rest11reader,
32989 'REST1.0' => $rest10reader,
32990 );
32991 }
32992
32993
32994
32995
32996
32997
32998
32999
33000 public function read($url)
33001 {
33002 $xml = $this->requestXml($url, "/channel.xml");
33003
33004 $channelName = (string) $xml->name;
33005 $channelAlias = (string) $xml->suggestedalias;
33006
33007 $supportedVersions = array_keys($this->readerMap);
33008 $selectedRestVersion = $this->selectRestVersion($xml, $supportedVersions);
33009 if (!$selectedRestVersion) {
33010 throw new \UnexpectedValueException(sprintf('PEAR repository %s does not supports any of %s protocols.', $url, implode(', ', $supportedVersions)));
33011 }
33012
33013 $reader = $this->readerMap[$selectedRestVersion['version']];
33014 $packageDefinitions = $reader->read($selectedRestVersion['baseUrl']);
33015
33016 return new ChannelInfo($channelName, $channelAlias, $packageDefinitions);
33017 }
33018
33019
33020
33021
33022
33023
33024
33025
33026 private function selectRestVersion($channelXml, $supportedVersions)
33027 {
33028 $channelXml->registerXPathNamespace('ns', self::CHANNEL_NS);
33029
33030 foreach ($supportedVersions as $version) {
33031 $xpathTest = "ns:servers/ns:*/ns:rest/ns:baseurl[@type='{$version}']";
33032 $testResult = $channelXml->xpath($xpathTest);
33033
33034 foreach ($testResult as $result) {
33035
33036  $result = (string) $result;
33037 if (preg_match('{^https://}i', $result)) {
33038 return array('version' => $version, 'baseUrl' => $result);
33039 }
33040 }
33041
33042
33043  if (count($testResult) > 0) {
33044 return array('version' => $version, 'baseUrl' => (string) $testResult[0]);
33045 }
33046 }
33047
33048 return null;
33049 }
33050 }
33051 <?php
33052
33053
33054
33055
33056
33057
33058
33059
33060
33061
33062
33063 namespace Composer\Repository\Pear;
33064
33065 use Composer\Downloader\TransportException;
33066
33067
33068
33069
33070
33071
33072
33073
33074
33075
33076
33077
33078 class ChannelRest10Reader extends BaseChannelReader
33079 {
33080 private $dependencyReader;
33081
33082 public function __construct($rfs)
33083 {
33084 parent::__construct($rfs);
33085
33086 $this->dependencyReader = new PackageDependencyParser();
33087 }
33088
33089
33090
33091
33092
33093
33094
33095
33096 public function read($baseUrl)
33097 {
33098 return $this->readPackages($baseUrl);
33099 }
33100
33101
33102
33103
33104
33105
33106
33107
33108 private function readPackages($baseUrl)
33109 {
33110 $result = array();
33111
33112 $xmlPath = '/p/packages.xml';
33113 $xml = $this->requestXml($baseUrl, $xmlPath);
33114 $xml->registerXPathNamespace('ns', self::ALL_PACKAGES_NS);
33115 foreach ($xml->xpath('ns:p') as $node) {
33116 $packageName = (string) $node;
33117 $packageInfo = $this->readPackage($baseUrl, $packageName);
33118 $result[] = $packageInfo;
33119 }
33120
33121 return $result;
33122 }
33123
33124
33125
33126
33127
33128
33129
33130
33131
33132 private function readPackage($baseUrl, $packageName)
33133 {
33134 $xmlPath = '/p/' . strtolower($packageName) . '/info.xml';
33135 $xml = $this->requestXml($baseUrl, $xmlPath);
33136 $xml->registerXPathNamespace('ns', self::PACKAGE_INFO_NS);
33137
33138 $channelName = (string) $xml->c;
33139 $packageName = (string) $xml->n;
33140 $license = (string) $xml->l;
33141 $shortDescription = (string) $xml->s;
33142 $description = (string) $xml->d;
33143
33144 return new PackageInfo(
33145 $channelName,
33146 $packageName,
33147 $license,
33148 $shortDescription,
33149 $description,
33150 $this->readPackageReleases($baseUrl, $packageName)
33151 );
33152 }
33153
33154
33155
33156
33157
33158
33159
33160
33161
33162
33163 private function readPackageReleases($baseUrl, $packageName)
33164 {
33165 $result = array();
33166
33167 try {
33168 $xmlPath = '/r/' . strtolower($packageName) . '/allreleases.xml';
33169 $xml = $this->requestXml($baseUrl, $xmlPath);
33170 $xml->registerXPathNamespace('ns', self::ALL_RELEASES_NS);
33171 foreach ($xml->xpath('ns:r') as $node) {
33172 $releaseVersion = (string) $node->v;
33173 $releaseStability = (string) $node->s;
33174
33175 try {
33176 $result[$releaseVersion] = new ReleaseInfo(
33177 $releaseStability,
33178 $this->readPackageReleaseDependencies($baseUrl, $packageName, $releaseVersion)
33179 );
33180 } catch (TransportException $exception) {
33181 if ($exception->getCode() != 404) {
33182 throw $exception;
33183 }
33184 }
33185 }
33186 } catch (TransportException $exception) {
33187 if ($exception->getCode() != 404) {
33188 throw $exception;
33189 }
33190 }
33191
33192 return $result;
33193 }
33194
33195
33196
33197
33198
33199
33200
33201
33202
33203
33204 private function readPackageReleaseDependencies($baseUrl, $packageName, $version)
33205 {
33206 $dependencyReader = new PackageDependencyParser();
33207
33208 $depthPath = '/r/' . strtolower($packageName) . '/deps.' . $version . '.txt';
33209 $content = $this->requestContent($baseUrl, $depthPath);
33210 $dependencyArray = unserialize($content);
33211 $result = $dependencyReader->buildDependencyInfo($dependencyArray);
33212
33213 return $result;
33214 }
33215 }
33216 <?php
33217
33218
33219
33220
33221
33222
33223
33224
33225
33226
33227
33228 namespace Composer\Repository\Pear;
33229
33230
33231
33232
33233
33234
33235
33236
33237
33238
33239 class ChannelRest11Reader extends BaseChannelReader
33240 {
33241 private $dependencyReader;
33242
33243 public function __construct($rfs)
33244 {
33245 parent::__construct($rfs);
33246
33247 $this->dependencyReader = new PackageDependencyParser();
33248 }
33249
33250
33251
33252
33253
33254
33255
33256
33257 public function read($baseUrl)
33258 {
33259 return $this->readChannelPackages($baseUrl);
33260 }
33261
33262
33263
33264
33265
33266
33267
33268
33269 private function readChannelPackages($baseUrl)
33270 {
33271 $result = array();
33272
33273 $xml = $this->requestXml($baseUrl, "/c/categories.xml");
33274 $xml->registerXPathNamespace('ns', self::ALL_CATEGORIES_NS);
33275 foreach ($xml->xpath('ns:c') as $node) {
33276 $categoryName = (string) $node;
33277 $categoryPackages = $this->readCategoryPackages($baseUrl, $categoryName);
33278 $result = array_merge($result, $categoryPackages);
33279 }
33280
33281 return $result;
33282 }
33283
33284
33285
33286
33287
33288
33289
33290
33291
33292 private function readCategoryPackages($baseUrl, $categoryName)
33293 {
33294 $result = array();
33295
33296 $categoryPath = '/c/'.urlencode($categoryName).'/packagesinfo.xml';
33297 $xml = $this->requestXml($baseUrl, $categoryPath);
33298 $xml->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
33299 foreach ($xml->xpath('ns:pi') as $node) {
33300 $packageInfo = $this->parsePackage($node);
33301 $result[] = $packageInfo;
33302 }
33303
33304 return $result;
33305 }
33306
33307
33308
33309
33310
33311
33312
33313 private function parsePackage($packageInfo)
33314 {
33315 $packageInfo->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
33316 $channelName = (string) $packageInfo->p->c;
33317 $packageName = (string) $packageInfo->p->n;
33318 $license = (string) $packageInfo->p->l;
33319 $shortDescription = (string) $packageInfo->p->s;
33320 $description = (string) $packageInfo->p->d;
33321
33322 $dependencies = array();
33323 foreach ($packageInfo->xpath('ns:deps') as $node) {
33324 $dependencyVersion = (string) $node->v;
33325 $dependencyArray = unserialize((string) $node->d);
33326
33327 $dependencyInfo = $this->dependencyReader->buildDependencyInfo($dependencyArray);
33328
33329 $dependencies[$dependencyVersion] = $dependencyInfo;
33330 }
33331
33332 $releases = array();
33333 $releasesInfo = $packageInfo->xpath('ns:a/ns:r');
33334 if ($releasesInfo) {
33335 foreach ($releasesInfo as $node) {
33336 $releaseVersion = (string) $node->v;
33337 $releaseStability = (string) $node->s;
33338 $releases[$releaseVersion] = new ReleaseInfo(
33339 $releaseStability,
33340 isset($dependencies[$releaseVersion]) ? $dependencies[$releaseVersion] : new DependencyInfo(array(), array())
33341 );
33342 }
33343 }
33344
33345 return new PackageInfo(
33346 $channelName,
33347 $packageName,
33348 $license,
33349 $shortDescription,
33350 $description,
33351 $releases
33352 );
33353 }
33354 }
33355 <?php
33356
33357
33358
33359
33360
33361
33362
33363
33364
33365
33366
33367 namespace Composer\Repository\Pear;
33368
33369
33370
33371
33372
33373
33374 class DependencyConstraint
33375 {
33376 private $type;
33377 private $constraint;
33378 private $channelName;
33379 private $packageName;
33380
33381
33382
33383
33384
33385
33386
33387 public function __construct($type, $constraint, $channelName, $packageName)
33388 {
33389 $this->type = $type;
33390 $this->constraint = $constraint;
33391 $this->channelName = $channelName;
33392 $this->packageName = $packageName;
33393 }
33394
33395 public function getChannelName()
33396 {
33397 return $this->channelName;
33398 }
33399
33400 public function getConstraint()
33401 {
33402 return $this->constraint;
33403 }
33404
33405 public function getPackageName()
33406 {
33407 return $this->packageName;
33408 }
33409
33410 public function getType()
33411 {
33412 return $this->type;
33413 }
33414 }
33415 <?php
33416
33417
33418
33419
33420
33421
33422
33423
33424
33425
33426
33427 namespace Composer\Repository\Pear;
33428
33429
33430
33431
33432
33433
33434 class DependencyInfo
33435 {
33436 private $requires;
33437 private $optionals;
33438
33439
33440
33441
33442
33443 public function __construct($requires, $optionals)
33444 {
33445 $this->requires = $requires;
33446 $this->optionals = $optionals;
33447 }
33448
33449
33450
33451
33452 public function getRequires()
33453 {
33454 return $this->requires;
33455 }
33456
33457
33458
33459
33460 public function getOptionals()
33461 {
33462 return $this->optionals;
33463 }
33464 }
33465 <?php
33466
33467
33468
33469
33470
33471
33472
33473
33474
33475
33476
33477 namespace Composer\Repository\Pear;
33478
33479
33480
33481
33482
33483
33484 class PackageDependencyParser
33485 {
33486
33487
33488
33489
33490
33491
33492 public function buildDependencyInfo($depArray)
33493 {
33494 if (!is_array($depArray)) {
33495 return new DependencyInfo(array(), array());
33496 }
33497 if (!$this->isHash($depArray)) {
33498 return new DependencyInfo($this->buildDependency10Info($depArray), array());
33499 }
33500
33501 return $this->buildDependency20Info($depArray);
33502 }
33503
33504
33505
33506
33507
33508
33509
33510
33511
33512
33513
33514
33515
33516 private function buildDependency10Info($depArray)
33517 {
33518 static $dep10toOperatorMap = array('has' => '==', 'eq' => '==', 'ge' => '>=', 'gt' => '>', 'le' => '<=', 'lt' => '<', 'not' => '!=');
33519
33520 $result = array();
33521
33522 foreach ($depArray as $depItem) {
33523 if (empty($depItem['rel']) || !array_key_exists($depItem['rel'], $dep10toOperatorMap)) {
33524
33525  continue;
33526 }
33527
33528 $depType = !empty($depItem['optional']) && 'yes' == $depItem['optional']
33529 ? 'optional'
33530 : 'required';
33531 $depType = 'not' == $depItem['rel']
33532 ? 'conflicts'
33533 : $depType;
33534
33535 $depVersion = !empty($depItem['version']) ? $this->parseVersion($depItem['version']) : '*';
33536
33537
33538  $depVersionConstraint = ('has' == $depItem['rel'] || 'not' == $depItem['rel']) && '*' == $depVersion
33539 ? '*'
33540 : $dep10toOperatorMap[$depItem['rel']] . $depVersion;
33541
33542 switch ($depItem['type']) {
33543 case 'php':
33544 $depChannelName = 'php';
33545 $depPackageName = '';
33546 break;
33547 case 'pkg':
33548 $depChannelName = !empty($depItem['channel']) ? $depItem['channel'] : 'pear.php.net';
33549 $depPackageName = $depItem['name'];
33550 break;
33551 case 'ext':
33552 $depChannelName = 'ext';
33553 $depPackageName = $depItem['name'];
33554 break;
33555 case 'os':
33556 case 'sapi':
33557 $depChannelName = '';
33558 $depPackageName = '';
33559 break;
33560 default:
33561 $depChannelName = '';
33562 $depPackageName = '';
33563 break;
33564 }
33565
33566 if ('' != $depChannelName) {
33567 $result[] = new DependencyConstraint(
33568 $depType,
33569 $depVersionConstraint,
33570 $depChannelName,
33571 $depPackageName
33572 );
33573 }
33574 }
33575
33576 return $result;
33577 }
33578
33579
33580
33581
33582
33583
33584
33585 private function buildDependency20Info($depArray)
33586 {
33587 $result = array();
33588 $optionals = array();
33589 $defaultOptionals = array();
33590 foreach ($depArray as $depType => $depTypeGroup) {
33591 if (!is_array($depTypeGroup)) {
33592 continue;
33593 }
33594 if ('required' == $depType || 'optional' == $depType) {
33595 foreach ($depTypeGroup as $depItemType => $depItem) {
33596 switch ($depItemType) {
33597 case 'php':
33598 $result[] = new DependencyConstraint(
33599 $depType,
33600 $this->parse20VersionConstraint($depItem),
33601 'php',
33602 ''
33603 );
33604 break;
33605 case 'package':
33606 $deps = $this->buildDepPackageConstraints($depItem, $depType);
33607 $result = array_merge($result, $deps);
33608 break;
33609 case 'extension':
33610 $deps = $this->buildDepExtensionConstraints($depItem, $depType);
33611 $result = array_merge($result, $deps);
33612 break;
33613 case 'subpackage':
33614 $deps = $this->buildDepPackageConstraints($depItem, 'replaces');
33615 $defaultOptionals += $deps;
33616 break;
33617 case 'os':
33618 case 'pearinstaller':
33619 break;
33620 default:
33621 break;
33622 }
33623 }
33624 } elseif ('group' == $depType) {
33625 if ($this->isHash($depTypeGroup)) {
33626 $depTypeGroup = array($depTypeGroup);
33627 }
33628
33629 foreach ($depTypeGroup as $depItem) {
33630 $groupName = $depItem['attribs']['name'];
33631 if (!isset($optionals[$groupName])) {
33632 $optionals[$groupName] = array();
33633 }
33634
33635 if (isset($depItem['subpackage'])) {
33636 $optionals[$groupName] += $this->buildDepPackageConstraints($depItem['subpackage'], 'replaces');
33637 } else {
33638 $result += $this->buildDepPackageConstraints($depItem['package'], 'optional');
33639 }
33640 }
33641 }
33642 }
33643
33644 if (count($defaultOptionals) > 0) {
33645 $optionals['*'] = $defaultOptionals;
33646 }
33647
33648 return new DependencyInfo($result, $optionals);
33649 }
33650
33651
33652
33653
33654
33655
33656
33657
33658 private function buildDepExtensionConstraints($depItem, $depType)
33659 {
33660 if ($this->isHash($depItem)) {
33661 $depItem = array($depItem);
33662 }
33663
33664 $result = array();
33665 foreach ($depItem as $subDepItem) {
33666 $depChannelName = 'ext';
33667 $depPackageName = $subDepItem['name'];
33668 $depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
33669
33670 $result[] = new DependencyConstraint(
33671 $depType,
33672 $depVersionConstraint,
33673 $depChannelName,
33674 $depPackageName
33675 );
33676 }
33677
33678 return $result;
33679 }
33680
33681
33682
33683
33684
33685
33686
33687
33688 private function buildDepPackageConstraints($depItem, $depType)
33689 {
33690 if ($this->isHash($depItem)) {
33691 $depItem = array($depItem);
33692 }
33693
33694 $result = array();
33695 foreach ($depItem as $subDepItem) {
33696 if (!array_key_exists('channel', $subDepItem)) {
33697 $subDepItem['channel'] = $subDepItem['uri'];
33698 }
33699 $depChannelName = $subDepItem['channel'];
33700 $depPackageName = $subDepItem['name'];
33701 $depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
33702 if (isset($subDepItem['conflicts'])) {
33703 $depType = 'conflicts';
33704 }
33705
33706 $result[] = new DependencyConstraint(
33707 $depType,
33708 $depVersionConstraint,
33709 $depChannelName,
33710 $depPackageName
33711 );
33712 }
33713
33714 return $result;
33715 }
33716
33717
33718
33719
33720
33721
33722
33723 private function parse20VersionConstraint(array $data)
33724 {
33725 static $dep20toOperatorMap = array('has' => '==', 'min' => '>=', 'max' => '<=', 'exclude' => '!=');
33726
33727 $versions = array();
33728 $values = array_intersect_key($data, $dep20toOperatorMap);
33729 if (0 == count($values)) {
33730 return '*';
33731 }
33732 if (isset($values['min']) && isset($values['exclude']) && $data['min'] == $data['exclude']) {
33733 $versions[] = '>' . $this->parseVersion($values['min']);
33734 } elseif (isset($values['max']) && isset($values['exclude']) && $data['max'] == $data['exclude']) {
33735 $versions[] = '<' . $this->parseVersion($values['max']);
33736 } else {
33737 foreach ($values as $op => $version) {
33738 if ('exclude' == $op && is_array($version)) {
33739 foreach ($version as $versionPart) {
33740 $versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($versionPart);
33741 }
33742 } else {
33743 $versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($version);
33744 }
33745 }
33746 }
33747
33748 return implode(',', $versions);
33749 }
33750
33751
33752
33753
33754
33755
33756
33757 private function parseVersion($version)
33758 {
33759 if (preg_match('{^v?(\d{1,3})(\.\d+)?(\.\d+)?(\.\d+)?}i', $version, $matches)) {
33760 $version = $matches[1]
33761 .(!empty($matches[2]) ? $matches[2] : '.0')
33762 .(!empty($matches[3]) ? $matches[3] : '.0')
33763 .(!empty($matches[4]) ? $matches[4] : '.0');
33764
33765 return $version;
33766 }
33767
33768 return null;
33769 }
33770
33771
33772
33773
33774
33775
33776
33777 private function isHash(array $array)
33778 {
33779 return !array_key_exists(1, $array) && !array_key_exists(0, $array);
33780 }
33781 }
33782 <?php
33783
33784
33785
33786
33787
33788
33789
33790
33791
33792
33793
33794 namespace Composer\Repository\Pear;
33795
33796
33797
33798
33799
33800
33801 class PackageInfo
33802 {
33803 private $channelName;
33804 private $packageName;
33805 private $license;
33806 private $shortDescription;
33807 private $description;
33808 private $releases;
33809
33810
33811
33812
33813
33814
33815
33816
33817
33818 public function __construct($channelName, $packageName, $license, $shortDescription, $description, $releases)
33819 {
33820 $this->channelName = $channelName;
33821 $this->packageName = $packageName;
33822 $this->license = $license;
33823 $this->shortDescription = $shortDescription;
33824 $this->description = $description;
33825 $this->releases = $releases;
33826 }
33827
33828
33829
33830
33831 public function getChannelName()
33832 {
33833 return $this->channelName;
33834 }
33835
33836
33837
33838
33839 public function getPackageName()
33840 {
33841 return $this->packageName;
33842 }
33843
33844
33845
33846
33847 public function getDescription()
33848 {
33849 return $this->description;
33850 }
33851
33852
33853
33854
33855 public function getShortDescription()
33856 {
33857 return $this->shortDescription;
33858 }
33859
33860
33861
33862
33863 public function getLicense()
33864 {
33865 return $this->license;
33866 }
33867
33868
33869
33870
33871 public function getReleases()
33872 {
33873 return $this->releases;
33874 }
33875 }
33876 <?php
33877
33878
33879
33880
33881
33882
33883
33884
33885
33886
33887
33888 namespace Composer\Repository\Pear;
33889
33890
33891
33892
33893
33894
33895 class ReleaseInfo
33896 {
33897 private $stability;
33898 private $dependencyInfo;
33899
33900
33901
33902
33903
33904 public function __construct($stability, $dependencyInfo)
33905 {
33906 $this->stability = $stability;
33907 $this->dependencyInfo = $dependencyInfo;
33908 }
33909
33910
33911
33912
33913 public function getDependencyInfo()
33914 {
33915 return $this->dependencyInfo;
33916 }
33917
33918
33919
33920
33921 public function getStability()
33922 {
33923 return $this->stability;
33924 }
33925 }
33926 <?php
33927
33928
33929
33930
33931
33932
33933
33934
33935
33936
33937
33938 namespace Composer\Repository;
33939
33940 use Composer\IO\IOInterface;
33941 use Composer\Semver\VersionParser as SemverVersionParser;
33942 use Composer\Package\Version\VersionParser;
33943 use Composer\Repository\Pear\ChannelReader;
33944 use Composer\Package\CompletePackage;
33945 use Composer\Repository\Pear\ChannelInfo;
33946 use Composer\EventDispatcher\EventDispatcher;
33947 use Composer\Package\Link;
33948 use Composer\Semver\Constraint\Constraint;
33949 use Composer\Util\RemoteFilesystem;
33950 use Composer\Config;
33951 use Composer\Factory;
33952
33953
33954
33955
33956
33957
33958
33959
33960
33961
33962 class PearRepository extends ArrayRepository implements ConfigurableRepositoryInterface
33963 {
33964 private $url;
33965 private $io;
33966 private $rfs;
33967 private $versionParser;
33968 private $repoConfig;
33969
33970
33971
33972
33973 private $vendorAlias;
33974
33975 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, RemoteFilesystem $rfs = null)
33976 {
33977 parent::__construct();
33978 if (!preg_match('{^https?://}', $repoConfig['url'])) {
33979 $repoConfig['url'] = 'http://'.$repoConfig['url'];
33980 }
33981
33982 $urlBits = parse_url($repoConfig['url']);
33983 if (empty($urlBits['scheme']) || empty($urlBits['host'])) {
33984 throw new \UnexpectedValueException('Invalid url given for PEAR repository: '.$repoConfig['url']);
33985 }
33986
33987 $this->url = rtrim($repoConfig['url'], '/');
33988 $this->io = $io;
33989 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $config);
33990 $this->vendorAlias = isset($repoConfig['vendor-alias']) ? $repoConfig['vendor-alias'] : null;
33991 $this->versionParser = new VersionParser();
33992 $this->repoConfig = $repoConfig;
33993 }
33994
33995 public function getRepoConfig()
33996 {
33997 return $this->repoConfig;
33998 }
33999
34000 protected function initialize()
34001 {
34002 parent::initialize();
34003
34004 $this->io->writeError('Initializing PEAR repository '.$this->url);
34005
34006 $reader = new ChannelReader($this->rfs);
34007 try {
34008 $channelInfo = $reader->read($this->url);
34009 } catch (\Exception $e) {
34010 $this->io->writeError('<warning>PEAR repository from '.$this->url.' could not be loaded. '.$e->getMessage().'</warning>');
34011
34012 return;
34013 }
34014 $packages = $this->buildComposerPackages($channelInfo, $this->versionParser);
34015 foreach ($packages as $package) {
34016 $this->addPackage($package);
34017 }
34018 }
34019
34020
34021
34022
34023
34024
34025
34026
34027 private function buildComposerPackages(ChannelInfo $channelInfo, SemverVersionParser $versionParser)
34028 {
34029 $result = array();
34030 foreach ($channelInfo->getPackages() as $packageDefinition) {
34031 foreach ($packageDefinition->getReleases() as $version => $releaseInfo) {
34032 try {
34033 $normalizedVersion = $versionParser->normalize($version);
34034 } catch (\UnexpectedValueException $e) {
34035 $this->io->writeError('Could not load '.$packageDefinition->getPackageName().' '.$version.': '.$e->getMessage(), true, IOInterface::VERBOSE);
34036 continue;
34037 }
34038
34039 $composerPackageName = $this->buildComposerPackageName($packageDefinition->getChannelName(), $packageDefinition->getPackageName());
34040
34041
34042  
34043  $urlBits = parse_url($this->url);
34044 $scheme = (isset($urlBits['scheme']) && 'https' === $urlBits['scheme'] && extension_loaded('openssl')) ? 'https' : 'http';
34045 $distUrl = "{$scheme}://{$packageDefinition->getChannelName()}/get/{$packageDefinition->getPackageName()}-{$version}.tgz";
34046
34047 $requires = array();
34048 $suggests = array();
34049 $conflicts = array();
34050 $replaces = array();
34051
34052
34053  
34054  if ($channelInfo->getName() == $packageDefinition->getChannelName()) {
34055 $composerPackageAlias = $this->buildComposerPackageName($channelInfo->getAlias(), $packageDefinition->getPackageName());
34056 $aliasConstraint = new Constraint('==', $normalizedVersion);
34057 $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
34058 }
34059
34060
34061  if (!empty($this->vendorAlias)
34062 && ($this->vendorAlias != 'pear-'.$channelInfo->getAlias() || $channelInfo->getName() != $packageDefinition->getChannelName())
34063 ) {
34064 $composerPackageAlias = "{$this->vendorAlias}/{$packageDefinition->getPackageName()}";
34065 $aliasConstraint = new Constraint('==', $normalizedVersion);
34066 $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
34067 }
34068
34069 foreach ($releaseInfo->getDependencyInfo()->getRequires() as $dependencyConstraint) {
34070 $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
34071 $constraint = $versionParser->parseConstraints($dependencyConstraint->getConstraint());
34072 $link = new Link($composerPackageName, $dependencyPackageName, $constraint, $dependencyConstraint->getType(), $dependencyConstraint->getConstraint());
34073 switch ($dependencyConstraint->getType()) {
34074 case 'required':
34075 $requires[] = $link;
34076 break;
34077 case 'conflicts':
34078 $conflicts[] = $link;
34079 break;
34080 case 'replaces':
34081 $replaces[] = $link;
34082 break;
34083 }
34084 }
34085
34086 foreach ($releaseInfo->getDependencyInfo()->getOptionals() as $group => $dependencyConstraints) {
34087 foreach ($dependencyConstraints as $dependencyConstraint) {
34088 $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
34089 $suggests[$group.'-'.$dependencyPackageName] = $dependencyConstraint->getConstraint();
34090 }
34091 }
34092
34093 $package = new CompletePackage($composerPackageName, $normalizedVersion, $version);
34094 $package->setType('pear-library');
34095 $package->setDescription($packageDefinition->getDescription());
34096 $package->setLicense(array($packageDefinition->getLicense()));
34097 $package->setDistType('file');
34098 $package->setDistUrl($distUrl);
34099 $package->setAutoload(array('classmap' => array('')));
34100 $package->setIncludePaths(array('/'));
34101 $package->setRequires($requires);
34102 $package->setConflicts($conflicts);
34103 $package->setSuggests($suggests);
34104 $package->setReplaces($replaces);
34105 $result[] = $package;
34106 }
34107 }
34108
34109 return $result;
34110 }
34111
34112 private function buildComposerPackageName($channelName, $packageName)
34113 {
34114 if ('php' === $channelName) {
34115 return "php";
34116 }
34117 if ('ext' === $channelName) {
34118 return "ext-{$packageName}";
34119 }
34120
34121 return "pear-{$channelName}/{$packageName}";
34122 }
34123 }
34124 <?php
34125
34126
34127
34128
34129
34130
34131
34132
34133
34134
34135
34136 namespace Composer\Repository;
34137
34138 use Composer\XdebugHandler;
34139 use Composer\Package\CompletePackage;
34140 use Composer\Package\PackageInterface;
34141 use Composer\Package\Version\VersionParser;
34142 use Composer\Plugin\PluginInterface;
34143 use Composer\Util\Silencer;
34144
34145
34146
34147
34148 class PlatformRepository extends ArrayRepository
34149 {
34150 const PLATFORM_PACKAGE_REGEX = '{^(?:php(?:-64bit|-ipv6|-zts|-debug)?|hhvm|(?:ext|lib)-[^/]+)$}i';
34151
34152 private $versionParser;
34153
34154
34155
34156
34157
34158
34159
34160
34161 private $overrides = array();
34162
34163 public function __construct(array $packages = array(), array $overrides = array())
34164 {
34165 foreach ($overrides as $name => $version) {
34166 $this->overrides[strtolower($name)] = array('name' => $name, 'version' => $version);
34167 }
34168 parent::__construct($packages);
34169 }
34170
34171 protected function initialize()
34172 {
34173 parent::initialize();
34174
34175 $this->versionParser = new VersionParser();
34176
34177
34178  
34179  foreach ($this->overrides as $override) {
34180
34181  if (!preg_match(self::PLATFORM_PACKAGE_REGEX, $override['name'])) {
34182 throw new \InvalidArgumentException('Invalid platform package name in config.platform: '.$override['name']);
34183 }
34184
34185 $this->addOverriddenPackage($override);
34186 }
34187
34188 $prettyVersion = PluginInterface::PLUGIN_API_VERSION;
34189 $version = $this->versionParser->normalize($prettyVersion);
34190 $composerPluginApi = new CompletePackage('composer-plugin-api', $version, $prettyVersion);
34191 $composerPluginApi->setDescription('The Composer Plugin API');
34192 $this->addPackage($composerPluginApi);
34193
34194 try {
34195 $prettyVersion = PHP_VERSION;
34196 $version = $this->versionParser->normalize($prettyVersion);
34197 } catch (\UnexpectedValueException $e) {
34198 $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', PHP_VERSION);
34199 $version = $this->versionParser->normalize($prettyVersion);
34200 }
34201
34202 $php = new CompletePackage('php', $version, $prettyVersion);
34203 $php->setDescription('The PHP interpreter');
34204 $this->addPackage($php);
34205
34206 if (PHP_DEBUG) {
34207 $phpdebug = new CompletePackage('php-debug', $version, $prettyVersion);
34208 $phpdebug->setDescription('The PHP interpreter, with debugging symbols');
34209 $this->addPackage($phpdebug);
34210 }
34211
34212 if (defined('PHP_ZTS') && PHP_ZTS) {
34213 $phpzts = new CompletePackage('php-zts', $version, $prettyVersion);
34214 $phpzts->setDescription('The PHP interpreter, with Zend Thread Safety');
34215 $this->addPackage($phpzts);
34216 }
34217
34218 if (PHP_INT_SIZE === 8) {
34219 $php64 = new CompletePackage('php-64bit', $version, $prettyVersion);
34220 $php64->setDescription('The PHP interpreter, 64bit');
34221 $this->addPackage($php64);
34222 }
34223
34224
34225  
34226  if (defined('AF_INET6') || Silencer::call('inet_pton', '::') !== false) {
34227 $phpIpv6 = new CompletePackage('php-ipv6', $version, $prettyVersion);
34228 $phpIpv6->setDescription('The PHP interpreter, with IPv6 support');
34229 $this->addPackage($phpIpv6);
34230 }
34231
34232 $loadedExtensions = get_loaded_extensions();
34233
34234
34235  foreach ($loadedExtensions as $name) {
34236 if (in_array($name, array('standard', 'Core'))) {
34237 continue;
34238 }
34239
34240 $reflExt = new \ReflectionExtension($name);
34241 $prettyVersion = $reflExt->getVersion();
34242 $this->addExtension($name, $prettyVersion);
34243 }
34244
34245
34246  if (!in_array('xdebug', $loadedExtensions, true) && ($prettyVersion = strval(getenv(XdebugHandler::ENV_VERSION)))) {
34247 $this->addExtension('xdebug', $prettyVersion);
34248 }
34249
34250
34251  
34252  
34253  foreach ($loadedExtensions as $name) {
34254 $prettyVersion = null;
34255 $description = 'The '.$name.' PHP library';
34256 switch ($name) {
34257 case 'curl':
34258 $curlVersion = curl_version();
34259 $prettyVersion = $curlVersion['version'];
34260 break;
34261
34262 case 'iconv':
34263 $prettyVersion = ICONV_VERSION;
34264 break;
34265
34266 case 'intl':
34267 $name = 'ICU';
34268 if (defined('INTL_ICU_VERSION')) {
34269 $prettyVersion = INTL_ICU_VERSION;
34270 } else {
34271 $reflector = new \ReflectionExtension('intl');
34272
34273 ob_start();
34274 $reflector->info();
34275 $output = ob_get_clean();
34276
34277 preg_match('/^ICU version => (.*)$/m', $output, $matches);
34278 $prettyVersion = $matches[1];
34279 }
34280
34281 break;
34282
34283 case 'libxml':
34284 $prettyVersion = LIBXML_DOTTED_VERSION;
34285 break;
34286
34287 case 'openssl':
34288 $prettyVersion = preg_replace_callback('{^(?:OpenSSL|LibreSSL)?\s*([0-9.]+)([a-z]*).*}i', function ($match) {
34289 if (empty($match[2])) {
34290 return $match[1];
34291 }
34292
34293
34294  
34295
34296 if (!preg_match('{^z*[a-z]$}', $match[2])) {
34297
34298  return 0;
34299 }
34300
34301 $len = strlen($match[2]);
34302 $patchVersion = ($len - 1) * 26; 
34303  $patchVersion += ord($match[2][$len - 1]) - 96;
34304
34305 return $match[1].'.'.$patchVersion;
34306 }, OPENSSL_VERSION_TEXT);
34307
34308 $description = OPENSSL_VERSION_TEXT;
34309 break;
34310
34311 case 'pcre':
34312 $prettyVersion = preg_replace('{^(\S+).*}', '$1', PCRE_VERSION);
34313 break;
34314
34315 case 'uuid':
34316 $prettyVersion = phpversion('uuid');
34317 break;
34318
34319 case 'xsl':
34320 $prettyVersion = LIBXSLT_DOTTED_VERSION;
34321 break;
34322
34323 default:
34324
34325  continue 2;
34326 }
34327
34328 try {
34329 $version = $this->versionParser->normalize($prettyVersion);
34330 } catch (\UnexpectedValueException $e) {
34331 continue;
34332 }
34333
34334 $lib = new CompletePackage('lib-'.$name, $version, $prettyVersion);
34335 $lib->setDescription($description);
34336 $this->addPackage($lib);
34337 }
34338
34339 if (defined('HHVM_VERSION')) {
34340 try {
34341 $prettyVersion = HHVM_VERSION;
34342 $version = $this->versionParser->normalize($prettyVersion);
34343 } catch (\UnexpectedValueException $e) {
34344 $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', HHVM_VERSION);
34345 $version = $this->versionParser->normalize($prettyVersion);
34346 }
34347
34348 $hhvm = new CompletePackage('hhvm', $version, $prettyVersion);
34349 $hhvm->setDescription('The HHVM Runtime (64bit)');
34350 $this->addPackage($hhvm);
34351 }
34352 }
34353
34354
34355
34356
34357 public function addPackage(PackageInterface $package)
34358 {
34359
34360  if (isset($this->overrides[$package->getName()])) {
34361 $overrider = $this->findPackage($package->getName(), '*');
34362 $overrider->setDescription($overrider->getDescription().' (actual: '.$package->getPrettyVersion().')');
34363
34364 return;
34365 }
34366
34367
34368  if (isset($this->overrides['php']) && 0 === strpos($package->getName(), 'php-')) {
34369 $overrider = $this->addOverriddenPackage($this->overrides['php'], $package->getPrettyName());
34370 $overrider->setDescription($overrider->getDescription().' (actual: '.$package->getPrettyVersion().')');
34371
34372 return;
34373 }
34374
34375 parent::addPackage($package);
34376 }
34377
34378 private function addOverriddenPackage(array $override, $name = null)
34379 {
34380 $version = $this->versionParser->normalize($override['version']);
34381 $package = new CompletePackage($name ?: $override['name'], $version, $override['version']);
34382 $package->setDescription('Package overridden via config.platform');
34383 $package->setExtra(array('config.platform' => true));
34384 parent::addPackage($package);
34385
34386 return $package;
34387 }
34388
34389
34390
34391
34392
34393
34394
34395 private function addExtension($name, $prettyVersion)
34396 {
34397 $extraDescription = null;
34398
34399 try {
34400 $version = $this->versionParser->normalize($prettyVersion);
34401 } catch (\UnexpectedValueException $e) {
34402 $extraDescription = ' (actual version: '.$prettyVersion.')';
34403 if (preg_match('{^(\d+\.\d+\.\d+(?:\.\d+)?)}', $prettyVersion, $match)) {
34404 $prettyVersion = $match[1];
34405 } else {
34406 $prettyVersion = '0';
34407 }
34408 $version = $this->versionParser->normalize($prettyVersion);
34409 }
34410
34411 $packageName = $this->buildPackageName($name);
34412 $ext = new CompletePackage($packageName, $version, $prettyVersion);
34413 $ext->setDescription('The '.$name.' PHP extension'.$extraDescription);
34414 $this->addPackage($ext);
34415 }
34416
34417 private function buildPackageName($name)
34418 {
34419 return 'ext-' . str_replace(' ', '-', $name);
34420 }
34421 }
34422 <?php
34423
34424
34425
34426
34427
34428
34429
34430
34431
34432
34433
34434 namespace Composer\Repository;
34435
34436 use Composer\Factory;
34437 use Composer\IO\IOInterface;
34438 use Composer\Config;
34439 use Composer\EventDispatcher\EventDispatcher;
34440 use Composer\Util\RemoteFilesystem;
34441 use Composer\Json\JsonFile;
34442
34443
34444
34445
34446 class RepositoryFactory
34447 {
34448
34449
34450
34451
34452
34453
34454
34455 public static function configFromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false)
34456 {
34457 if (0 === strpos($repository, 'http')) {
34458 $repoConfig = array('type' => 'composer', 'url' => $repository);
34459 } elseif ("json" === pathinfo($repository, PATHINFO_EXTENSION)) {
34460 $json = new JsonFile($repository, Factory::createRemoteFilesystem($io, $config));
34461 $data = $json->read();
34462 if (!empty($data['packages']) || !empty($data['includes']) || !empty($data['provider-includes'])) {
34463 $repoConfig = array('type' => 'composer', 'url' => 'file://' . strtr(realpath($repository), '\\', '/'));
34464 } elseif ($allowFilesystem) {
34465 $repoConfig = array('type' => 'filesystem', 'json' => $json);
34466 } else {
34467 throw new \InvalidArgumentException("Invalid repository URL ($repository) given. This file does not contain a valid composer repository.");
34468 }
34469 } elseif ('{' === substr($repository, 0, 1)) {
34470
34471  $repoConfig = JsonFile::parseJson($repository);
34472 } else {
34473 throw new \InvalidArgumentException("Invalid repository url ($repository) given. Has to be a .json file, an http url or a JSON object.");
34474 }
34475
34476 return $repoConfig;
34477 }
34478
34479
34480
34481
34482
34483
34484
34485
34486 public static function fromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false)
34487 {
34488 $repoConfig = static::configFromString($io, $config, $repository, $allowFilesystem);
34489
34490 return static::createRepo($io, $config, $repoConfig);
34491 }
34492
34493
34494
34495
34496
34497
34498
34499 public static function createRepo(IOInterface $io, Config $config, array $repoConfig)
34500 {
34501 $rm = static::manager($io, $config, null, Factory::createRemoteFilesystem($io, $config));
34502 $repos = static::createRepos($rm, array($repoConfig));
34503
34504 return reset($repos);
34505 }
34506
34507
34508
34509
34510
34511
34512
34513 public static function defaultRepos(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
34514 {
34515 if (!$config) {
34516 $config = Factory::createConfig($io);
34517 }
34518 if (!$rm) {
34519 if (!$io) {
34520 throw new \InvalidArgumentException('This function requires either an IOInterface or a RepositoryManager');
34521 }
34522 $rm = static::manager($io, $config, null, Factory::createRemoteFilesystem($io, $config));
34523 }
34524
34525 return static::createRepos($rm, $config->getRepositories());
34526 }
34527
34528
34529
34530
34531
34532
34533
34534
34535 public static function manager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
34536 {
34537 $rm = new RepositoryManager($io, $config, $eventDispatcher, $rfs);
34538 $rm->setRepositoryClass('composer', 'Composer\Repository\ComposerRepository');
34539 $rm->setRepositoryClass('vcs', 'Composer\Repository\VcsRepository');
34540 $rm->setRepositoryClass('package', 'Composer\Repository\PackageRepository');
34541 $rm->setRepositoryClass('pear', 'Composer\Repository\PearRepository');
34542 $rm->setRepositoryClass('git', 'Composer\Repository\VcsRepository');
34543 $rm->setRepositoryClass('github', 'Composer\Repository\VcsRepository');
34544 $rm->setRepositoryClass('gitlab', 'Composer\Repository\VcsRepository');
34545 $rm->setRepositoryClass('svn', 'Composer\Repository\VcsRepository');
34546 $rm->setRepositoryClass('fossil', 'Composer\Repository\VcsRepository');
34547 $rm->setRepositoryClass('perforce', 'Composer\Repository\VcsRepository');
34548 $rm->setRepositoryClass('hg', 'Composer\Repository\VcsRepository');
34549 $rm->setRepositoryClass('artifact', 'Composer\Repository\ArtifactRepository');
34550 $rm->setRepositoryClass('path', 'Composer\Repository\PathRepository');
34551
34552 return $rm;
34553 }
34554
34555
34556
34557
34558 private static function createRepos(RepositoryManager $rm, array $repoConfigs)
34559 {
34560 $repos = array();
34561
34562 foreach ($repoConfigs as $index => $repo) {
34563 if (is_string($repo)) {
34564 throw new \UnexpectedValueException('"repositories" should be an array of repository definitions, only a single repository was given');
34565 }
34566 if (!is_array($repo)) {
34567 throw new \UnexpectedValueException('Repository "'.$index.'" ('.json_encode($repo).') should be an array, '.gettype($repo).' given');
34568 }
34569 if (!isset($repo['type'])) {
34570 throw new \UnexpectedValueException('Repository "'.$index.'" ('.json_encode($repo).') must have a type defined');
34571 }
34572 $name = is_int($index) && isset($repo['url']) ? preg_replace('{^https?://}i', '', $repo['url']) : $index;
34573 while (isset($repos[$name])) {
34574 $name .= '2';
34575 }
34576 if ($repo['type'] === 'filesystem') {
34577 $repos[$name] = new FilesystemRepository($repo['json']);
34578 } else {
34579 $repos[$name] = $rm->createRepository($repo['type'], $repo, $index);
34580 }
34581 }
34582
34583 return $repos;
34584 }
34585 }
34586 <?php
34587
34588
34589
34590
34591
34592
34593
34594
34595
34596
34597
34598 namespace Composer\Repository;
34599
34600 use Composer\Package\PackageInterface;
34601
34602
34603
34604
34605
34606
34607
34608
34609 interface RepositoryInterface extends \Countable
34610 {
34611 const SEARCH_FULLTEXT = 0;
34612 const SEARCH_NAME = 1;
34613
34614
34615
34616
34617
34618
34619
34620
34621 public function hasPackage(PackageInterface $package);
34622
34623
34624
34625
34626
34627
34628
34629
34630
34631 public function findPackage($name, $constraint);
34632
34633
34634
34635
34636
34637
34638
34639
34640
34641 public function findPackages($name, $constraint = null);
34642
34643
34644
34645
34646
34647
34648 public function getPackages();
34649
34650
34651
34652
34653
34654
34655
34656
34657
34658 public function search($query, $mode = 0);
34659 }
34660 <?php
34661
34662
34663
34664
34665
34666
34667
34668
34669
34670
34671
34672 namespace Composer\Repository;
34673
34674 use Composer\IO\IOInterface;
34675 use Composer\Config;
34676 use Composer\EventDispatcher\EventDispatcher;
34677 use Composer\Package\PackageInterface;
34678 use Composer\Util\RemoteFilesystem;
34679
34680
34681
34682
34683
34684
34685
34686
34687 class RepositoryManager
34688 {
34689 private $localRepository;
34690 private $repositories = array();
34691 private $repositoryClasses = array();
34692 private $io;
34693 private $config;
34694 private $eventDispatcher;
34695 private $rfs;
34696
34697 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
34698 {
34699 $this->io = $io;
34700 $this->config = $config;
34701 $this->eventDispatcher = $eventDispatcher;
34702 $this->rfs = $rfs;
34703 }
34704
34705
34706
34707
34708
34709
34710
34711
34712
34713 public function findPackage($name, $constraint)
34714 {
34715 foreach ($this->repositories as $repository) {
34716 if ($package = $repository->findPackage($name, $constraint)) {
34717 return $package;
34718 }
34719 }
34720
34721 return null;
34722 }
34723
34724
34725
34726
34727
34728
34729
34730
34731
34732 public function findPackages($name, $constraint)
34733 {
34734 $packages = array();
34735
34736 foreach ($this->repositories as $repository) {
34737 $packages = array_merge($packages, $repository->findPackages($name, $constraint));
34738 }
34739
34740 return $packages;
34741 }
34742
34743
34744
34745
34746
34747
34748 public function addRepository(RepositoryInterface $repository)
34749 {
34750 $this->repositories[] = $repository;
34751 }
34752
34753
34754
34755
34756
34757
34758
34759
34760 public function prependRepository(RepositoryInterface $repository)
34761 {
34762 array_unshift($this->repositories, $repository);
34763 }
34764
34765
34766
34767
34768
34769
34770
34771
34772
34773
34774 public function createRepository($type, $config, $name = null)
34775 {
34776 if (!isset($this->repositoryClasses[$type])) {
34777 throw new \InvalidArgumentException('Repository type is not registered: '.$type);
34778 }
34779
34780 if (isset($config['packagist']) && false === $config['packagist']) {
34781 $this->io->writeError('<warning>Repository "'.$name.'" ('.json_encode($config).') has a packagist key which should be in its own repository definition</warning>');
34782 }
34783
34784 $class = $this->repositoryClasses[$type];
34785
34786 $reflMethod = new \ReflectionMethod($class, '__construct');
34787 $params = $reflMethod->getParameters();
34788 if (isset($params[4]) && $params[4]->getClass() && $params[4]->getClass()->getName() === 'Composer\Util\RemoteFilesystem') {
34789 return new $class($config, $this->io, $this->config, $this->eventDispatcher, $this->rfs);
34790 }
34791
34792 return new $class($config, $this->io, $this->config, $this->eventDispatcher);
34793 }
34794
34795
34796
34797
34798
34799
34800
34801 public function setRepositoryClass($type, $class)
34802 {
34803 $this->repositoryClasses[$type] = $class;
34804 }
34805
34806
34807
34808
34809
34810
34811 public function getRepositories()
34812 {
34813 return $this->repositories;
34814 }
34815
34816
34817
34818
34819
34820
34821 public function setLocalRepository(WritableRepositoryInterface $repository)
34822 {
34823 $this->localRepository = $repository;
34824 }
34825
34826
34827
34828
34829
34830
34831 public function getLocalRepository()
34832 {
34833 return $this->localRepository;
34834 }
34835 }
34836 <?php
34837
34838
34839
34840
34841
34842
34843
34844
34845
34846
34847
34848 namespace Composer\Repository;
34849
34850
34851
34852
34853
34854
34855 class RepositorySecurityException extends \Exception
34856 {
34857 }
34858 <?php
34859
34860
34861
34862
34863
34864
34865
34866
34867
34868
34869
34870 namespace Composer\Repository\Vcs;
34871
34872 use Composer\Cache;
34873 use Composer\Downloader\TransportException;
34874 use Composer\Json\JsonFile;
34875 use Composer\Util\Bitbucket;
34876
34877 abstract class BitbucketDriver extends VcsDriver
34878 {
34879
34880 protected $cache;
34881 protected $owner;
34882 protected $repository;
34883 protected $hasIssues;
34884 protected $rootIdentifier;
34885 protected $tags;
34886 protected $branches;
34887 protected $infoCache = array();
34888 protected $branchesUrl = '';
34889 protected $tagsUrl = '';
34890 protected $homeUrl = '';
34891 protected $website = '';
34892 protected $cloneHttpsUrl = '';
34893
34894
34895
34896
34897 protected $fallbackDriver;
34898
34899 protected $vcsType;
34900
34901
34902
34903
34904 public function initialize()
34905 {
34906 preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+?)(\.git|/?)$#', $this->url, $match);
34907 $this->owner = $match[1];
34908 $this->repository = $match[2];
34909 $this->originUrl = 'bitbucket.org';
34910 $this->cache = new Cache(
34911 $this->io,
34912 implode('/', array(
34913 $this->config->get('cache-repo-dir'),
34914 $this->originUrl,
34915 $this->owner,
34916 $this->repository,
34917 ))
34918 );
34919 }
34920
34921
34922
34923
34924 public function getUrl()
34925 {
34926 if ($this->fallbackDriver) {
34927 return $this->fallbackDriver->getUrl();
34928 }
34929
34930 return $this->cloneHttpsUrl;
34931 }
34932
34933
34934
34935
34936
34937
34938
34939 protected function getRepoData()
34940 {
34941 $resource = sprintf(
34942 'https://api.bitbucket.org/2.0/repositories/%s/%s?%s',
34943 $this->owner,
34944 $this->repository,
34945 http_build_query(
34946 array('fields' => '-project,-owner'),
34947 null,
34948 '&'
34949 )
34950 );
34951
34952 $repoData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource, true), $resource);
34953 if ($this->fallbackDriver) {
34954 return false;
34955 }
34956 $this->parseCloneUrls($repoData['links']['clone']);
34957
34958 $this->hasIssues = !empty($repoData['has_issues']);
34959 $this->branchesUrl = $repoData['links']['branches']['href'];
34960 $this->tagsUrl = $repoData['links']['tags']['href'];
34961 $this->homeUrl = $repoData['links']['html']['href'];
34962 $this->website = $repoData['website'];
34963 $this->vcsType = $repoData['scm'];
34964
34965 return true;
34966 }
34967
34968
34969
34970
34971 public function getComposerInformation($identifier)
34972 {
34973 if ($this->fallbackDriver) {
34974 return $this->fallbackDriver->getComposerInformation($identifier);
34975 }
34976
34977 if (!isset($this->infoCache[$identifier])) {
34978 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
34979 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
34980 }
34981
34982 $composer = $this->getBaseComposerInformation($identifier);
34983
34984
34985  if (!isset($composer['support']['source'])) {
34986 $label = array_search(
34987 $identifier,
34988 $this->getTags()
34989 ) ?: array_search(
34990 $identifier,
34991 $this->getBranches()
34992 ) ?: $identifier;
34993
34994 if (array_key_exists($label, $tags = $this->getTags())) {
34995 $hash = $tags[$label];
34996 } elseif (array_key_exists($label, $branches = $this->getBranches())) {
34997 $hash = $branches[$label];
34998 }
34999
35000 if (! isset($hash)) {
35001 $composer['support']['source'] = sprintf(
35002 'https://%s/%s/%s/src',
35003 $this->originUrl,
35004 $this->owner,
35005 $this->repository
35006 );
35007 } else {
35008 $composer['support']['source'] = sprintf(
35009 'https://%s/%s/%s/src/%s/?at=%s',
35010 $this->originUrl,
35011 $this->owner,
35012 $this->repository,
35013 $hash,
35014 $label
35015 );
35016 }
35017 }
35018 if (!isset($composer['support']['issues']) && $this->hasIssues) {
35019 $composer['support']['issues'] = sprintf(
35020 'https://%s/%s/%s/issues',
35021 $this->originUrl,
35022 $this->owner,
35023 $this->repository
35024 );
35025 }
35026 if (!isset($composer['homepage'])) {
35027 $composer['homepage'] = empty($this->website) ? $this->homeUrl : $this->website;
35028 }
35029
35030 $this->infoCache[$identifier] = $composer;
35031
35032 if ($this->shouldCache($identifier)) {
35033 $this->cache->write($identifier, json_encode($composer));
35034 }
35035 }
35036
35037 return $this->infoCache[$identifier];
35038 }
35039
35040
35041
35042
35043 public function getFileContent($file, $identifier)
35044 {
35045 if ($this->fallbackDriver) {
35046 return $this->fallbackDriver->getFileContent($file, $identifier);
35047 }
35048
35049 $resource = sprintf(
35050 'https://api.bitbucket.org/1.0/repositories/%s/%s/raw/%s/%s',
35051 $this->owner,
35052 $this->repository,
35053 $identifier,
35054 $file
35055 );
35056
35057 return $this->getContentsWithOAuthCredentials($resource);
35058 }
35059
35060
35061
35062
35063 public function getChangeDate($identifier)
35064 {
35065 if ($this->fallbackDriver) {
35066 return $this->fallbackDriver->getChangeDate($identifier);
35067 }
35068
35069 $resource = sprintf(
35070 'https://api.bitbucket.org/2.0/repositories/%s/%s/commit/%s?fields=date',
35071 $this->owner,
35072 $this->repository,
35073 $identifier
35074 );
35075 $commit = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
35076
35077 return new \DateTime($commit['date']);
35078 }
35079
35080
35081
35082
35083 public function getSource($identifier)
35084 {
35085 if ($this->fallbackDriver) {
35086 return $this->fallbackDriver->getSource($identifier);
35087 }
35088
35089 return array('type' => $this->vcsType, 'url' => $this->getUrl(), 'reference' => $identifier);
35090 }
35091
35092
35093
35094
35095 public function getDist($identifier)
35096 {
35097 if ($this->fallbackDriver) {
35098 return $this->fallbackDriver->getDist($identifier);
35099 }
35100
35101 $url = sprintf(
35102 'https://bitbucket.org/%s/%s/get/%s.zip',
35103 $this->owner,
35104 $this->repository,
35105 $identifier
35106 );
35107
35108 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
35109 }
35110
35111
35112
35113
35114 public function getTags()
35115 {
35116 if ($this->fallbackDriver) {
35117 return $this->fallbackDriver->getTags();
35118 }
35119
35120 if (null === $this->tags) {
35121 $this->tags = array();
35122 $resource = sprintf(
35123 '%s?%s',
35124 $this->tagsUrl,
35125 http_build_query(
35126 array(
35127 'pagelen' => 100,
35128 'fields' => 'values.name,values.target.hash,next',
35129 'sort' => '-target.date',
35130 ),
35131 null,
35132 '&'
35133 )
35134 );
35135 $hasNext = true;
35136 while ($hasNext) {
35137 $tagsData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
35138 foreach ($tagsData['values'] as $data) {
35139 $this->tags[$data['name']] = $data['target']['hash'];
35140 }
35141 if (empty($tagsData['next'])) {
35142 $hasNext = false;
35143 } else {
35144 $resource = $tagsData['next'];
35145 }
35146 }
35147 if ($this->vcsType === 'hg') {
35148 unset($this->tags['tip']);
35149 }
35150 }
35151
35152 return $this->tags;
35153 }
35154
35155
35156
35157
35158 public function getBranches()
35159 {
35160 if ($this->fallbackDriver) {
35161 return $this->fallbackDriver->getBranches();
35162 }
35163
35164 if (null === $this->branches) {
35165 $this->branches = array();
35166 $resource = sprintf(
35167 '%s?%s',
35168 $this->branchesUrl,
35169 http_build_query(
35170 array(
35171 'pagelen' => 100,
35172 'fields' => 'values.name,values.target.hash,values.heads,next',
35173 'sort' => '-target.date',
35174 ),
35175 null,
35176 '&'
35177 )
35178 );
35179 $hasNext = true;
35180 while ($hasNext) {
35181 $branchData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
35182 foreach ($branchData['values'] as $data) {
35183
35184  if ($this->vcsType === 'hg' && empty($data['heads'])) {
35185 continue;
35186 }
35187
35188 $this->branches[$data['name']] = $data['target']['hash'];
35189 }
35190 if (empty($branchData['next'])) {
35191 $hasNext = false;
35192 } else {
35193 $resource = $branchData['next'];
35194 }
35195 }
35196 }
35197
35198 return $this->branches;
35199 }
35200
35201
35202
35203
35204
35205
35206
35207
35208
35209 protected function getContentsWithOAuthCredentials($url, $fetchingRepoData = false)
35210 {
35211 try {
35212 return parent::getContents($url);
35213 } catch (TransportException $e) {
35214 $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process, $this->remoteFilesystem);
35215
35216 if (403 === $e->getCode() || (401 === $e->getCode() && strpos($e->getMessage(), 'Could not authenticate against') === 0)) {
35217 if (!$this->io->hasAuthentication($this->originUrl)
35218 && $bitbucketUtil->authorizeOAuth($this->originUrl)
35219 ) {
35220 return parent::getContents($url);
35221 }
35222
35223 if (!$this->io->isInteractive() && $fetchingRepoData) {
35224 return $this->attemptCloneFallback();
35225 }
35226 }
35227
35228 throw $e;
35229 }
35230 }
35231
35232
35233
35234
35235
35236
35237 abstract protected function generateSshUrl();
35238
35239 protected function attemptCloneFallback()
35240 {
35241 try {
35242 $this->setupFallbackDriver($this->generateSshUrl());
35243 } catch (\RuntimeException $e) {
35244 $this->fallbackDriver = null;
35245
35246 $this->io->writeError(
35247 '<error>Failed to clone the ' . $this->generateSshUrl() . ' repository, try running in interactive mode'
35248 . ' so that you can enter your Bitbucket OAuth consumer credentials</error>'
35249 );
35250 throw $e;
35251 }
35252 }
35253
35254
35255
35256
35257
35258 abstract protected function setupFallbackDriver($url);
35259
35260
35261
35262
35263
35264 protected function parseCloneUrls(array $cloneLinks)
35265 {
35266 foreach ($cloneLinks as $cloneLink) {
35267 if ($cloneLink['name'] === 'https') {
35268
35269  
35270  $this->cloneHttpsUrl = preg_replace('/https:\/\/([^@]+@)?/', 'https://', $cloneLink['href']);
35271 }
35272 }
35273 }
35274
35275
35276
35277
35278 protected function getMainBranchData()
35279 {
35280 $resource = sprintf(
35281 'https://api.bitbucket.org/1.0/repositories/%s/%s/main-branch',
35282 $this->owner,
35283 $this->repository
35284 );
35285
35286 return JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
35287 }
35288 }
35289 <?php
35290
35291
35292
35293
35294
35295
35296
35297
35298
35299
35300
35301 namespace Composer\Repository\Vcs;
35302
35303 use Composer\Config;
35304 use Composer\Util\ProcessExecutor;
35305 use Composer\Util\Filesystem;
35306 use Composer\IO\IOInterface;
35307
35308
35309
35310
35311 class FossilDriver extends VcsDriver
35312 {
35313 protected $tags;
35314 protected $branches;
35315 protected $rootIdentifier;
35316 protected $repoFile;
35317 protected $checkoutDir;
35318 protected $infoCache = array();
35319
35320
35321
35322
35323 public function initialize()
35324 {
35325 if (Filesystem::isLocalPath($this->url)) {
35326 $this->checkoutDir = $this->url;
35327 } else {
35328 $this->repoFile = $this->config->get('cache-repo-dir') . '/' . preg_replace('{[^a-z0-9]}i', '-', $this->url) . '.fossil';
35329 $this->checkoutDir = $this->config->get('cache-vcs-dir') . '/' . preg_replace('{[^a-z0-9]}i', '-', $this->url) . '/';
35330
35331 $fs = new Filesystem();
35332 $fs->ensureDirectoryExists($this->checkoutDir);
35333
35334 if (!is_writable(dirname($this->checkoutDir))) {
35335 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$this->checkoutDir.'" directory is not writable by the current user.');
35336 }
35337
35338
35339  $this->config->prohibitUrlByConfig($this->url, $this->io);
35340
35341
35342  if (is_file($this->repoFile) && is_dir($this->checkoutDir) && 0 === $this->process->execute('fossil info', $output, $this->checkoutDir)) {
35343 if (0 !== $this->process->execute('fossil pull', $output, $this->checkoutDir)) {
35344 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')</error>');
35345 }
35346 } else {
35347
35348  $fs->removeDirectory($this->checkoutDir);
35349 $fs->remove($this->repoFile);
35350
35351 $fs->ensureDirectoryExists($this->checkoutDir);
35352
35353 if (0 !== $this->process->execute(sprintf('fossil clone %s %s', ProcessExecutor::escape($this->url), ProcessExecutor::escape($this->repoFile)), $output)) {
35354 $output = $this->process->getErrorOutput();
35355
35356 if (0 !== $this->process->execute('fossil version', $ignoredOutput)) {
35357 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());
35358 }
35359
35360 throw new \RuntimeException('Failed to clone '.$this->url.' to repository ' . $this->repoFile . "\n\n" .$output);
35361 }
35362
35363 if (0 !== $this->process->execute(sprintf('fossil open %s', ProcessExecutor::escape($this->repoFile)), $output, $this->checkoutDir)) {
35364 $output = $this->process->getErrorOutput();
35365
35366 throw new \RuntimeException('Failed to open repository '.$this->repoFile.' in ' . $this->checkoutDir . "\n\n" .$output);
35367 }
35368 }
35369 }
35370
35371 $this->getTags();
35372 $this->getBranches();
35373 }
35374
35375
35376
35377
35378 public function getRootIdentifier()
35379 {
35380 if (null === $this->rootIdentifier) {
35381 $this->rootIdentifier = 'trunk';
35382 }
35383
35384 return $this->rootIdentifier;
35385 }
35386
35387
35388
35389
35390 public function getUrl()
35391 {
35392 return $this->url;
35393 }
35394
35395
35396
35397
35398 public function getSource($identifier)
35399 {
35400 return array('type' => 'fossil', 'url' => $this->getUrl(), 'reference' => $identifier);
35401 }
35402
35403
35404
35405
35406 public function getDist($identifier)
35407 {
35408 return null;
35409 }
35410
35411
35412
35413
35414 public function getFileContent($file, $identifier)
35415 {
35416 $command = sprintf('fossil cat -r %s %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
35417 $this->process->execute($command, $content, $this->checkoutDir);
35418
35419 if (!trim($content)) {
35420 return null;
35421 }
35422
35423 return $content;
35424 }
35425
35426
35427
35428
35429 public function getChangeDate($identifier)
35430 {
35431 $this->process->execute(sprintf('fossil finfo composer.json | head -n 2 | tail -n 1 | awk \'{print $1}\''), $output, $this->checkoutDir);
35432
35433 return new \DateTime(trim($output), new \DateTimeZone('UTC'));
35434 }
35435
35436
35437
35438
35439 public function getTags()
35440 {
35441 if (null === $this->tags) {
35442 $tags = array();
35443
35444 $this->process->execute('fossil tag list', $output, $this->checkoutDir);
35445 foreach ($this->process->splitLines($output) as $tag) {
35446 $tags[$tag] = $tag;
35447 }
35448
35449 $this->tags = $tags;
35450 }
35451
35452 return $this->tags;
35453 }
35454
35455
35456
35457
35458 public function getBranches()
35459 {
35460 if (null === $this->branches) {
35461 $branches = array();
35462 $bookmarks = array();
35463
35464 $this->process->execute('fossil branch list', $output, $this->checkoutDir);
35465 foreach ($this->process->splitLines($output) as $branch) {
35466 $branch = trim(preg_replace('/^\*/', '', trim($branch)));
35467 $branches[$branch] = $branch;
35468 }
35469
35470 $this->branches = $branches;
35471 }
35472
35473 return $this->branches;
35474 }
35475
35476
35477
35478
35479 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
35480 {
35481 if (preg_match('#(^(?:https?|ssh)://(?:[^@]@)?(?:chiselapp\.com|fossil\.))#i', $url)) {
35482 return true;
35483 }
35484
35485 if (preg_match('!/fossil/|\.fossil!', $url)) {
35486 return true;
35487 }
35488
35489
35490  if (Filesystem::isLocalPath($url)) {
35491 $url = Filesystem::getPlatformPath($url);
35492 if (!is_dir($url)) {
35493 return false;
35494 }
35495
35496 $process = new ProcessExecutor();
35497
35498  if ($process->execute('fossil info', $output, $url) === 0) {
35499 return true;
35500 }
35501 }
35502
35503 return false;
35504 }
35505 }
35506 <?php
35507
35508
35509
35510
35511
35512
35513
35514
35515
35516
35517
35518 namespace Composer\Repository\Vcs;
35519
35520 use Composer\Config;
35521 use Composer\IO\IOInterface;
35522
35523
35524
35525
35526 class GitBitbucketDriver extends BitbucketDriver
35527 {
35528
35529
35530
35531 public function getRootIdentifier()
35532 {
35533 if ($this->fallbackDriver) {
35534 return $this->fallbackDriver->getRootIdentifier();
35535 }
35536
35537 if (null === $this->rootIdentifier) {
35538 if (! $this->getRepoData()) {
35539 return $this->fallbackDriver->getRootIdentifier();
35540 }
35541
35542 if ($this->vcsType !== 'git') {
35543 throw new \RuntimeException(
35544 $this->url.' does not appear to be a git repository, use '.
35545 $this->cloneHttpsUrl.' if this is a mercurial bitbucket repository'
35546 );
35547 }
35548
35549 $mainBranchData = $this->getMainBranchData();
35550 $this->rootIdentifier = !empty($mainBranchData['name']) ? $mainBranchData['name'] : 'master';
35551 }
35552
35553 return $this->rootIdentifier;
35554 }
35555
35556
35557
35558
35559 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
35560 {
35561 if (!preg_match('#^https?://bitbucket\.org/([^/]+)/(.+?)\.git$#', $url)) {
35562 return false;
35563 }
35564
35565 if (!extension_loaded('openssl')) {
35566 $io->writeError('Skipping Bitbucket git driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
35567
35568 return false;
35569 }
35570
35571 return true;
35572 }
35573
35574
35575
35576
35577 protected function setupFallbackDriver($url)
35578 {
35579 $this->fallbackDriver = new GitDriver(
35580 array('url' => $url),
35581 $this->io,
35582 $this->config,
35583 $this->process,
35584 $this->remoteFilesystem
35585 );
35586 $this->fallbackDriver->initialize();
35587 }
35588
35589
35590
35591
35592 protected function generateSshUrl()
35593 {
35594 return 'git@' . $this->originUrl . ':' . $this->owner.'/'.$this->repository.'.git';
35595 }
35596 }
35597 <?php
35598
35599
35600
35601
35602
35603
35604
35605
35606
35607
35608
35609 namespace Composer\Repository\Vcs;
35610
35611 use Composer\Util\ProcessExecutor;
35612 use Composer\Util\Filesystem;
35613 use Composer\Util\Git as GitUtil;
35614 use Composer\IO\IOInterface;
35615 use Composer\Cache;
35616 use Composer\Config;
35617
35618
35619
35620
35621 class GitDriver extends VcsDriver
35622 {
35623 protected $cache;
35624 protected $tags;
35625 protected $branches;
35626 protected $rootIdentifier;
35627 protected $repoDir;
35628 protected $infoCache = array();
35629
35630
35631
35632
35633 public function initialize()
35634 {
35635 if (Filesystem::isLocalPath($this->url)) {
35636 $this->url = preg_replace('{[\\/]\.git/?$}', '', $this->url);
35637 $this->repoDir = $this->url;
35638 $cacheUrl = realpath($this->url);
35639 } else {
35640 $this->repoDir = $this->config->get('cache-vcs-dir') . '/' . preg_replace('{[^a-z0-9.]}i', '-', $this->url) . '/';
35641
35642 GitUtil::cleanEnv();
35643
35644 $fs = new Filesystem();
35645 $fs->ensureDirectoryExists(dirname($this->repoDir));
35646
35647 if (!is_writable(dirname($this->repoDir))) {
35648 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.dirname($this->repoDir).'" directory is not writable by the current user.');
35649 }
35650
35651 if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $this->url)) {
35652 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.');
35653 }
35654
35655 $gitUtil = new GitUtil($this->io, $this->config, $this->process, $fs);
35656 if (!$gitUtil->syncMirror($this->url, $this->repoDir)) {
35657 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated</error>');
35658 }
35659
35660 $cacheUrl = $this->url;
35661 }
35662
35663 $this->getTags();
35664 $this->getBranches();
35665
35666 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $cacheUrl));
35667 }
35668
35669
35670
35671
35672 public function getRootIdentifier()
35673 {
35674 if (null === $this->rootIdentifier) {
35675 $this->rootIdentifier = 'master';
35676
35677
35678  $this->process->execute('git branch --no-color', $output, $this->repoDir);
35679 $branches = $this->process->splitLines($output);
35680 if (!in_array('* master', $branches)) {
35681 foreach ($branches as $branch) {
35682 if ($branch && preg_match('{^\* +(\S+)}', $branch, $match)) {
35683 $this->rootIdentifier = $match[1];
35684 break;
35685 }
35686 }
35687 }
35688 }
35689
35690 return $this->rootIdentifier;
35691 }
35692
35693
35694
35695
35696 public function getUrl()
35697 {
35698 return $this->url;
35699 }
35700
35701
35702
35703
35704 public function getSource($identifier)
35705 {
35706 return array('type' => 'git', 'url' => $this->getUrl(), 'reference' => $identifier);
35707 }
35708
35709
35710
35711
35712 public function getDist($identifier)
35713 {
35714 return null;
35715 }
35716
35717
35718
35719
35720 public function getFileContent($file, $identifier)
35721 {
35722 $resource = sprintf('%s:%s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
35723 $this->process->execute(sprintf('git show %s', $resource), $content, $this->repoDir);
35724
35725 if (!trim($content)) {
35726 return null;
35727 }
35728
35729 return $content;
35730 }
35731
35732
35733
35734
35735 public function getChangeDate($identifier)
35736 {
35737 $this->process->execute(sprintf(
35738 'git log -1 --format=%%at %s',
35739 ProcessExecutor::escape($identifier)
35740 ), $output, $this->repoDir);
35741
35742 return new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
35743 }
35744
35745
35746
35747
35748 public function getTags()
35749 {
35750 if (null === $this->tags) {
35751 $this->tags = array();
35752
35753 $this->process->execute('git show-ref --tags --dereference', $output, $this->repoDir);
35754 foreach ($output = $this->process->splitLines($output) as $tag) {
35755 if ($tag && preg_match('{^([a-f0-9]{40}) refs/tags/(\S+?)(\^\{\})?$}', $tag, $match)) {
35756 $this->tags[$match[2]] = $match[1];
35757 }
35758 }
35759 }
35760
35761 return $this->tags;
35762 }
35763
35764
35765
35766
35767 public function getBranches()
35768 {
35769 if (null === $this->branches) {
35770 $branches = array();
35771
35772 $this->process->execute('git branch --no-color --no-abbrev -v', $output, $this->repoDir);
35773 foreach ($this->process->splitLines($output) as $branch) {
35774 if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
35775 if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+)(?: .*)?$}', $branch, $match)) {
35776 $branches[$match[1]] = $match[2];
35777 }
35778 }
35779 }
35780
35781 $this->branches = $branches;
35782 }
35783
35784 return $this->branches;
35785 }
35786
35787
35788
35789
35790 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
35791 {
35792 if (preg_match('#(^git://|\.git/?$|git(?:olite)?@|//git\.|//github.com/)#i', $url)) {
35793 return true;
35794 }
35795
35796
35797  if (Filesystem::isLocalPath($url)) {
35798 $url = Filesystem::getPlatformPath($url);
35799 if (!is_dir($url)) {
35800 return false;
35801 }
35802
35803 $process = new ProcessExecutor($io);
35804
35805  if ($process->execute('git tag', $output, $url) === 0) {
35806 return true;
35807 }
35808 }
35809
35810 if (!$deep) {
35811 return false;
35812 }
35813
35814 $process = new ProcessExecutor($io);
35815 if ($process->execute('git ls-remote --heads ' . ProcessExecutor::escape($url), $output) === 0) {
35816 return true;
35817 }
35818
35819 return false;
35820 }
35821 }
35822 <?php
35823
35824
35825
35826
35827
35828
35829
35830
35831
35832
35833
35834 namespace Composer\Repository\Vcs;
35835
35836 use Composer\Config;
35837 use Composer\Downloader\TransportException;
35838 use Composer\Json\JsonFile;
35839 use Composer\Cache;
35840 use Composer\IO\IOInterface;
35841 use Composer\Util\GitHub;
35842
35843
35844
35845
35846 class GitHubDriver extends VcsDriver
35847 {
35848 protected $cache;
35849 protected $owner;
35850 protected $repository;
35851 protected $tags;
35852 protected $branches;
35853 protected $rootIdentifier;
35854 protected $repoData;
35855 protected $hasIssues;
35856 protected $infoCache = array();
35857 protected $isPrivate = false;
35858
35859
35860
35861
35862
35863
35864 protected $gitDriver;
35865
35866
35867
35868
35869 public function initialize()
35870 {
35871 preg_match('#^(?:(?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git|/)?$#', $this->url, $match);
35872 $this->owner = $match[3];
35873 $this->repository = $match[4];
35874 $this->originUrl = !empty($match[1]) ? $match[1] : $match[2];
35875 if ($this->originUrl === 'www.github.com') {
35876 $this->originUrl = 'github.com';
35877 }
35878 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository);
35879
35880 if (isset($this->repoConfig['no-api']) && $this->repoConfig['no-api']) {
35881 $this->setupGitDriver($this->url);
35882
35883 return;
35884 }
35885
35886 $this->fetchRootIdentifier();
35887 }
35888
35889 public function getRepositoryUrl()
35890 {
35891 return 'https://'.$this->originUrl.'/'.$this->owner.'/'.$this->repository;
35892 }
35893
35894
35895
35896
35897 public function getRootIdentifier()
35898 {
35899 if ($this->gitDriver) {
35900 return $this->gitDriver->getRootIdentifier();
35901 }
35902
35903 return $this->rootIdentifier;
35904 }
35905
35906
35907
35908
35909 public function getUrl()
35910 {
35911 if ($this->gitDriver) {
35912 return $this->gitDriver->getUrl();
35913 }
35914
35915 return 'https://' . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git';
35916 }
35917
35918
35919
35920
35921 protected function getApiUrl()
35922 {
35923 if ('github.com' === $this->originUrl) {
35924 $apiUrl = 'api.github.com';
35925 } else {
35926 $apiUrl = $this->originUrl . '/api/v3';
35927 }
35928
35929 return 'https://' . $apiUrl;
35930 }
35931
35932
35933
35934
35935 public function getSource($identifier)
35936 {
35937 if ($this->gitDriver) {
35938 return $this->gitDriver->getSource($identifier);
35939 }
35940 if ($this->isPrivate) {
35941
35942  
35943  $url = $this->generateSshUrl();
35944 } else {
35945 $url = $this->getUrl();
35946 }
35947
35948 return array('type' => 'git', 'url' => $url, 'reference' => $identifier);
35949 }
35950
35951
35952
35953
35954 public function getDist($identifier)
35955 {
35956 $url = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/zipball/'.$identifier;
35957
35958 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
35959 }
35960
35961
35962
35963
35964 public function getComposerInformation($identifier)
35965 {
35966 if ($this->gitDriver) {
35967 return $this->gitDriver->getComposerInformation($identifier);
35968 }
35969
35970 if (!isset($this->infoCache[$identifier])) {
35971 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
35972 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
35973 }
35974
35975 $composer = $this->getBaseComposerInformation($identifier);
35976 if ($composer) {
35977
35978
35979  if (!isset($composer['support']['source'])) {
35980 $label = array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches()) ?: $identifier;
35981 $composer['support']['source'] = sprintf('https://%s/%s/%s/tree/%s', $this->originUrl, $this->owner, $this->repository, $label);
35982 }
35983 if (!isset($composer['support']['issues']) && $this->hasIssues) {
35984 $composer['support']['issues'] = sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository);
35985 }
35986 }
35987
35988 if ($this->shouldCache($identifier)) {
35989 $this->cache->write($identifier, json_encode($composer));
35990 }
35991
35992 $this->infoCache[$identifier] = $composer;
35993 }
35994
35995 return $this->infoCache[$identifier];
35996 }
35997
35998
35999
36000
36001 public function getFileContent($file, $identifier)
36002 {
36003 if ($this->gitDriver) {
36004 return $this->gitDriver->getFileContent($file, $identifier);
36005 }
36006
36007 $notFoundRetries = 2;
36008 while ($notFoundRetries) {
36009 try {
36010 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/contents/' . $file . '?ref='.urlencode($identifier);
36011 $resource = JsonFile::parseJson($this->getContents($resource));
36012 if (empty($resource['content']) || $resource['encoding'] !== 'base64' || !($content = base64_decode($resource['content']))) {
36013 throw new \RuntimeException('Could not retrieve ' . $file . ' for '.$identifier);
36014 }
36015
36016 return $content;
36017 } catch (TransportException $e) {
36018 if (404 !== $e->getCode()) {
36019 throw $e;
36020 }
36021
36022
36023  
36024  $notFoundRetries--;
36025
36026 return null;
36027 }
36028 }
36029
36030 return null;
36031 }
36032
36033
36034
36035
36036 public function getChangeDate($identifier)
36037 {
36038 if ($this->gitDriver) {
36039 return $this->gitDriver->getChangeDate($identifier);
36040 }
36041
36042 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/commits/'.urlencode($identifier);
36043 $commit = JsonFile::parseJson($this->getContents($resource), $resource);
36044
36045 return new \DateTime($commit['commit']['committer']['date']);
36046 }
36047
36048
36049
36050
36051 public function getTags()
36052 {
36053 if ($this->gitDriver) {
36054 return $this->gitDriver->getTags();
36055 }
36056 if (null === $this->tags) {
36057 $this->tags = array();
36058 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/tags?per_page=100';
36059
36060 do {
36061 $tagsData = JsonFile::parseJson($this->getContents($resource), $resource);
36062 foreach ($tagsData as $tag) {
36063 $this->tags[$tag['name']] = $tag['commit']['sha'];
36064 }
36065
36066 $resource = $this->getNextPage();
36067 } while ($resource);
36068 }
36069
36070 return $this->tags;
36071 }
36072
36073
36074
36075
36076 public function getBranches()
36077 {
36078 if ($this->gitDriver) {
36079 return $this->gitDriver->getBranches();
36080 }
36081 if (null === $this->branches) {
36082 $this->branches = array();
36083 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/git/refs/heads?per_page=100';
36084
36085 $branchBlacklist = array('gh-pages');
36086
36087 do {
36088 $branchData = JsonFile::parseJson($this->getContents($resource), $resource);
36089 foreach ($branchData as $branch) {
36090 $name = substr($branch['ref'], 11);
36091 if (!in_array($name, $branchBlacklist)) {
36092 $this->branches[$name] = $branch['object']['sha'];
36093 }
36094 }
36095
36096 $resource = $this->getNextPage();
36097 } while ($resource);
36098 }
36099
36100 return $this->branches;
36101 }
36102
36103
36104
36105
36106 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
36107 {
36108 if (!preg_match('#^((?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git|/)?$#', $url, $matches)) {
36109 return false;
36110 }
36111
36112 $originUrl = !empty($matches[2]) ? $matches[2] : $matches[3];
36113 if (!in_array(preg_replace('{^www\.}i', '', $originUrl), $config->get('github-domains'))) {
36114 return false;
36115 }
36116
36117 if (!extension_loaded('openssl')) {
36118 $io->writeError('Skipping GitHub driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
36119
36120 return false;
36121 }
36122
36123 return true;
36124 }
36125
36126
36127
36128
36129
36130
36131 public function getRepoData()
36132 {
36133 $this->fetchRootIdentifier();
36134
36135 return $this->repoData;
36136 }
36137
36138
36139
36140
36141
36142
36143 protected function generateSshUrl()
36144 {
36145 return 'git@' . $this->originUrl . ':'.$this->owner.'/'.$this->repository.'.git';
36146 }
36147
36148
36149
36150
36151 protected function getContents($url, $fetchingRepoData = false)
36152 {
36153 try {
36154 return parent::getContents($url);
36155 } catch (TransportException $e) {
36156 $gitHubUtil = new GitHub($this->io, $this->config, $this->process, $this->remoteFilesystem);
36157
36158 switch ($e->getCode()) {
36159 case 401:
36160 case 404:
36161
36162  if (!$fetchingRepoData) {
36163 throw $e;
36164 }
36165
36166 if ($gitHubUtil->authorizeOAuth($this->originUrl)) {
36167 return parent::getContents($url);
36168 }
36169
36170 if (!$this->io->isInteractive()) {
36171 return $this->attemptCloneFallback();
36172 }
36173
36174 $scopesIssued = array();
36175 $scopesNeeded = array();
36176 if ($headers = $e->getHeaders()) {
36177 if ($scopes = $this->remoteFilesystem->findHeaderValue($headers, 'X-OAuth-Scopes')) {
36178 $scopesIssued = explode(' ', $scopes);
36179 }
36180 if ($scopes = $this->remoteFilesystem->findHeaderValue($headers, 'X-Accepted-OAuth-Scopes')) {
36181 $scopesNeeded = explode(' ', $scopes);
36182 }
36183 }
36184 $scopesFailed = array_diff($scopesNeeded, $scopesIssued);
36185 if (!$headers || count($scopesFailed)) {
36186 $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'Your GitHub credentials are required to fetch private repository metadata (<info>'.$this->url.'</info>)');
36187 }
36188
36189 return parent::getContents($url);
36190
36191 case 403:
36192 if (!$this->io->hasAuthentication($this->originUrl) && $gitHubUtil->authorizeOAuth($this->originUrl)) {
36193 return parent::getContents($url);
36194 }
36195
36196 if (!$this->io->isInteractive() && $fetchingRepoData) {
36197 return $this->attemptCloneFallback();
36198 }
36199
36200 $rateLimited = false;
36201 foreach ($e->getHeaders() as $header) {
36202 if (preg_match('{^X-RateLimit-Remaining: *0$}i', trim($header))) {
36203 $rateLimited = true;
36204 }
36205 }
36206
36207 if (!$this->io->hasAuthentication($this->originUrl)) {
36208 if (!$this->io->isInteractive()) {
36209 $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>');
36210 throw $e;
36211 }
36212
36213 $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'API limit exhausted. Enter your GitHub credentials to get a larger API limit (<info>'.$this->url.'</info>)');
36214
36215 return parent::getContents($url);
36216 }
36217
36218 if ($rateLimited) {
36219 $rateLimit = $this->getRateLimit($e->getHeaders());
36220 $this->io->writeError(sprintf(
36221 '<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>',
36222 $rateLimit['limit'],
36223 $rateLimit['reset']
36224 ));
36225 }
36226
36227 throw $e;
36228
36229 default:
36230 throw $e;
36231 }
36232 }
36233 }
36234
36235
36236
36237
36238
36239
36240
36241
36242 protected function getRateLimit(array $headers)
36243 {
36244 $rateLimit = array(
36245 'limit' => '?',
36246 'reset' => '?',
36247 );
36248
36249 foreach ($headers as $header) {
36250 $header = trim($header);
36251 if (false === strpos($header, 'X-RateLimit-')) {
36252 continue;
36253 }
36254 list($type, $value) = explode(':', $header, 2);
36255 switch ($type) {
36256 case 'X-RateLimit-Limit':
36257 $rateLimit['limit'] = (int) trim($value);
36258 break;
36259 case 'X-RateLimit-Reset':
36260 $rateLimit['reset'] = date('Y-m-d H:i:s', (int) trim($value));
36261 break;
36262 }
36263 }
36264
36265 return $rateLimit;
36266 }
36267
36268
36269
36270
36271
36272
36273 protected function fetchRootIdentifier()
36274 {
36275 if ($this->repoData) {
36276 return;
36277 }
36278
36279 $repoDataUrl = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository;
36280
36281 $this->repoData = JsonFile::parseJson($this->getContents($repoDataUrl, true), $repoDataUrl);
36282 if (null === $this->repoData && null !== $this->gitDriver) {
36283 return;
36284 }
36285
36286 $this->owner = $this->repoData['owner']['login'];
36287 $this->repository = $this->repoData['name'];
36288
36289 $this->isPrivate = !empty($this->repoData['private']);
36290 if (isset($this->repoData['default_branch'])) {
36291 $this->rootIdentifier = $this->repoData['default_branch'];
36292 } elseif (isset($this->repoData['master_branch'])) {
36293 $this->rootIdentifier = $this->repoData['master_branch'];
36294 } else {
36295 $this->rootIdentifier = 'master';
36296 }
36297 $this->hasIssues = !empty($this->repoData['has_issues']);
36298 }
36299
36300 protected function attemptCloneFallback()
36301 {
36302 $this->isPrivate = true;
36303
36304 try {
36305
36306  
36307  
36308  
36309  $this->setupGitDriver($this->generateSshUrl());
36310
36311 return;
36312 } catch (\RuntimeException $e) {
36313 $this->gitDriver = null;
36314
36315 $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>');
36316 throw $e;
36317 }
36318 }
36319
36320 protected function setupGitDriver($url)
36321 {
36322 $this->gitDriver = new GitDriver(
36323 array('url' => $url),
36324 $this->io,
36325 $this->config,
36326 $this->process,
36327 $this->remoteFilesystem
36328 );
36329 $this->gitDriver->initialize();
36330 }
36331
36332 protected function getNextPage()
36333 {
36334 $headers = $this->remoteFilesystem->getLastHeaders();
36335 foreach ($headers as $header) {
36336 if (substr($header, 0, 5) === 'Link:') {
36337 $links = explode(',', substr($header, 5));
36338 foreach ($links as $link) {
36339 if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) {
36340 return $match[1];
36341 }
36342 }
36343 }
36344 }
36345 }
36346 }
36347 <?php
36348
36349
36350
36351
36352
36353
36354
36355
36356
36357
36358
36359 namespace Composer\Repository\Vcs;
36360
36361 use Composer\Config;
36362 use Composer\Cache;
36363 use Composer\IO\IOInterface;
36364 use Composer\Json\JsonFile;
36365 use Composer\Downloader\TransportException;
36366 use Composer\Util\RemoteFilesystem;
36367 use Composer\Util\GitLab;
36368
36369
36370
36371
36372
36373
36374
36375 class GitLabDriver extends VcsDriver
36376 {
36377 private $scheme;
36378 private $namespace;
36379 private $repository;
36380
36381
36382
36383
36384 private $project;
36385
36386
36387
36388
36389 private $commits = array();
36390
36391
36392
36393
36394 private $tags;
36395
36396
36397
36398
36399 private $branches;
36400
36401
36402
36403
36404
36405
36406 protected $gitDriver;
36407
36408
36409
36410
36411
36412
36413 private $isPrivate = true;
36414
36415 const URL_REGEX = '#^(?:(?P<scheme>https?)://(?P<domain>.+?)/|git@(?P<domain2>[^:]+):)(?P<parts>.+)/(?P<repo>[^/]+?)(?:\.git|/)?$#';
36416
36417
36418
36419
36420
36421
36422
36423
36424 public function initialize()
36425 {
36426 if (!preg_match(self::URL_REGEX, $this->url, $match)) {
36427 throw new \InvalidArgumentException('The URL provided is invalid. It must be the HTTP URL of a GitLab project.');
36428 }
36429
36430 $guessedDomain = !empty($match['domain']) ? $match['domain'] : $match['domain2'];
36431 $configuredDomains = $this->config->get('gitlab-domains');
36432 $urlParts = explode('/', $match['parts']);
36433
36434 $this->scheme = !empty($match['scheme'])
36435 ? $match['scheme']
36436 : (isset($this->repoConfig['secure-http']) && $this->repoConfig['secure-http'] === false ? 'http' : 'https')
36437 ;
36438 $this->originUrl = $this->determineOrigin($configuredDomains, $guessedDomain, $urlParts);
36439 $this->namespace = implode('/', $urlParts);
36440 $this->repository = preg_replace('#(\.git)$#', '', $match['repo']);
36441
36442 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->namespace.'/'.$this->repository);
36443
36444 $this->fetchProject();
36445 }
36446
36447
36448
36449
36450
36451
36452
36453 public function setRemoteFilesystem(RemoteFilesystem $remoteFilesystem)
36454 {
36455 $this->remoteFilesystem = $remoteFilesystem;
36456 }
36457
36458
36459
36460
36461 public function getFileContent($file, $identifier)
36462 {
36463 if ($this->gitDriver) {
36464 return $this->gitDriver->getFileContent($file, $identifier);
36465 }
36466
36467
36468  if (!preg_match('{[a-f0-9]{40}}i', $identifier)) {
36469 $branches = $this->getBranches();
36470 if (isset($branches[$identifier])) {
36471 $identifier = $branches[$identifier];
36472 }
36473 }
36474
36475 $resource = $this->getApiUrl().'/repository/files/'.$this->urlEncodeAll($file).'/raw?ref='.$identifier;
36476
36477 try {
36478 $content = $this->getContents($resource);
36479 } catch (TransportException $e) {
36480 if ($e->getCode() !== 404) {
36481 throw $e;
36482 }
36483
36484 return null;
36485 }
36486
36487 return $content;
36488 }
36489
36490
36491
36492
36493 public function getChangeDate($identifier)
36494 {
36495 if ($this->gitDriver) {
36496 return $this->gitDriver->getChangeDate($identifier);
36497 }
36498
36499 if (isset($this->commits[$identifier])) {
36500 return new \DateTime($this->commits[$identifier]['committed_date']);
36501 }
36502
36503 return new \DateTime();
36504 }
36505
36506
36507
36508
36509 public function getRepositoryUrl()
36510 {
36511 return $this->isPrivate ? $this->project['ssh_url_to_repo'] : $this->project['http_url_to_repo'];
36512 }
36513
36514
36515
36516
36517 public function getUrl()
36518 {
36519 if ($this->gitDriver) {
36520 return $this->gitDriver->getUrl();
36521 }
36522
36523 return $this->project['web_url'];
36524 }
36525
36526
36527
36528
36529 public function getDist($identifier)
36530 {
36531 $url = $this->getApiUrl().'/repository/archive.zip?sha='.$identifier;
36532
36533 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
36534 }
36535
36536
36537
36538
36539 public function getSource($identifier)
36540 {
36541 if ($this->gitDriver) {
36542 return $this->gitDriver->getSource($identifier);
36543 }
36544
36545 return array('type' => 'git', 'url' => $this->getRepositoryUrl(), 'reference' => $identifier);
36546 }
36547
36548
36549
36550
36551 public function getRootIdentifier()
36552 {
36553 if ($this->gitDriver) {
36554 return $this->gitDriver->getRootIdentifier();
36555 }
36556
36557 return $this->project['default_branch'];
36558 }
36559
36560
36561
36562
36563 public function getBranches()
36564 {
36565 if ($this->gitDriver) {
36566 return $this->gitDriver->getBranches();
36567 }
36568
36569 if (!$this->branches) {
36570 $this->branches = $this->getReferences('branches');
36571 }
36572
36573 return $this->branches;
36574 }
36575
36576
36577
36578
36579 public function getTags()
36580 {
36581 if ($this->gitDriver) {
36582 return $this->gitDriver->getTags();
36583 }
36584
36585 if (!$this->tags) {
36586 $this->tags = $this->getReferences('tags');
36587 }
36588
36589 return $this->tags;
36590 }
36591
36592
36593
36594
36595 public function getApiUrl()
36596 {
36597 return $this->scheme.'://'.$this->originUrl.'/api/v4/projects/'.$this->urlEncodeAll($this->namespace).'%2F'.$this->urlEncodeAll($this->repository);
36598 }
36599
36600
36601
36602
36603
36604
36605
36606 private function urlEncodeAll($string)
36607 {
36608 $encoded = '';
36609 for ($i = 0; isset($string[$i]); $i++) {
36610 $character = $string[$i];
36611 if (!ctype_alnum($character) && !in_array($character, array('-', '_'), true)) {
36612 $character = '%' . sprintf('%02X', ord($character));
36613 }
36614 $encoded .= $character;
36615 }
36616
36617 return $encoded;
36618 }
36619
36620
36621
36622
36623
36624
36625 protected function getReferences($type)
36626 {
36627 $perPage = 100;
36628 $resource = $this->getApiUrl().'/repository/'.$type.'?per_page='.$perPage;
36629
36630 $references = array();
36631 do {
36632 $data = JsonFile::parseJson($this->getContents($resource), $resource);
36633
36634 foreach ($data as $datum) {
36635 $references[$datum['name']] = $datum['commit']['id'];
36636
36637
36638  
36639  $this->commits[$datum['commit']['id']] = $datum['commit'];
36640 }
36641
36642 if (count($data) >= $perPage) {
36643 $resource = $this->getNextPage();
36644 } else {
36645 $resource = false;
36646 }
36647 } while ($resource);
36648
36649 return $references;
36650 }
36651
36652 protected function fetchProject()
36653 {
36654
36655  $resource = $this->getApiUrl();
36656 $this->project = JsonFile::parseJson($this->getContents($resource, true), $resource);
36657 if (isset($this->project['visibility'])) {
36658 $this->isPrivate = $this->project['visibility'] !== 'public';
36659 } else {
36660
36661  $this->isPrivate = false;
36662 }
36663 }
36664
36665 protected function attemptCloneFallback()
36666 {
36667 try {
36668 if ($this->isPrivate === false) {
36669 $url = $this->generatePublicUrl();
36670 } else {
36671 $url = $this->generateSshUrl();
36672 }
36673
36674
36675  
36676  
36677  $this->setupGitDriver($url);
36678
36679 return;
36680 } catch (\RuntimeException $e) {
36681 $this->gitDriver = null;
36682
36683 $this->io->writeError('<error>Failed to clone the '.$url.' repository, try running in interactive mode so that you can enter your credentials</error>');
36684 throw $e;
36685 }
36686 }
36687
36688
36689
36690
36691
36692
36693 protected function generateSshUrl()
36694 {
36695 return 'git@' . $this->originUrl . ':'.$this->namespace.'/'.$this->repository.'.git';
36696 }
36697
36698 protected function generatePublicUrl()
36699 {
36700 return $this->scheme . '://' . $this->originUrl . '/'.$this->namespace.'/'.$this->repository.'.git';
36701 }
36702
36703 protected function setupGitDriver($url)
36704 {
36705 $this->gitDriver = new GitDriver(
36706 array('url' => $url),
36707 $this->io,
36708 $this->config,
36709 $this->process,
36710 $this->remoteFilesystem
36711 );
36712 $this->gitDriver->initialize();
36713 }
36714
36715
36716
36717
36718 protected function getContents($url, $fetchingRepoData = false)
36719 {
36720 try {
36721 $res = parent::getContents($url);
36722
36723 if ($fetchingRepoData) {
36724 $json = JsonFile::parseJson($res, $url);
36725
36726
36727  if (!isset($json['default_branch'])) {
36728 if (!empty($json['id'])) {
36729 $this->isPrivate = false;
36730 }
36731
36732 throw new TransportException('GitLab API seems to not be authenticated as it did not return a default_branch', 401);
36733 }
36734 }
36735
36736 return $res;
36737 } catch (TransportException $e) {
36738 $gitLabUtil = new GitLab($this->io, $this->config, $this->process, $this->remoteFilesystem);
36739
36740 switch ($e->getCode()) {
36741 case 401:
36742 case 404:
36743
36744  if (!$fetchingRepoData) {
36745 throw $e;
36746 }
36747
36748 if ($gitLabUtil->authorizeOAuth($this->originUrl)) {
36749 return parent::getContents($url);
36750 }
36751
36752 if (!$this->io->isInteractive()) {
36753 return $this->attemptCloneFallback();
36754 }
36755 $this->io->writeError('<warning>Failed to download ' . $this->namespace . '/' . $this->repository . ':' . $e->getMessage() . '</warning>');
36756 $gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, 'Your credentials are required to fetch private repository metadata (<info>'.$this->url.'</info>)');
36757
36758 return parent::getContents($url);
36759
36760 case 403:
36761 if (!$this->io->hasAuthentication($this->originUrl) && $gitLabUtil->authorizeOAuth($this->originUrl)) {
36762 return parent::getContents($url);
36763 }
36764
36765 if (!$this->io->isInteractive() && $fetchingRepoData) {
36766 return $this->attemptCloneFallback();
36767 }
36768
36769 throw $e;
36770
36771 default:
36772 throw $e;
36773 }
36774 }
36775 }
36776
36777
36778
36779
36780
36781
36782
36783 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
36784 {
36785 if (!preg_match(self::URL_REGEX, $url, $match)) {
36786 return false;
36787 }
36788
36789 $scheme = !empty($match['scheme']) ? $match['scheme'] : null;
36790 $guessedDomain = !empty($match['domain']) ? $match['domain'] : $match['domain2'];
36791 $urlParts = explode('/', $match['parts']);
36792
36793 if (false === self::determineOrigin((array) $config->get('gitlab-domains'), $guessedDomain, $urlParts)) {
36794 return false;
36795 }
36796
36797 if ('https' === $scheme && !extension_loaded('openssl')) {
36798 $io->writeError('Skipping GitLab driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
36799
36800 return false;
36801 }
36802
36803 return true;
36804 }
36805
36806 private function getNextPage()
36807 {
36808 $headers = $this->remoteFilesystem->getLastHeaders();
36809 foreach ($headers as $header) {
36810 if (preg_match('{^link:\s*(.+?)\s*$}i', $header, $match)) {
36811 $links = explode(',', $match[1]);
36812 foreach ($links as $link) {
36813 if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) {
36814 return $match[1];
36815 }
36816 }
36817 }
36818 }
36819 }
36820
36821
36822
36823
36824
36825
36826
36827 private static function determineOrigin(array $configuredDomains, $guessedDomain, array &$urlParts)
36828 {
36829 if (in_array($guessedDomain, $configuredDomains)) {
36830 return $guessedDomain;
36831 }
36832
36833 while (null !== ($part = array_shift($urlParts))) {
36834 $guessedDomain .= '/' . $part;
36835
36836 if (in_array($guessedDomain, $configuredDomains)) {
36837 return $guessedDomain;
36838 }
36839 }
36840
36841 return false;
36842 }
36843 }
36844 <?php
36845
36846
36847
36848
36849
36850
36851
36852
36853
36854
36855
36856 namespace Composer\Repository\Vcs;
36857
36858 use Composer\Config;
36859 use Composer\IO\IOInterface;
36860
36861
36862
36863
36864 class HgBitbucketDriver extends BitbucketDriver
36865 {
36866
36867
36868
36869 public function getRootIdentifier()
36870 {
36871 if ($this->fallbackDriver) {
36872 return $this->fallbackDriver->getRootIdentifier();
36873 }
36874
36875 if (null === $this->rootIdentifier) {
36876 if (! $this->getRepoData()) {
36877 return $this->fallbackDriver->getRootIdentifier();
36878 }
36879
36880 if ($this->vcsType !== 'hg') {
36881 throw new \RuntimeException(
36882 $this->url.' does not appear to be a mercurial repository, use '.
36883 $this->cloneHttpsUrl.' if this is a git bitbucket repository'
36884 );
36885 }
36886
36887 $mainBranchData = $this->getMainBranchData();
36888 $this->rootIdentifier = !empty($mainBranchData['name']) ? $mainBranchData['name'] : 'default';
36889 }
36890
36891 return $this->rootIdentifier;
36892 }
36893
36894
36895
36896
36897 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
36898 {
36899 if (!preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+)/?$#', $url)) {
36900 return false;
36901 }
36902
36903 if (!extension_loaded('openssl')) {
36904 $io->writeError('Skipping Bitbucket hg driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
36905
36906 return false;
36907 }
36908
36909 return true;
36910 }
36911
36912
36913
36914
36915 protected function setupFallbackDriver($url)
36916 {
36917 $this->fallbackDriver = new HgDriver(
36918 array('url' => $url),
36919 $this->io,
36920 $this->config,
36921 $this->process,
36922 $this->remoteFilesystem
36923 );
36924 $this->fallbackDriver->initialize();
36925 }
36926
36927
36928
36929
36930 protected function generateSshUrl()
36931 {
36932 return 'ssh://hg@' . $this->originUrl . '/' . $this->owner.'/'.$this->repository;
36933 }
36934 }
36935 <?php
36936
36937
36938
36939
36940
36941
36942
36943
36944
36945
36946
36947 namespace Composer\Repository\Vcs;
36948
36949 use Composer\Config;
36950 use Composer\Util\ProcessExecutor;
36951 use Composer\Util\Filesystem;
36952 use Composer\IO\IOInterface;
36953
36954
36955
36956
36957 class HgDriver extends VcsDriver
36958 {
36959 protected $tags;
36960 protected $branches;
36961 protected $rootIdentifier;
36962 protected $repoDir;
36963 protected $infoCache = array();
36964
36965
36966
36967
36968 public function initialize()
36969 {
36970 if (Filesystem::isLocalPath($this->url)) {
36971 $this->repoDir = $this->url;
36972 } else {
36973 $cacheDir = $this->config->get('cache-vcs-dir');
36974 $this->repoDir = $cacheDir . '/' . preg_replace('{[^a-z0-9]}i', '-', $this->url) . '/';
36975
36976 $fs = new Filesystem();
36977 $fs->ensureDirectoryExists($cacheDir);
36978
36979 if (!is_writable(dirname($this->repoDir))) {
36980 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$cacheDir.'" directory is not writable by the current user.');
36981 }
36982
36983
36984  $this->config->prohibitUrlByConfig($this->url, $this->io);
36985
36986
36987  if (is_dir($this->repoDir) && 0 === $this->process->execute('hg summary', $output, $this->repoDir)) {
36988 if (0 !== $this->process->execute('hg pull', $output, $this->repoDir)) {
36989 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')</error>');
36990 }
36991 } else {
36992
36993  $fs->removeDirectory($this->repoDir);
36994
36995 if (0 !== $this->process->execute(sprintf('hg clone --noupdate %s %s', ProcessExecutor::escape($this->url), ProcessExecutor::escape($this->repoDir)), $output, $cacheDir)) {
36996 $output = $this->process->getErrorOutput();
36997
36998 if (0 !== $this->process->execute('hg --version', $ignoredOutput)) {
36999 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());
37000 }
37001
37002 throw new \RuntimeException('Failed to clone '.$this->url.', could not read packages from it' . "\n\n" .$output);
37003 }
37004 }
37005 }
37006
37007 $this->getTags();
37008 $this->getBranches();
37009 }
37010
37011
37012
37013
37014 public function getRootIdentifier()
37015 {
37016 if (null === $this->rootIdentifier) {
37017 $this->process->execute(sprintf('hg tip --template "{node}"'), $output, $this->repoDir);
37018 $output = $this->process->splitLines($output);
37019 $this->rootIdentifier = $output[0];
37020 }
37021
37022 return $this->rootIdentifier;
37023 }
37024
37025
37026
37027
37028 public function getUrl()
37029 {
37030 return $this->url;
37031 }
37032
37033
37034
37035
37036 public function getSource($identifier)
37037 {
37038 return array('type' => 'hg', 'url' => $this->getUrl(), 'reference' => $identifier);
37039 }
37040
37041
37042
37043
37044 public function getDist($identifier)
37045 {
37046 return null;
37047 }
37048
37049
37050
37051
37052 public function getFileContent($file, $identifier)
37053 {
37054 $resource = sprintf('hg cat -r %s %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
37055 $this->process->execute($resource, $content, $this->repoDir);
37056
37057 if (!trim($content)) {
37058 return;
37059 }
37060
37061 return $content;
37062 }
37063
37064
37065
37066
37067 public function getChangeDate($identifier)
37068 {
37069 $this->process->execute(
37070 sprintf(
37071 'hg log --template "{date|rfc3339date}" -r %s',
37072 ProcessExecutor::escape($identifier)
37073 ),
37074 $output,
37075 $this->repoDir
37076 );
37077
37078 return new \DateTime(trim($output), new \DateTimeZone('UTC'));
37079 }
37080
37081
37082
37083
37084 public function getTags()
37085 {
37086 if (null === $this->tags) {
37087 $tags = array();
37088
37089 $this->process->execute('hg tags', $output, $this->repoDir);
37090 foreach ($this->process->splitLines($output) as $tag) {
37091 if ($tag && preg_match('(^([^\s]+)\s+\d+:(.*)$)', $tag, $match)) {
37092 $tags[$match[1]] = $match[2];
37093 }
37094 }
37095 unset($tags['tip']);
37096
37097 $this->tags = $tags;
37098 }
37099
37100 return $this->tags;
37101 }
37102
37103
37104
37105
37106 public function getBranches()
37107 {
37108 if (null === $this->branches) {
37109 $branches = array();
37110 $bookmarks = array();
37111
37112 $this->process->execute('hg branches', $output, $this->repoDir);
37113 foreach ($this->process->splitLines($output) as $branch) {
37114 if ($branch && preg_match('(^([^\s]+)\s+\d+:([a-f0-9]+))', $branch, $match)) {
37115 $branches[$match[1]] = $match[2];
37116 }
37117 }
37118
37119 $this->process->execute('hg bookmarks', $output, $this->repoDir);
37120 foreach ($this->process->splitLines($output) as $branch) {
37121 if ($branch && preg_match('(^(?:[\s*]*)([^\s]+)\s+\d+:(.*)$)', $branch, $match)) {
37122 $bookmarks[$match[1]] = $match[2];
37123 }
37124 }
37125
37126
37127  $this->branches = array_merge($bookmarks, $branches);
37128 }
37129
37130 return $this->branches;
37131 }
37132
37133
37134
37135
37136 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37137 {
37138 if (preg_match('#(^(?:https?|ssh)://(?:[^@]+@)?bitbucket.org|https://(?:.*?)\.kilnhg.com)#i', $url)) {
37139 return true;
37140 }
37141
37142
37143  if (Filesystem::isLocalPath($url)) {
37144 $url = Filesystem::getPlatformPath($url);
37145 if (!is_dir($url)) {
37146 return false;
37147 }
37148
37149 $process = new ProcessExecutor();
37150
37151  if ($process->execute('hg summary', $output, $url) === 0) {
37152 return true;
37153 }
37154 }
37155
37156 if (!$deep) {
37157 return false;
37158 }
37159
37160 $processExecutor = new ProcessExecutor();
37161 $exit = $processExecutor->execute(sprintf('hg identify %s', ProcessExecutor::escape($url)), $ignored);
37162
37163 return $exit === 0;
37164 }
37165 }
37166 <?php
37167
37168
37169
37170
37171
37172
37173
37174
37175
37176
37177
37178 namespace Composer\Repository\Vcs;
37179
37180 use Composer\Config;
37181 use Composer\IO\IOInterface;
37182 use Composer\Util\ProcessExecutor;
37183 use Composer\Util\Perforce;
37184
37185
37186
37187
37188 class PerforceDriver extends VcsDriver
37189 {
37190 protected $depot;
37191 protected $branch;
37192
37193 protected $perforce;
37194
37195
37196
37197
37198 public function initialize()
37199 {
37200 $this->depot = $this->repoConfig['depot'];
37201 $this->branch = '';
37202 if (!empty($this->repoConfig['branch'])) {
37203 $this->branch = $this->repoConfig['branch'];
37204 }
37205
37206 $this->initPerforce($this->repoConfig);
37207 $this->perforce->p4Login();
37208 $this->perforce->checkStream();
37209
37210 $this->perforce->writeP4ClientSpec();
37211 $this->perforce->connectClient();
37212
37213 return true;
37214 }
37215
37216 private function initPerforce($repoConfig)
37217 {
37218 if (!empty($this->perforce)) {
37219 return;
37220 }
37221
37222 $repoDir = $this->config->get('cache-vcs-dir') . '/' . $this->depot;
37223 $this->perforce = Perforce::create($repoConfig, $this->getUrl(), $repoDir, $this->process, $this->io);
37224 }
37225
37226
37227
37228
37229 public function getFileContent($file, $identifier)
37230 {
37231 return $this->perforce->getFileContent($file, $identifier);
37232 }
37233
37234
37235
37236
37237 public function getChangeDate($identifier)
37238 {
37239 return null;
37240 }
37241
37242
37243
37244
37245 public function getRootIdentifier()
37246 {
37247 return $this->branch;
37248 }
37249
37250
37251
37252
37253 public function getBranches()
37254 {
37255 $branches = $this->perforce->getBranches();
37256
37257 return $branches;
37258 }
37259
37260
37261
37262
37263 public function getTags()
37264 {
37265 $tags = $this->perforce->getTags();
37266
37267 return $tags;
37268 }
37269
37270
37271
37272
37273 public function getDist($identifier)
37274 {
37275 return null;
37276 }
37277
37278
37279
37280
37281 public function getSource($identifier)
37282 {
37283 $source = array(
37284 'type' => 'perforce',
37285 'url' => $this->repoConfig['url'],
37286 'reference' => $identifier,
37287 'p4user' => $this->perforce->getUser(),
37288 );
37289
37290 return $source;
37291 }
37292
37293
37294
37295
37296 public function getUrl()
37297 {
37298 return $this->url;
37299 }
37300
37301
37302
37303
37304 public function hasComposerFile($identifier)
37305 {
37306 $composerInfo = $this->perforce->getComposerInformation('//' . $this->depot . '/' . $identifier);
37307 $composerInfoIdentifier = $identifier;
37308
37309 return !empty($composerInfo);
37310 }
37311
37312
37313
37314
37315 public function getContents($url)
37316 {
37317 return false;
37318 }
37319
37320
37321
37322
37323 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37324 {
37325 if ($deep || preg_match('#\b(perforce|p4)\b#i', $url)) {
37326 return Perforce::checkServerExists($url, new ProcessExecutor($io));
37327 }
37328
37329 return false;
37330 }
37331
37332
37333
37334
37335 public function cleanup()
37336 {
37337 $this->perforce->cleanupClientSpec();
37338 $this->perforce = null;
37339 }
37340
37341 public function getDepot()
37342 {
37343 return $this->depot;
37344 }
37345
37346 public function getBranch()
37347 {
37348 return $this->branch;
37349 }
37350 }
37351 <?php
37352
37353
37354
37355
37356
37357
37358
37359
37360
37361
37362
37363 namespace Composer\Repository\Vcs;
37364
37365 use Composer\Cache;
37366 use Composer\Config;
37367 use Composer\Json\JsonFile;
37368 use Composer\Util\ProcessExecutor;
37369 use Composer\Util\Filesystem;
37370 use Composer\Util\Svn as SvnUtil;
37371 use Composer\IO\IOInterface;
37372 use Composer\Downloader\TransportException;
37373
37374
37375
37376
37377
37378 class SvnDriver extends VcsDriver
37379 {
37380
37381
37382
37383 protected $cache;
37384 protected $baseUrl;
37385 protected $tags;
37386 protected $branches;
37387 protected $rootIdentifier;
37388 protected $infoCache = array();
37389
37390 protected $trunkPath = 'trunk';
37391 protected $branchesPath = 'branches';
37392 protected $tagsPath = 'tags';
37393 protected $packagePath = '';
37394 protected $cacheCredentials = true;
37395
37396
37397
37398
37399 private $util;
37400
37401
37402
37403
37404 public function initialize()
37405 {
37406 $this->url = $this->baseUrl = rtrim(self::normalizeUrl($this->url), '/');
37407
37408 SvnUtil::cleanEnv();
37409
37410 if (isset($this->repoConfig['trunk-path'])) {
37411 $this->trunkPath = $this->repoConfig['trunk-path'];
37412 }
37413 if (isset($this->repoConfig['branches-path'])) {
37414 $this->branchesPath = $this->repoConfig['branches-path'];
37415 }
37416 if (isset($this->repoConfig['tags-path'])) {
37417 $this->tagsPath = $this->repoConfig['tags-path'];
37418 }
37419 if (array_key_exists('svn-cache-credentials', $this->repoConfig)) {
37420 $this->cacheCredentials = (bool) $this->repoConfig['svn-cache-credentials'];
37421 }
37422 if (isset($this->repoConfig['package-path'])) {
37423 $this->packagePath = '/' . trim($this->repoConfig['package-path'], '/');
37424 }
37425
37426 if (false !== ($pos = strrpos($this->url, '/' . $this->trunkPath))) {
37427 $this->baseUrl = substr($this->url, 0, $pos);
37428 }
37429
37430 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->baseUrl));
37431
37432 $this->getBranches();
37433 $this->getTags();
37434 }
37435
37436
37437
37438
37439 public function getRootIdentifier()
37440 {
37441 return $this->rootIdentifier ?: $this->trunkPath;
37442 }
37443
37444
37445
37446
37447 public function getUrl()
37448 {
37449 return $this->url;
37450 }
37451
37452
37453
37454
37455 public function getSource($identifier)
37456 {
37457 return array('type' => 'svn', 'url' => $this->baseUrl, 'reference' => $identifier);
37458 }
37459
37460
37461
37462
37463 public function getDist($identifier)
37464 {
37465 return null;
37466 }
37467
37468
37469
37470
37471 public function getComposerInformation($identifier)
37472 {
37473 if (!isset($this->infoCache[$identifier])) {
37474 if ($res = $this->cache->read($identifier.'.json')) {
37475 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
37476 }
37477
37478 $composer = $this->getBaseComposerInformation($identifier);
37479
37480 $this->cache->write($identifier.'.json', json_encode($composer));
37481
37482 $this->infoCache[$identifier] = $composer;
37483 }
37484
37485 return $this->infoCache[$identifier];
37486 }
37487
37488
37489
37490
37491
37492 public function getFileContent($file, $identifier)
37493 {
37494 $identifier = '/' . trim($identifier, '/') . '/';
37495
37496 preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match);
37497 if (!empty($match[2])) {
37498 $path = $match[1];
37499 $rev = $match[2];
37500 } else {
37501 $path = $identifier;
37502 $rev = '';
37503 }
37504
37505 try {
37506 $resource = $path.$file;
37507 $output = $this->execute('svn cat', $this->baseUrl . $resource . $rev);
37508 if (!trim($output)) {
37509 return null;
37510 }
37511 } catch (\RuntimeException $e) {
37512 throw new TransportException($e->getMessage());
37513 }
37514
37515 return $output;
37516 }
37517
37518
37519
37520
37521 public function getChangeDate($identifier)
37522 {
37523 $identifier = '/' . trim($identifier, '/') . '/';
37524
37525 preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match);
37526 if (!empty($match[2])) {
37527 $path = $match[1];
37528 $rev = $match[2];
37529 } else {
37530 $path = $identifier;
37531 $rev = '';
37532 }
37533
37534 $output = $this->execute('svn info', $this->baseUrl . $path . $rev);
37535 foreach ($this->process->splitLines($output) as $line) {
37536 if ($line && preg_match('{^Last Changed Date: ([^(]+)}', $line, $match)) {
37537 return new \DateTime($match[1], new \DateTimeZone('UTC'));
37538 }
37539 }
37540
37541 return null;
37542 }
37543
37544
37545
37546
37547 public function getTags()
37548 {
37549 if (null === $this->tags) {
37550 $this->tags = array();
37551
37552 if ($this->tagsPath !== false) {
37553 $output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->tagsPath);
37554 if ($output) {
37555 foreach ($this->process->splitLines($output) as $line) {
37556 $line = trim($line);
37557 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
37558 if (isset($match[1]) && isset($match[2]) && $match[2] !== './') {
37559 $this->tags[rtrim($match[2], '/')] = $this->buildIdentifier(
37560 '/' . $this->tagsPath . '/' . $match[2],
37561 $match[1]
37562 );
37563 }
37564 }
37565 }
37566 }
37567 }
37568 }
37569
37570 return $this->tags;
37571 }
37572
37573
37574
37575
37576 public function getBranches()
37577 {
37578 if (null === $this->branches) {
37579 $this->branches = array();
37580
37581 if (false === $this->trunkPath) {
37582 $trunkParent = $this->baseUrl . '/';
37583 } else {
37584 $trunkParent = $this->baseUrl . '/' . $this->trunkPath;
37585 }
37586
37587 $output = $this->execute('svn ls --verbose', $trunkParent);
37588 if ($output) {
37589 foreach ($this->process->splitLines($output) as $line) {
37590 $line = trim($line);
37591 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
37592 if (isset($match[1]) && isset($match[2]) && $match[2] === './') {
37593 $this->branches['trunk'] = $this->buildIdentifier(
37594 '/' . $this->trunkPath,
37595 $match[1]
37596 );
37597 $this->rootIdentifier = $this->branches['trunk'];
37598 break;
37599 }
37600 }
37601 }
37602 }
37603 unset($output);
37604
37605 if ($this->branchesPath !== false) {
37606 $output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->branchesPath);
37607 if ($output) {
37608 foreach ($this->process->splitLines(trim($output)) as $line) {
37609 $line = trim($line);
37610 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
37611 if (isset($match[1]) && isset($match[2]) && $match[2] !== './') {
37612 $this->branches[rtrim($match[2], '/')] = $this->buildIdentifier(
37613 '/' . $this->branchesPath . '/' . $match[2],
37614 $match[1]
37615 );
37616 }
37617 }
37618 }
37619 }
37620 }
37621 }
37622
37623 return $this->branches;
37624 }
37625
37626
37627
37628
37629 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37630 {
37631 $url = self::normalizeUrl($url);
37632 if (preg_match('#(^svn://|^svn\+ssh://|svn\.)#i', $url)) {
37633 return true;
37634 }
37635
37636
37637  if (!$deep && !Filesystem::isLocalPath($url)) {
37638 return false;
37639 }
37640
37641 $processExecutor = new ProcessExecutor();
37642
37643 $exit = $processExecutor->execute(
37644 "svn info --non-interactive {$url}",
37645 $ignoredOutput
37646 );
37647
37648 if ($exit === 0) {
37649
37650  return true;
37651 }
37652
37653
37654  if (false !== stripos($processExecutor->getErrorOutput(), 'authorization failed:')) {
37655
37656  
37657  return true;
37658 }
37659
37660
37661  if (false !== stripos($processExecutor->getErrorOutput(), 'Authentication failed')) {
37662
37663  
37664  return true;
37665 }
37666
37667 return false;
37668 }
37669
37670
37671
37672
37673
37674
37675
37676
37677 protected static function normalizeUrl($url)
37678 {
37679 $fs = new Filesystem();
37680 if ($fs->isAbsolutePath($url)) {
37681 return 'file://' . strtr($url, '\\', '/');
37682 }
37683
37684 return $url;
37685 }
37686
37687
37688
37689
37690
37691
37692
37693
37694
37695
37696 protected function execute($command, $url)
37697 {
37698 if (null === $this->util) {
37699 $this->util = new SvnUtil($this->baseUrl, $this->io, $this->config, $this->process);
37700 $this->util->setCacheCredentials($this->cacheCredentials);
37701 }
37702
37703 try {
37704 return $this->util->execute($command, $url);
37705 } catch (\RuntimeException $e) {
37706 if (0 !== $this->process->execute('svn --version', $ignoredOutput)) {
37707 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());
37708 }
37709
37710 throw new \RuntimeException(
37711 'Repository '.$this->url.' could not be processed, '.$e->getMessage()
37712 );
37713 }
37714 }
37715
37716
37717
37718
37719
37720
37721
37722
37723
37724 protected function buildIdentifier($baseDir, $revision)
37725 {
37726 return rtrim($baseDir, '/') . $this->packagePath . '/@' . $revision;
37727 }
37728 }
37729 <?php
37730
37731
37732
37733
37734
37735
37736
37737
37738
37739
37740
37741 namespace Composer\Repository\Vcs;
37742
37743 use Composer\Cache;
37744 use Composer\Downloader\TransportException;
37745 use Composer\Config;
37746 use Composer\Factory;
37747 use Composer\IO\IOInterface;
37748 use Composer\Json\JsonFile;
37749 use Composer\Util\ProcessExecutor;
37750 use Composer\Util\RemoteFilesystem;
37751 use Composer\Util\Filesystem;
37752
37753
37754
37755
37756
37757
37758 abstract class VcsDriver implements VcsDriverInterface
37759 {
37760
37761 protected $url;
37762
37763 protected $originUrl;
37764
37765 protected $repoConfig;
37766
37767 protected $io;
37768
37769 protected $config;
37770
37771 protected $process;
37772
37773 protected $remoteFilesystem;
37774
37775 protected $infoCache = array();
37776
37777 protected $cache;
37778
37779
37780
37781
37782
37783
37784
37785
37786
37787
37788 final public function __construct(array $repoConfig, IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
37789 {
37790 if (Filesystem::isLocalPath($repoConfig['url'])) {
37791 $repoConfig['url'] = Filesystem::getPlatformPath($repoConfig['url']);
37792 }
37793
37794 $this->url = $repoConfig['url'];
37795 $this->originUrl = $repoConfig['url'];
37796 $this->repoConfig = $repoConfig;
37797 $this->io = $io;
37798 $this->config = $config;
37799 $this->process = $process ?: new ProcessExecutor($io);
37800 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
37801 }
37802
37803
37804
37805
37806
37807
37808
37809 protected function shouldCache($identifier)
37810 {
37811 return $this->cache && preg_match('{[a-f0-9]{40}}i', $identifier);
37812 }
37813
37814
37815
37816
37817 public function getComposerInformation($identifier)
37818 {
37819 if (!isset($this->infoCache[$identifier])) {
37820 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
37821 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
37822 }
37823
37824 $composer = $this->getBaseComposerInformation($identifier);
37825
37826 if ($this->shouldCache($identifier)) {
37827 $this->cache->write($identifier, json_encode($composer));
37828 }
37829
37830 $this->infoCache[$identifier] = $composer;
37831 }
37832
37833 return $this->infoCache[$identifier];
37834 }
37835
37836 protected function getBaseComposerInformation($identifier)
37837 {
37838 $composerFileContent = $this->getFileContent('composer.json', $identifier);
37839
37840 if (!$composerFileContent) {
37841 return null;
37842 }
37843
37844 $composer = JsonFile::parseJson($composerFileContent, $identifier . ':composer.json');
37845
37846 if (empty($composer['time']) && $changeDate = $this->getChangeDate($identifier)) {
37847 $composer['time'] = $changeDate->format(DATE_RFC3339);
37848 }
37849
37850 return $composer;
37851 }
37852
37853
37854
37855
37856 public function hasComposerFile($identifier)
37857 {
37858 try {
37859 return (bool) $this->getComposerInformation($identifier);
37860 } catch (TransportException $e) {
37861 }
37862
37863 return false;
37864 }
37865
37866
37867
37868
37869
37870
37871
37872
37873 protected function getScheme()
37874 {
37875 if (extension_loaded('openssl')) {
37876 return 'https';
37877 }
37878
37879 return 'http';
37880 }
37881
37882
37883
37884
37885
37886
37887
37888
37889 protected function getContents($url)
37890 {
37891 $options = isset($this->repoConfig['options']) ? $this->repoConfig['options'] : array();
37892
37893 return $this->remoteFilesystem->getContents($this->originUrl, $url, false, $options);
37894 }
37895
37896
37897
37898
37899 public function cleanup()
37900 {
37901 return;
37902 }
37903 }
37904 <?php
37905
37906
37907
37908
37909
37910
37911
37912
37913
37914
37915
37916 namespace Composer\Repository\Vcs;
37917
37918 use Composer\Config;
37919 use Composer\IO\IOInterface;
37920
37921
37922
37923
37924 interface VcsDriverInterface
37925 {
37926
37927
37928
37929 public function initialize();
37930
37931
37932
37933
37934
37935
37936
37937 public function getComposerInformation($identifier);
37938
37939
37940
37941
37942
37943
37944
37945
37946 public function getFileContent($file, $identifier);
37947
37948
37949
37950
37951
37952
37953
37954 public function getChangeDate($identifier);
37955
37956
37957
37958
37959
37960
37961 public function getRootIdentifier();
37962
37963
37964
37965
37966
37967
37968 public function getBranches();
37969
37970
37971
37972
37973
37974
37975 public function getTags();
37976
37977
37978
37979
37980
37981 public function getDist($identifier);
37982
37983
37984
37985
37986
37987 public function getSource($identifier);
37988
37989
37990
37991
37992
37993
37994 public function getUrl();
37995
37996
37997
37998
37999
38000
38001
38002
38003 public function hasComposerFile($identifier);
38004
38005
38006
38007
38008 public function cleanup();
38009
38010
38011
38012
38013
38014
38015
38016
38017
38018
38019 public static function supports(IOInterface $io, Config $config, $url, $deep = false);
38020 }
38021 <?php
38022
38023
38024
38025
38026
38027
38028
38029
38030
38031
38032
38033 namespace Composer\Repository;
38034
38035 use Composer\Downloader\TransportException;
38036 use Composer\Repository\Vcs\VcsDriverInterface;
38037 use Composer\Package\Version\VersionParser;
38038 use Composer\Package\Loader\ArrayLoader;
38039 use Composer\Package\Loader\ValidatingArrayLoader;
38040 use Composer\Package\Loader\InvalidPackageException;
38041 use Composer\Package\Loader\LoaderInterface;
38042 use Composer\EventDispatcher\EventDispatcher;
38043 use Composer\IO\IOInterface;
38044 use Composer\Config;
38045
38046
38047
38048
38049 class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInterface
38050 {
38051 protected $url;
38052 protected $packageName;
38053 protected $verbose;
38054 protected $io;
38055 protected $config;
38056 protected $versionParser;
38057 protected $type;
38058 protected $loader;
38059 protected $repoConfig;
38060 protected $branchErrorOccurred = false;
38061 private $drivers;
38062
38063 private $driver;
38064
38065 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, array $drivers = null)
38066 {
38067 parent::__construct();
38068 $this->drivers = $drivers ?: array(
38069 'github' => 'Composer\Repository\Vcs\GitHubDriver',
38070 'gitlab' => 'Composer\Repository\Vcs\GitLabDriver',
38071 'git-bitbucket' => 'Composer\Repository\Vcs\GitBitbucketDriver',
38072 'git' => 'Composer\Repository\Vcs\GitDriver',
38073 'hg-bitbucket' => 'Composer\Repository\Vcs\HgBitbucketDriver',
38074 'hg' => 'Composer\Repository\Vcs\HgDriver',
38075 'perforce' => 'Composer\Repository\Vcs\PerforceDriver',
38076 'fossil' => 'Composer\Repository\Vcs\FossilDriver',
38077
38078  'svn' => 'Composer\Repository\Vcs\SvnDriver',
38079 );
38080
38081 $this->url = $repoConfig['url'];
38082 $this->io = $io;
38083 $this->type = isset($repoConfig['type']) ? $repoConfig['type'] : 'vcs';
38084 $this->verbose = $io->isVeryVerbose();
38085 $this->config = $config;
38086 $this->repoConfig = $repoConfig;
38087 }
38088
38089 public function getRepoConfig()
38090 {
38091 return $this->repoConfig;
38092 }
38093
38094 public function setLoader(LoaderInterface $loader)
38095 {
38096 $this->loader = $loader;
38097 }
38098
38099 public function getDriver()
38100 {
38101 if ($this->driver) {
38102 return $this->driver;
38103 }
38104
38105 if (isset($this->drivers[$this->type])) {
38106 $class = $this->drivers[$this->type];
38107 $this->driver = new $class($this->repoConfig, $this->io, $this->config);
38108 $this->driver->initialize();
38109
38110 return $this->driver;
38111 }
38112
38113 foreach ($this->drivers as $driver) {
38114 if ($driver::supports($this->io, $this->config, $this->url)) {
38115 $this->driver = new $driver($this->repoConfig, $this->io, $this->config);
38116 $this->driver->initialize();
38117
38118 return $this->driver;
38119 }
38120 }
38121
38122 foreach ($this->drivers as $driver) {
38123 if ($driver::supports($this->io, $this->config, $this->url, true)) {
38124 $this->driver = new $driver($this->repoConfig, $this->io, $this->config);
38125 $this->driver->initialize();
38126
38127 return $this->driver;
38128 }
38129 }
38130 }
38131
38132 public function hadInvalidBranches()
38133 {
38134 return $this->branchErrorOccurred;
38135 }
38136
38137 protected function initialize()
38138 {
38139 parent::initialize();
38140
38141 $verbose = $this->verbose;
38142
38143 $driver = $this->getDriver();
38144 if (!$driver) {
38145 throw new \InvalidArgumentException('No driver found to handle VCS repository '.$this->url);
38146 }
38147
38148 $this->versionParser = new VersionParser;
38149 if (!$this->loader) {
38150 $this->loader = new ArrayLoader($this->versionParser);
38151 }
38152
38153 try {
38154 if ($driver->hasComposerFile($driver->getRootIdentifier())) {
38155 $data = $driver->getComposerInformation($driver->getRootIdentifier());
38156 $this->packageName = !empty($data['name']) ? $data['name'] : null;
38157 }
38158 } catch (\Exception $e) {
38159 if ($verbose) {
38160 $this->io->writeError('<error>Skipped parsing '.$driver->getRootIdentifier().', '.$e->getMessage().'</error>');
38161 }
38162 }
38163
38164 foreach ($driver->getTags() as $tag => $identifier) {
38165 $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $tag . '</comment>)';
38166 if ($verbose) {
38167 $this->io->writeError($msg);
38168 } else {
38169 $this->io->overwriteError($msg, false);
38170 }
38171
38172
38173  $tag = str_replace('release-', '', $tag);
38174
38175 if (!$parsedTag = $this->validateTag($tag)) {
38176 if ($verbose) {
38177 $this->io->writeError('<warning>Skipped tag '.$tag.', invalid tag name</warning>');
38178 }
38179 continue;
38180 }
38181
38182 try {
38183 if (!$data = $driver->getComposerInformation($identifier)) {
38184 if ($verbose) {
38185 $this->io->writeError('<warning>Skipped tag '.$tag.', no composer file</warning>');
38186 }
38187 continue;
38188 }
38189
38190
38191  if (isset($data['version'])) {
38192 $data['version_normalized'] = $this->versionParser->normalize($data['version']);
38193 } else {
38194
38195  $data['version'] = $tag;
38196 $data['version_normalized'] = $parsedTag;
38197 }
38198
38199
38200  $data['version'] = preg_replace('{[.-]?dev$}i', '', $data['version']);
38201 $data['version_normalized'] = preg_replace('{(^dev-|[.-]?dev$)}i', '', $data['version_normalized']);
38202
38203
38204  if ($data['version_normalized'] !== $parsedTag) {
38205 if ($verbose) {
38206 $this->io->writeError('<warning>Skipped tag '.$tag.', tag ('.$parsedTag.') does not match version ('.$data['version_normalized'].') in composer.json</warning>');
38207 }
38208 continue;
38209 }
38210
38211 if ($verbose) {
38212 $this->io->writeError('Importing tag '.$tag.' ('.$data['version_normalized'].')');
38213 }
38214
38215 $this->addPackage($this->loader->load($this->preProcess($driver, $data, $identifier)));
38216 } catch (\Exception $e) {
38217 if ($verbose) {
38218 $this->io->writeError('<warning>Skipped tag '.$tag.', '.($e instanceof TransportException ? 'no composer file was found' : $e->getMessage()).'</warning>');
38219 }
38220 continue;
38221 }
38222 }
38223
38224 if (!$verbose) {
38225 $this->io->overwriteError('', false);
38226 }
38227
38228 foreach ($driver->getBranches() as $branch => $identifier) {
38229 $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $branch . '</comment>)';
38230 if ($verbose) {
38231 $this->io->writeError($msg);
38232 } else {
38233 $this->io->overwriteError($msg, false);
38234 }
38235
38236 if (!$parsedBranch = $this->validateBranch($branch)) {
38237 if ($verbose) {
38238 $this->io->writeError('<warning>Skipped branch '.$branch.', invalid name</warning>');
38239 }
38240 continue;
38241 }
38242
38243 try {
38244 if (!$data = $driver->getComposerInformation($identifier)) {
38245 if ($verbose) {
38246 $this->io->writeError('<warning>Skipped branch '.$branch.', no composer file</warning>');
38247 }
38248 continue;
38249 }
38250
38251
38252  $data['version'] = $branch;
38253 $data['version_normalized'] = $parsedBranch;
38254
38255
38256  if ('dev-' === substr($parsedBranch, 0, 4) || '9999999-dev' === $parsedBranch) {
38257 $data['version'] = 'dev-' . $data['version'];
38258 } else {
38259 $prefix = substr($branch, 0, 1) === 'v' ? 'v' : '';
38260 $data['version'] = $prefix . preg_replace('{(\.9{7})+}', '.x', $parsedBranch);
38261 }
38262
38263 if ($verbose) {
38264 $this->io->writeError('Importing branch '.$branch.' ('.$data['version'].')');
38265 }
38266
38267 $packageData = $this->preProcess($driver, $data, $identifier);
38268 $package = $this->loader->load($packageData);
38269 if ($this->loader instanceof ValidatingArrayLoader && $this->loader->getWarnings()) {
38270 throw new InvalidPackageException($this->loader->getErrors(), $this->loader->getWarnings(), $packageData);
38271 }
38272 $this->addPackage($package);
38273 } catch (TransportException $e) {
38274 if ($verbose) {
38275 $this->io->writeError('<warning>Skipped branch '.$branch.', no composer file was found</warning>');
38276 }
38277 continue;
38278 } catch (\Exception $e) {
38279 if (!$verbose) {
38280 $this->io->writeError('');
38281 }
38282 $this->branchErrorOccurred = true;
38283 $this->io->writeError('<error>Skipped branch '.$branch.', '.$e->getMessage().'</error>');
38284 $this->io->writeError('');
38285 continue;
38286 }
38287 }
38288 $driver->cleanup();
38289
38290 if (!$verbose) {
38291 $this->io->overwriteError('', false);
38292 }
38293
38294 if (!$this->getPackages()) {
38295 throw new InvalidRepositoryException('No valid composer.json was found in any branch or tag of '.$this->url.', could not load a package from it.');
38296 }
38297 }
38298
38299 protected function preProcess(VcsDriverInterface $driver, array $data, $identifier)
38300 {
38301
38302  $data['name'] = $this->packageName ?: $data['name'];
38303
38304 if (!isset($data['dist'])) {
38305 $data['dist'] = $driver->getDist($identifier);
38306 }
38307 if (!isset($data['source'])) {
38308 $data['source'] = $driver->getSource($identifier);
38309 }
38310
38311 return $data;
38312 }
38313
38314 private function validateBranch($branch)
38315 {
38316 try {
38317 return $this->versionParser->normalizeBranch($branch);
38318 } catch (\Exception $e) {
38319 }
38320
38321 return false;
38322 }
38323
38324 private function validateTag($version)
38325 {
38326 try {
38327 return $this->versionParser->normalize($version);
38328 } catch (\Exception $e) {
38329 }
38330
38331 return false;
38332 }
38333 }
38334 <?php
38335
38336
38337
38338
38339
38340
38341
38342
38343
38344
38345
38346 namespace Composer\Repository;
38347
38348 use Composer\Package\AliasPackage;
38349
38350
38351
38352
38353
38354
38355 class WritableArrayRepository extends ArrayRepository implements WritableRepositoryInterface
38356 {
38357
38358
38359
38360 public function write()
38361 {
38362 }
38363
38364
38365
38366
38367 public function reload()
38368 {
38369 }
38370
38371
38372
38373
38374 public function getCanonicalPackages()
38375 {
38376 $packages = $this->getPackages();
38377
38378
38379  $packagesByName = array();
38380 foreach ($packages as $package) {
38381 if (!isset($packagesByName[$package->getName()]) || $packagesByName[$package->getName()] instanceof AliasPackage) {
38382 $packagesByName[$package->getName()] = $package;
38383 }
38384 }
38385
38386 $canonicalPackages = array();
38387
38388
38389  foreach ($packagesByName as $package) {
38390 while ($package instanceof AliasPackage) {
38391 $package = $package->getAliasOf();
38392 }
38393
38394 $canonicalPackages[] = $package;
38395 }
38396
38397 return $canonicalPackages;
38398 }
38399 }
38400 <?php
38401
38402
38403
38404
38405
38406
38407
38408
38409
38410
38411
38412 namespace Composer\Repository;
38413
38414 use Composer\Package\PackageInterface;
38415
38416
38417
38418
38419
38420
38421 interface WritableRepositoryInterface extends RepositoryInterface
38422 {
38423
38424
38425
38426 public function write();
38427
38428
38429
38430
38431
38432
38433 public function addPackage(PackageInterface $package);
38434
38435
38436
38437
38438
38439
38440 public function removePackage(PackageInterface $package);
38441
38442
38443
38444
38445
38446
38447 public function getCanonicalPackages();
38448
38449
38450
38451
38452 public function reload();
38453 }
38454 <?php
38455
38456
38457
38458
38459
38460
38461
38462
38463
38464
38465
38466 namespace Composer\Script;
38467
38468
38469
38470
38471
38472
38473 class CommandEvent extends Event
38474 {
38475 }
38476 <?php
38477
38478
38479
38480
38481
38482
38483
38484
38485
38486
38487
38488 namespace Composer\Script;
38489
38490 use Composer\Composer;
38491 use Composer\IO\IOInterface;
38492 use Composer\EventDispatcher\Event as BaseEvent;
38493
38494
38495
38496
38497
38498
38499
38500 class Event extends BaseEvent
38501 {
38502
38503
38504
38505 private $composer;
38506
38507
38508
38509
38510 private $io;
38511
38512
38513
38514
38515 private $devMode;
38516
38517
38518
38519
38520
38521
38522
38523
38524
38525
38526
38527 public function __construct($name, Composer $composer, IOInterface $io, $devMode = false, array $args = array(), array $flags = array())
38528 {
38529 parent::__construct($name, $args, $flags);
38530 $this->composer = $composer;
38531 $this->io = $io;
38532 $this->devMode = $devMode;
38533 }
38534
38535
38536
38537
38538
38539
38540 public function getComposer()
38541 {
38542 return $this->composer;
38543 }
38544
38545
38546
38547
38548
38549
38550 public function getIO()
38551 {
38552 return $this->io;
38553 }
38554
38555
38556
38557
38558
38559
38560 public function isDevMode()
38561 {
38562 return $this->devMode;
38563 }
38564 }
38565 <?php
38566
38567
38568
38569
38570
38571
38572
38573
38574
38575
38576
38577 namespace Composer\Script;
38578
38579 use Composer\Installer\PackageEvent as BasePackageEvent;
38580
38581
38582
38583
38584
38585
38586 class PackageEvent extends BasePackageEvent
38587 {
38588 }
38589 <?php
38590
38591
38592
38593
38594
38595
38596
38597
38598
38599
38600
38601 namespace Composer\Script;
38602
38603
38604
38605
38606
38607
38608
38609 class ScriptEvents
38610 {
38611
38612
38613
38614
38615
38616
38617
38618 const PRE_INSTALL_CMD = 'pre-install-cmd';
38619
38620
38621
38622
38623
38624
38625
38626
38627 const POST_INSTALL_CMD = 'post-install-cmd';
38628
38629
38630
38631
38632
38633
38634
38635
38636 const PRE_UPDATE_CMD = 'pre-update-cmd';
38637
38638
38639
38640
38641
38642
38643
38644
38645 const POST_UPDATE_CMD = 'post-update-cmd';
38646
38647
38648
38649
38650
38651
38652
38653
38654 const PRE_STATUS_CMD = 'pre-status-cmd';
38655
38656
38657
38658
38659
38660
38661
38662
38663 const POST_STATUS_CMD = 'post-status-cmd';
38664
38665
38666
38667
38668
38669
38670
38671
38672 const PRE_AUTOLOAD_DUMP = 'pre-autoload-dump';
38673
38674
38675
38676
38677
38678
38679
38680
38681 const POST_AUTOLOAD_DUMP = 'post-autoload-dump';
38682
38683
38684
38685
38686
38687
38688
38689
38690 const POST_ROOT_PACKAGE_INSTALL = 'post-root-package-install';
38691
38692
38693
38694
38695
38696
38697
38698
38699
38700 const POST_CREATE_PROJECT_CMD = 'post-create-project-cmd';
38701
38702
38703
38704
38705
38706
38707
38708
38709 const PRE_ARCHIVE_CMD = 'pre-archive-cmd';
38710
38711
38712
38713
38714
38715
38716
38717
38718 const POST_ARCHIVE_CMD = 'post-archive-cmd';
38719
38720
38721
38722
38723
38724
38725
38726
38727
38728
38729
38730 const PRE_PACKAGE_INSTALL = 'pre-package-install';
38731
38732
38733
38734
38735
38736
38737
38738
38739
38740 const POST_PACKAGE_INSTALL = 'post-package-install';
38741
38742
38743
38744
38745
38746
38747
38748
38749
38750 const PRE_PACKAGE_UPDATE = 'pre-package-update';
38751
38752
38753
38754
38755
38756
38757
38758
38759
38760 const POST_PACKAGE_UPDATE = 'post-package-update';
38761
38762
38763
38764
38765
38766
38767
38768
38769
38770 const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
38771
38772
38773
38774
38775
38776
38777
38778
38779
38780 const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
38781 }
38782 <?php
38783
38784
38785
38786
38787
38788
38789
38790
38791
38792
38793
38794 namespace Composer\SelfUpdate;
38795
38796
38797
38798
38799 class Keys
38800 {
38801 public static function fingerprint($path)
38802 {
38803 $hash = strtoupper(hash('sha256', preg_replace('{\s}', '', file_get_contents($path))));
38804
38805 return implode(' ', array(
38806 substr($hash, 0, 8),
38807 substr($hash, 8, 8),
38808 substr($hash, 16, 8),
38809 substr($hash, 24, 8),
38810 '', 
38811  substr($hash, 32, 8),
38812 substr($hash, 40, 8),
38813 substr($hash, 48, 8),
38814 substr($hash, 56, 8),
38815 ));
38816 }
38817 }
38818 <?php
38819
38820
38821
38822
38823
38824
38825
38826
38827
38828
38829
38830 namespace Composer\SelfUpdate;
38831
38832 use Composer\Util\RemoteFilesystem;
38833 use Composer\Config;
38834 use Composer\Json\JsonFile;
38835
38836
38837
38838
38839 class Versions
38840 {
38841 private $rfs;
38842 private $config;
38843 private $channel;
38844
38845 public function __construct(Config $config, RemoteFilesystem $rfs)
38846 {
38847 $this->rfs = $rfs;
38848 $this->config = $config;
38849 }
38850
38851 public function getChannel()
38852 {
38853 if ($this->channel) {
38854 return $this->channel;
38855 }
38856
38857 $channelFile = $this->config->get('home').'/update-channel';
38858 if (file_exists($channelFile)) {
38859 $channel = trim(file_get_contents($channelFile));
38860 if (in_array($channel, array('stable', 'preview', 'snapshot'), true)) {
38861 return $this->channel = $channel;
38862 }
38863 }
38864
38865 return $this->channel = 'stable';
38866 }
38867
38868 public function setChannel($channel)
38869 {
38870 if (!in_array($channel, array('stable', 'preview', 'snapshot'), true)) {
38871 throw new \InvalidArgumentException('Invalid channel '.$channel.', must be one of: stable, preview, snapshot');
38872 }
38873
38874 $channelFile = $this->config->get('home').'/update-channel';
38875 $this->channel = $channel;
38876 file_put_contents($channelFile, $channel.PHP_EOL);
38877 }
38878
38879 public function getLatest()
38880 {
38881 $protocol = extension_loaded('openssl') ? 'https' : 'http';
38882 $versions = JsonFile::parseJson($this->rfs->getContents('getcomposer.org', $protocol . '://getcomposer.org/versions', false));
38883
38884 foreach ($versions[$this->getChannel()] as $version) {
38885 if ($version['min-php'] <= PHP_VERSION_ID) {
38886 return $version;
38887 }
38888 }
38889
38890 throw new \LogicException('There is no version of Composer available for your PHP version ('.PHP_VERSION.')');
38891 }
38892 }
38893 <?php
38894
38895
38896
38897
38898
38899
38900
38901
38902
38903
38904
38905 namespace Composer\Util;
38906
38907 use Composer\Config;
38908 use Composer\IO\IOInterface;
38909
38910
38911
38912
38913 class AuthHelper
38914 {
38915 protected $io;
38916 protected $config;
38917
38918 public function __construct(IOInterface $io, Config $config)
38919 {
38920 $this->io = $io;
38921 $this->config = $config;
38922 }
38923
38924 public function storeAuth($originUrl, $storeAuth)
38925 {
38926 $store = false;
38927 $configSource = $this->config->getAuthConfigSource();
38928 if ($storeAuth === true) {
38929 $store = $configSource;
38930 } elseif ($storeAuth === 'prompt') {
38931 $answer = $this->io->askAndValidate(
38932 'Do you want to store credentials for '.$originUrl.' in '.$configSource->getName().' ? [Yn] ',
38933 function ($value) {
38934 $input = strtolower(substr(trim($value), 0, 1));
38935 if (in_array($input, array('y','n'))) {
38936 return $input;
38937 }
38938 throw new \RuntimeException('Please answer (y)es or (n)o');
38939 },
38940 null,
38941 'y'
38942 );
38943
38944 if ($answer === 'y') {
38945 $store = $configSource;
38946 }
38947 }
38948 if ($store) {
38949 $store->addConfigSetting(
38950 'http-basic.'.$originUrl,
38951 $this->io->getAuthentication($originUrl)
38952 );
38953 }
38954 }
38955 }
38956 <?php
38957
38958
38959
38960
38961
38962
38963
38964
38965
38966
38967
38968 namespace Composer\Util;
38969
38970 use Composer\Factory;
38971 use Composer\IO\IOInterface;
38972 use Composer\Config;
38973 use Composer\Downloader\TransportException;
38974
38975
38976
38977
38978 class Bitbucket
38979 {
38980 private $io;
38981 private $config;
38982 private $process;
38983 private $remoteFilesystem;
38984 private $token = array();
38985 private $time;
38986
38987 const OAUTH2_ACCESS_TOKEN_URL = 'https://bitbucket.org/site/oauth2/access_token';
38988
38989
38990
38991
38992
38993
38994
38995
38996
38997
38998 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null, $time = null)
38999 {
39000 $this->io = $io;
39001 $this->config = $config;
39002 $this->process = $process ?: new ProcessExecutor;
39003 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
39004 $this->time = $time;
39005 }
39006
39007
39008
39009
39010 public function getToken()
39011 {
39012 if (!isset($this->token['access_token'])) {
39013 return '';
39014 }
39015
39016 return $this->token['access_token'];
39017 }
39018
39019
39020
39021
39022
39023
39024
39025 public function authorizeOAuth($originUrl)
39026 {
39027 if ($originUrl !== 'bitbucket.org') {
39028 return false;
39029 }
39030
39031
39032  if (0 === $this->process->execute('git config bitbucket.accesstoken', $output)) {
39033 $this->io->setAuthentication($originUrl, 'x-token-auth', trim($output));
39034
39035 return true;
39036 }
39037
39038 return false;
39039 }
39040
39041
39042
39043
39044
39045 private function requestAccessToken($originUrl)
39046 {
39047 try {
39048 $json = $this->remoteFilesystem->getContents($originUrl, self::OAUTH2_ACCESS_TOKEN_URL, false, array(
39049 'retry-auth-failure' => false,
39050 'http' => array(
39051 'method' => 'POST',
39052 'content' => 'grant_type=client_credentials',
39053 ),
39054 ));
39055
39056 $this->token = json_decode($json, true);
39057 } catch (TransportException $e) {
39058 if ($e->getCode() === 400) {
39059 $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
39060 $this->io->writeError('This can have two reasons:');
39061 $this->io->writeError('1. You are authenticating with a bitbucket username/password combination');
39062 $this->io->writeError('2. You are using an OAuth consumer, but didn\'t configure a (dummy) callback url');
39063
39064 return false;
39065 } elseif (in_array($e->getCode(), array(403, 401))) {
39066 $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
39067 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
39068
39069 return false;
39070 }
39071
39072 throw $e;
39073 }
39074
39075 return true;
39076 }
39077
39078
39079
39080
39081
39082
39083
39084
39085
39086
39087 public function authorizeOAuthInteractively($originUrl, $message = null)
39088 {
39089 if ($message) {
39090 $this->io->writeError($message);
39091 }
39092
39093 $url = 'https://confluence.atlassian.com/bitbucket/oauth-on-bitbucket-cloud-238027431.html';
39094 $this->io->writeError(sprintf('Follow the instructions on %s', $url));
39095 $this->io->writeError(sprintf('to create a consumer. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
39096 $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)');
39097
39098 $consumerKey = trim($this->io->askAndHideAnswer('Consumer Key (hidden): '));
39099
39100 if (!$consumerKey) {
39101 $this->io->writeError('<warning>No consumer key given, aborting.</warning>');
39102 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
39103
39104 return false;
39105 }
39106
39107 $consumerSecret = trim($this->io->askAndHideAnswer('Consumer Secret (hidden): '));
39108
39109 if (!$consumerSecret) {
39110 $this->io->writeError('<warning>No consumer secret given, aborting.</warning>');
39111 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
39112
39113 return false;
39114 }
39115
39116 $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
39117
39118 if (!$this->requestAccessToken($originUrl)) {
39119 return false;
39120 }
39121
39122
39123  $this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);
39124
39125
39126  $this->config->getAuthConfigSource()->removeConfigSetting('http-basic.' . $originUrl);
39127
39128 $this->io->writeError('<info>Consumer stored successfully.</info>');
39129
39130 return true;
39131 }
39132
39133
39134
39135
39136
39137
39138
39139
39140
39141 public function requestToken($originUrl, $consumerKey, $consumerSecret)
39142 {
39143 if (!empty($this->token) || $this->getTokenFromConfig($originUrl)) {
39144 return $this->token['access_token'];
39145 }
39146
39147 $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
39148 if (!$this->requestAccessToken($originUrl)) {
39149 return '';
39150 }
39151
39152 $this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);
39153
39154 return $this->token['access_token'];
39155 }
39156
39157
39158
39159
39160
39161
39162
39163 private function storeInAuthConfig($originUrl, $consumerKey, $consumerSecret)
39164 {
39165 $this->config->getConfigSource()->removeConfigSetting('bitbucket-oauth.'.$originUrl);
39166
39167 $time = null === $this->time ? time() : $this->time;
39168 $consumer = array(
39169 "consumer-key" => $consumerKey,
39170 "consumer-secret" => $consumerSecret,
39171 "access-token" => $this->token['access_token'],
39172 "access-token-expiration" => $time + $this->token['expires_in'],
39173 );
39174
39175 $this->config->getAuthConfigSource()->addConfigSetting('bitbucket-oauth.'.$originUrl, $consumer);
39176 }
39177
39178
39179
39180
39181
39182 private function getTokenFromConfig($originUrl)
39183 {
39184 $authConfig = $this->config->get('bitbucket-oauth');
39185
39186 if (
39187 !isset($authConfig[$originUrl]['access-token'])
39188 || !isset($authConfig[$originUrl]['access-token-expiration'])
39189 || time() > $authConfig[$originUrl]['access-token-expiration']
39190 ) {
39191 return false;
39192 }
39193
39194 $this->token = array(
39195 'access_token' => $authConfig[$originUrl]['access-token'],
39196 );
39197
39198 return true;
39199 }
39200 }
39201 <?php
39202
39203
39204
39205
39206
39207
39208
39209
39210
39211
39212
39213 namespace Composer\Util;
39214
39215
39216
39217
39218
39219
39220 class ComposerMirror
39221 {
39222 public static function processUrl($mirrorUrl, $packageName, $version, $reference, $type)
39223 {
39224 if ($reference) {
39225 $reference = preg_match('{^([a-f0-9]*|%reference%)$}', $reference) ? $reference : md5($reference);
39226 }
39227 $version = strpos($version, '/') === false ? $version : md5($version);
39228
39229 return str_replace(
39230 array('%package%', '%version%', '%reference%', '%type%'),
39231 array($packageName, $version, $reference, $type),
39232 $mirrorUrl
39233 );
39234 }
39235
39236 public static function processGitUrl($mirrorUrl, $packageName, $url, $type)
39237 {
39238 if (preg_match('#^(?:(?:https?|git)://github\.com/|git@github\.com:)([^/]+)/(.+?)(?:\.git)?$#', $url, $match)) {
39239 $url = 'gh-'.$match[1].'/'.$match[2];
39240 } elseif (preg_match('#^https://bitbucket\.org/([^/]+)/(.+?)(?:\.git)?/?$#', $url, $match)) {
39241 $url = 'bb-'.$match[1].'/'.$match[2];
39242 } else {
39243 $url = preg_replace('{[^a-z0-9_.-]}i', '-', trim($url, '/'));
39244 }
39245
39246 return str_replace(
39247 array('%package%', '%normalizedUrl%', '%type%'),
39248 array($packageName, $url, $type),
39249 $mirrorUrl
39250 );
39251 }
39252
39253 public static function processHgUrl($mirrorUrl, $packageName, $url, $type)
39254 {
39255 return self::processGitUrl($mirrorUrl, $packageName, $url, $type);
39256 }
39257 }
39258 <?php
39259
39260
39261
39262
39263
39264
39265
39266
39267
39268
39269
39270 namespace Composer\Util;
39271
39272 use Composer\Package\Loader\ArrayLoader;
39273 use Composer\Package\Loader\ValidatingArrayLoader;
39274 use Composer\Package\Loader\InvalidPackageException;
39275 use Composer\Json\JsonValidationException;
39276 use Composer\IO\IOInterface;
39277 use Composer\Json\JsonFile;
39278 use Composer\Spdx\SpdxLicenses;
39279
39280
39281
39282
39283
39284
39285
39286 class ConfigValidator
39287 {
39288 private $io;
39289
39290 public function __construct(IOInterface $io)
39291 {
39292 $this->io = $io;
39293 }
39294
39295
39296
39297
39298
39299
39300
39301
39302
39303 public function validate($file, $arrayLoaderValidationFlags = ValidatingArrayLoader::CHECK_ALL)
39304 {
39305 $errors = array();
39306 $publishErrors = array();
39307 $warnings = array();
39308
39309
39310  $laxValid = false;
39311 try {
39312 $json = new JsonFile($file, null, $this->io);
39313 $manifest = $json->read();
39314
39315 $json->validateSchema(JsonFile::LAX_SCHEMA);
39316 $laxValid = true;
39317 $json->validateSchema();
39318 } catch (JsonValidationException $e) {
39319 foreach ($e->getErrors() as $message) {
39320 if ($laxValid) {
39321 $publishErrors[] = $message;
39322 } else {
39323 $errors[] = $message;
39324 }
39325 }
39326 } catch (\Exception $e) {
39327 $errors[] = $e->getMessage();
39328
39329 return array($errors, $publishErrors, $warnings);
39330 }
39331
39332
39333  if (!empty($manifest['license'])) {
39334
39335  if (is_array($manifest['license'])) {
39336 foreach ($manifest['license'] as $key => $license) {
39337 if ('proprietary' === $license) {
39338 unset($manifest['license'][$key]);
39339 }
39340 }
39341 }
39342
39343 $licenseValidator = new SpdxLicenses();
39344 if ('proprietary' !== $manifest['license'] && array() !== $manifest['license'] && !$licenseValidator->validate($manifest['license']) && $licenseValidator->validate(trim($manifest['license']))) {
39345 $warnings[] = sprintf(
39346 'License %s must not contain extra spaces, make sure to trim it.',
39347 json_encode($manifest['license'])
39348 );
39349 } elseif ('proprietary' !== $manifest['license'] && array() !== $manifest['license'] && !$licenseValidator->validate($manifest['license'])) {
39350 $warnings[] = sprintf(
39351 'License %s is not a valid SPDX license identifier, see https://spdx.org/licenses/ if you use an open license.'
39352 . PHP_EOL .
39353 'If the software is closed-source, you may use "proprietary" as license.',
39354 json_encode($manifest['license'])
39355 );
39356 }
39357 } else {
39358 $warnings[] = 'No license specified, it is recommended to do so. For closed-source software you may use "proprietary" as license.';
39359 }
39360
39361 if (isset($manifest['version'])) {
39362 $warnings[] = 'The version field is present, it is recommended to leave it out if the package is published on Packagist.';
39363 }
39364
39365 if (!empty($manifest['name']) && preg_match('{[A-Z]}', $manifest['name'])) {
39366 $suggestName = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $manifest['name']);
39367 $suggestName = strtolower($suggestName);
39368
39369 $publishErrors[] = sprintf(
39370 '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.',
39371 $manifest['name'],
39372 $suggestName
39373 );
39374 }
39375
39376 if (!empty($manifest['type']) && $manifest['type'] == 'composer-installer') {
39377 $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.";
39378 }
39379
39380
39381  if (isset($manifest['require']) && isset($manifest['require-dev'])) {
39382 $requireOverrides = array_intersect_key($manifest['require'], $manifest['require-dev']);
39383
39384 if (!empty($requireOverrides)) {
39385 $plural = (count($requireOverrides) > 1) ? 'are' : 'is';
39386 $warnings[] = implode(', ', array_keys($requireOverrides)). " {$plural} required both in require and require-dev, this can lead to unexpected behavior";
39387 }
39388 }
39389
39390
39391  $require = isset($manifest['require']) ? $manifest['require'] : array();
39392 $requireDev = isset($manifest['require-dev']) ? $manifest['require-dev'] : array();
39393 $packages = array_merge($require, $requireDev);
39394 foreach ($packages as $package => $version) {
39395 if (preg_match('/#/', $version) === 1) {
39396 $warnings[] = sprintf(
39397 'The package "%s" is pointing to a commit-ref, this is bad practice and can cause unforeseen issues.',
39398 $package
39399 );
39400 }
39401 }
39402
39403
39404  if (isset($manifest['autoload']['psr-0'][''])) {
39405 $warnings[] = "Defining autoload.psr-0 with an empty namespace prefix is a bad idea for performance";
39406 }
39407 if (isset($manifest['autoload']['psr-4'][''])) {
39408 $warnings[] = "Defining autoload.psr-4 with an empty namespace prefix is a bad idea for performance";
39409 }
39410
39411 try {
39412 $loader = new ValidatingArrayLoader(new ArrayLoader(), true, null, $arrayLoaderValidationFlags);
39413 if (!isset($manifest['version'])) {
39414 $manifest['version'] = '1.0.0';
39415 }
39416 if (!isset($manifest['name'])) {
39417 $manifest['name'] = 'dummy/dummy';
39418 }
39419 $loader->load($manifest);
39420 } catch (InvalidPackageException $e) {
39421 $errors = array_merge($errors, $e->getErrors());
39422 }
39423
39424 $warnings = array_merge($warnings, $loader->getWarnings());
39425
39426 return array($errors, $publishErrors, $warnings);
39427 }
39428 }
39429 <?php
39430
39431
39432
39433
39434
39435
39436
39437
39438
39439
39440
39441 namespace Composer\Util;
39442
39443 use Composer\IO\IOInterface;
39444
39445
39446
39447
39448
39449
39450 class ErrorHandler
39451 {
39452 private static $io;
39453
39454
39455
39456
39457
39458
39459
39460
39461
39462
39463
39464
39465 public static function handle($level, $message, $file, $line)
39466 {
39467
39468  if (!(error_reporting() & $level)) {
39469 return;
39470 }
39471
39472 if (ini_get('xdebug.scream')) {
39473 $message .= "\n\nWarning: You have xdebug.scream enabled, the warning above may be".
39474 "\na legitimately suppressed error that you were not supposed to see.";
39475 }
39476
39477 if ($level !== E_DEPRECATED && $level !== E_USER_DEPRECATED) {
39478 throw new \ErrorException($message, 0, $level, $file, $line);
39479 }
39480
39481 if (self::$io) {
39482 self::$io->writeError('<warning>Deprecation Notice: '.$message.' in '.$file.':'.$line.'</warning>');
39483 if (self::$io->isVerbose()) {
39484 self::$io->writeError('<warning>Stack trace:</warning>');
39485 self::$io->writeError(array_filter(array_map(function ($a) {
39486 if (isset($a['line'], $a['file'])) {
39487 return '<warning> '.$a['file'].':'.$a['line'].'</warning>';
39488 }
39489
39490 return null;
39491 }, array_slice(debug_backtrace(), 2))));
39492 }
39493 }
39494 }
39495
39496
39497
39498
39499
39500
39501 public static function register(IOInterface $io = null)
39502 {
39503 set_error_handler(array(__CLASS__, 'handle'));
39504 error_reporting(E_ALL | E_STRICT);
39505 self::$io = $io;
39506 }
39507 }
39508 <?php
39509
39510
39511
39512
39513
39514
39515
39516
39517
39518
39519
39520 namespace Composer\Util;
39521
39522 use RecursiveDirectoryIterator;
39523 use RecursiveIteratorIterator;
39524 use Symfony\Component\Filesystem\Exception\IOException;
39525 use Symfony\Component\Finder\Finder;
39526
39527
39528
39529
39530
39531 class Filesystem
39532 {
39533 private $processExecutor;
39534
39535 public function __construct(ProcessExecutor $executor = null)
39536 {
39537 $this->processExecutor = $executor ?: new ProcessExecutor();
39538 }
39539
39540 public function remove($file)
39541 {
39542 if (is_dir($file)) {
39543 return $this->removeDirectory($file);
39544 }
39545
39546 if (file_exists($file)) {
39547 return $this->unlink($file);
39548 }
39549
39550 return false;
39551 }
39552
39553
39554
39555
39556
39557
39558
39559 public function isDirEmpty($dir)
39560 {
39561 $finder = Finder::create()
39562 ->ignoreVCS(false)
39563 ->ignoreDotFiles(false)
39564 ->depth(0)
39565 ->in($dir);
39566
39567 return count($finder) === 0;
39568 }
39569
39570 public function emptyDirectory($dir, $ensureDirectoryExists = true)
39571 {
39572 if (file_exists($dir) && is_link($dir)) {
39573 $this->unlink($dir);
39574 }
39575
39576 if ($ensureDirectoryExists) {
39577 $this->ensureDirectoryExists($dir);
39578 }
39579
39580 if (is_dir($dir)) {
39581 $finder = Finder::create()
39582 ->ignoreVCS(false)
39583 ->ignoreDotFiles(false)
39584 ->depth(0)
39585 ->in($dir);
39586
39587 foreach ($finder as $path) {
39588 $this->remove((string) $path);
39589 }
39590 }
39591 }
39592
39593
39594
39595
39596
39597
39598
39599
39600
39601
39602
39603 public function removeDirectory($directory)
39604 {
39605 if ($this->isSymlinkedDirectory($directory)) {
39606 return $this->unlinkSymlinkedDirectory($directory);
39607 }
39608
39609 if ($this->isJunction($directory)) {
39610 return $this->removeJunction($directory);
39611 }
39612
39613 if (!file_exists($directory) || !is_dir($directory)) {
39614 return true;
39615 }
39616
39617 if (preg_match('{^(?:[a-z]:)?[/\\\\]+$}i', $directory)) {
39618 throw new \RuntimeException('Aborting an attempted deletion of '.$directory.', this was probably not intended, if it is a real use case please report it.');
39619 }
39620
39621 if (!function_exists('proc_open')) {
39622 return $this->removeDirectoryPhp($directory);
39623 }
39624
39625 if (Platform::isWindows()) {
39626 $cmd = sprintf('rmdir /S /Q %s', ProcessExecutor::escape(realpath($directory)));
39627 } else {
39628 $cmd = sprintf('rm -rf %s', ProcessExecutor::escape($directory));
39629 }
39630
39631 $result = $this->getProcess()->execute($cmd, $output) === 0;
39632
39633
39634  clearstatcache();
39635
39636 if ($result && !file_exists($directory)) {
39637 return true;
39638 }
39639
39640 return $this->removeDirectoryPhp($directory);
39641 }
39642
39643
39644
39645
39646
39647
39648
39649
39650
39651
39652
39653 public function removeDirectoryPhp($directory)
39654 {
39655 try {
39656 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
39657 } catch (\UnexpectedValueException $e) {
39658
39659  
39660  clearstatcache();
39661 usleep(100000);
39662 if (!is_dir($directory)) {
39663 return true;
39664 }
39665 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
39666 }
39667 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
39668
39669 foreach ($ri as $file) {
39670 if ($file->isDir()) {
39671 $this->rmdir($file->getPathname());
39672 } else {
39673 $this->unlink($file->getPathname());
39674 }
39675 }
39676
39677 return $this->rmdir($directory);
39678 }
39679
39680 public function ensureDirectoryExists($directory)
39681 {
39682 if (!is_dir($directory)) {
39683 if (file_exists($directory)) {
39684 throw new \RuntimeException(
39685 $directory.' exists and is not a directory.'
39686 );
39687 }
39688 if (!@mkdir($directory, 0777, true)) {
39689 throw new \RuntimeException(
39690 $directory.' does not exist and could not be created.'
39691 );
39692 }
39693 }
39694 }
39695
39696
39697
39698
39699
39700
39701
39702
39703 public function unlink($path)
39704 {
39705 if (!@$this->unlinkImplementation($path)) {
39706
39707  if (!Platform::isWindows() || (usleep(350000) && !@$this->unlinkImplementation($path))) {
39708 $error = error_get_last();
39709 $message = 'Could not delete '.$path.': ' . @$error['message'];
39710 if (Platform::isWindows()) {
39711 $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
39712 }
39713
39714 throw new \RuntimeException($message);
39715 }
39716 }
39717
39718 return true;
39719 }
39720
39721
39722
39723
39724
39725
39726
39727
39728 public function rmdir($path)
39729 {
39730 if (!@rmdir($path)) {
39731
39732  if (!Platform::isWindows() || (usleep(350000) && !@rmdir($path))) {
39733 $error = error_get_last();
39734 $message = 'Could not delete '.$path.': ' . @$error['message'];
39735 if (Platform::isWindows()) {
39736 $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
39737 }
39738
39739 throw new \RuntimeException($message);
39740 }
39741 }
39742
39743 return true;
39744 }
39745
39746
39747
39748
39749
39750
39751
39752
39753
39754
39755 public function copyThenRemove($source, $target)
39756 {
39757 if (!is_dir($source)) {
39758 copy($source, $target);
39759 $this->unlink($source);
39760
39761 return;
39762 }
39763
39764 $it = new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS);
39765 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::SELF_FIRST);
39766 $this->ensureDirectoryExists($target);
39767
39768 foreach ($ri as $file) {
39769 $targetPath = $target . DIRECTORY_SEPARATOR . $ri->getSubPathName();
39770 if ($file->isDir()) {
39771 $this->ensureDirectoryExists($targetPath);
39772 } else {
39773 copy($file->getPathname(), $targetPath);
39774 }
39775 }
39776
39777 $this->removeDirectoryPhp($source);
39778 }
39779
39780 public function rename($source, $target)
39781 {
39782 if (true === @rename($source, $target)) {
39783 return;
39784 }
39785
39786 if (!function_exists('proc_open')) {
39787 return $this->copyThenRemove($source, $target);
39788 }
39789
39790 if (Platform::isWindows()) {
39791
39792  $command = sprintf('xcopy %s %s /E /I /Q /Y', ProcessExecutor::escape($source), ProcessExecutor::escape($target));
39793 $result = $this->processExecutor->execute($command, $output);
39794
39795
39796  clearstatcache();
39797
39798 if (0 === $result) {
39799 $this->remove($source);
39800
39801 return;
39802 }
39803 } else {
39804
39805  
39806  $command = sprintf('mv %s %s', ProcessExecutor::escape($source), ProcessExecutor::escape($target));
39807 $result = $this->processExecutor->execute($command, $output);
39808
39809
39810  clearstatcache();
39811
39812 if (0 === $result) {
39813 return;
39814 }
39815 }
39816
39817 return $this->copyThenRemove($source, $target);
39818 }
39819
39820
39821
39822
39823
39824
39825
39826
39827
39828
39829 public function findShortestPath($from, $to, $directories = false)
39830 {
39831 if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
39832 throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
39833 }
39834
39835 $from = lcfirst($this->normalizePath($from));
39836 $to = lcfirst($this->normalizePath($to));
39837
39838 if ($directories) {
39839 $from = rtrim($from, '/') . '/dummy_file';
39840 }
39841
39842 if (dirname($from) === dirname($to)) {
39843 return './'.basename($to);
39844 }
39845
39846 $commonPath = $to;
39847 while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath)) {
39848 $commonPath = strtr(dirname($commonPath), '\\', '/');
39849 }
39850
39851 if (0 !== strpos($from, $commonPath) || '/' === $commonPath) {
39852 return $to;
39853 }
39854
39855 $commonPath = rtrim($commonPath, '/') . '/';
39856 $sourcePathDepth = substr_count(substr($from, strlen($commonPath)), '/');
39857 $commonPathCode = str_repeat('../', $sourcePathDepth);
39858
39859 return ($commonPathCode . substr($to, strlen($commonPath))) ?: './';
39860 }
39861
39862
39863
39864
39865
39866
39867
39868
39869
39870
39871
39872 public function findShortestPathCode($from, $to, $directories = false, $staticCode = false)
39873 {
39874 if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
39875 throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
39876 }
39877
39878 $from = lcfirst($this->normalizePath($from));
39879 $to = lcfirst($this->normalizePath($to));
39880
39881 if ($from === $to) {
39882 return $directories ? '__DIR__' : '__FILE__';
39883 }
39884
39885 $commonPath = $to;
39886 while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath) && '.' !== $commonPath) {
39887 $commonPath = strtr(dirname($commonPath), '\\', '/');
39888 }
39889
39890 if (0 !== strpos($from, $commonPath) || '/' === $commonPath || '.' === $commonPath) {
39891 return var_export($to, true);
39892 }
39893
39894 $commonPath = rtrim($commonPath, '/') . '/';
39895 if (strpos($to, $from.'/') === 0) {
39896 return '__DIR__ . '.var_export(substr($to, strlen($from)), true);
39897 }
39898 $sourcePathDepth = substr_count(substr($from, strlen($commonPath)), '/') + $directories;
39899 if ($staticCode) {
39900 $commonPathCode = "__DIR__ . '".str_repeat('/..', $sourcePathDepth)."'";
39901 } else {
39902 $commonPathCode = str_repeat('dirname(', $sourcePathDepth).'__DIR__'.str_repeat(')', $sourcePathDepth);
39903 }
39904 $relTarget = substr($to, strlen($commonPath));
39905
39906 return $commonPathCode . (strlen($relTarget) ? '.' . var_export('/' . $relTarget, true) : '');
39907 }
39908
39909
39910
39911
39912
39913
39914
39915 public function isAbsolutePath($path)
39916 {
39917 return substr($path, 0, 1) === '/' || substr($path, 1, 1) === ':';
39918 }
39919
39920
39921
39922
39923
39924
39925
39926
39927
39928 public function size($path)
39929 {
39930 if (!file_exists($path)) {
39931 throw new \RuntimeException("$path does not exist.");
39932 }
39933 if (is_dir($path)) {
39934 return $this->directorySize($path);
39935 }
39936
39937 return filesize($path);
39938 }
39939
39940
39941
39942
39943
39944
39945
39946
39947 public function normalizePath($path)
39948 {
39949 $parts = array();
39950 $path = strtr($path, '\\', '/');
39951 $prefix = '';
39952 $absolute = false;
39953
39954
39955  if (preg_match('{^( [0-9a-z]{2,}+: (?: // (?: [a-z]: )? )? | [a-z]: )}ix', $path, $match)) {
39956 $prefix = $match[1];
39957 $path = substr($path, strlen($prefix));
39958 }
39959
39960 if (substr($path, 0, 1) === '/') {
39961 $absolute = true;
39962 $path = substr($path, 1);
39963 }
39964
39965 $up = false;
39966 foreach (explode('/', $path) as $chunk) {
39967 if ('..' === $chunk && ($absolute || $up)) {
39968 array_pop($parts);
39969 $up = !(empty($parts) || '..' === end($parts));
39970 } elseif ('.' !== $chunk && '' !== $chunk) {
39971 $parts[] = $chunk;
39972 $up = '..' !== $chunk;
39973 }
39974 }
39975
39976 return $prefix.($absolute ? '/' : '').implode('/', $parts);
39977 }
39978
39979
39980
39981
39982
39983
39984
39985 public static function isLocalPath($path)
39986 {
39987 return (bool) preg_match('{^(file://(?!//)|/(?!/)|/?[a-z]:[\\\\/]|\.\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i', $path);
39988 }
39989
39990 public static function getPlatformPath($path)
39991 {
39992 if (Platform::isWindows()) {
39993 $path = preg_replace('{^(?:file:///([a-z]):?/)}i', 'file://$1:/', $path);
39994 }
39995
39996 return preg_replace('{^file://}i', '', $path);
39997 }
39998
39999 protected function directorySize($directory)
40000 {
40001 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
40002 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
40003
40004 $size = 0;
40005 foreach ($ri as $file) {
40006 if ($file->isFile()) {
40007 $size += $file->getSize();
40008 }
40009 }
40010
40011 return $size;
40012 }
40013
40014 protected function getProcess()
40015 {
40016 return new ProcessExecutor;
40017 }
40018
40019
40020
40021
40022
40023
40024
40025
40026
40027
40028 private function unlinkImplementation($path)
40029 {
40030 if (Platform::isWindows() && is_dir($path) && is_link($path)) {
40031 return rmdir($path);
40032 }
40033
40034 return unlink($path);
40035 }
40036
40037
40038
40039
40040
40041
40042
40043
40044 public function relativeSymlink($target, $link)
40045 {
40046 $cwd = getcwd();
40047
40048 $relativePath = $this->findShortestPath($link, $target);
40049 chdir(dirname($link));
40050 $result = @symlink($relativePath, $link);
40051
40052 chdir($cwd);
40053
40054 return (bool) $result;
40055 }
40056
40057
40058
40059
40060
40061
40062
40063
40064 public function isSymlinkedDirectory($directory)
40065 {
40066 if (!is_dir($directory)) {
40067 return false;
40068 }
40069
40070 $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
40071
40072 return is_link($resolved);
40073 }
40074
40075
40076
40077
40078
40079
40080 private function unlinkSymlinkedDirectory($directory)
40081 {
40082 $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
40083
40084 return $this->unlink($resolved);
40085 }
40086
40087
40088
40089
40090
40091
40092
40093
40094 private function resolveSymlinkedDirectorySymlink($pathname)
40095 {
40096 if (!is_dir($pathname)) {
40097 return $pathname;
40098 }
40099
40100 $resolved = rtrim($pathname, '/');
40101
40102 if (!strlen($resolved)) {
40103 return $pathname;
40104 }
40105
40106 return $resolved;
40107 }
40108
40109
40110
40111
40112
40113
40114
40115 public function junction($target, $junction)
40116 {
40117 if (!Platform::isWindows()) {
40118 throw new \LogicException(sprintf('Function %s is not available on non-Windows platform', __CLASS__));
40119 }
40120 if (!is_dir($target)) {
40121 throw new IOException(sprintf('Cannot junction to "%s" as it is not a directory.', $target), 0, null, $target);
40122 }
40123 $cmd = sprintf('mklink /J %s %s',
40124 ProcessExecutor::escape(str_replace('/', DIRECTORY_SEPARATOR, $junction)),
40125 ProcessExecutor::escape(realpath($target)));
40126 if ($this->getProcess()->execute($cmd, $output) !== 0) {
40127 throw new IOException(sprintf('Failed to create junction to "%s" at "%s".', $target, $junction), 0, null, $target);
40128 }
40129 clearstatcache(true, $junction);
40130 }
40131
40132
40133
40134
40135
40136
40137
40138 public function isJunction($junction)
40139 {
40140 if (!Platform::isWindows()) {
40141 return false;
40142 }
40143 if (!is_dir($junction) || is_link($junction)) {
40144 return false;
40145 }
40146
40147
40148
40149
40150
40151
40152
40153
40154
40155
40156
40157 clearstatcache(true, $junction);
40158 $stat = lstat($junction);
40159
40160 return !($stat['mode'] & 0xC000);
40161 }
40162
40163
40164
40165
40166
40167
40168
40169 public function removeJunction($junction)
40170 {
40171 if (!Platform::isWindows()) {
40172 return false;
40173 }
40174 $junction = rtrim(str_replace('/', DIRECTORY_SEPARATOR, $junction), DIRECTORY_SEPARATOR);
40175 if (!$this->isJunction($junction)) {
40176 throw new IOException(sprintf('%s is not a junction and thus cannot be removed as one', $junction));
40177 }
40178 $cmd = sprintf('rmdir /S /Q %s', ProcessExecutor::escape($junction));
40179 clearstatcache(true, $junction);
40180
40181 return ($this->getProcess()->execute($cmd, $output) === 0);
40182 }
40183 }
40184 <?php
40185
40186
40187
40188
40189
40190
40191
40192
40193
40194
40195
40196 namespace Composer\Util;
40197
40198 use Composer\Config;
40199 use Composer\IO\IOInterface;
40200
40201
40202
40203
40204 class Git
40205 {
40206 private static $version;
40207
40208
40209 protected $io;
40210
40211 protected $config;
40212
40213 protected $process;
40214
40215 protected $filesystem;
40216
40217 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process, Filesystem $fs)
40218 {
40219 $this->io = $io;
40220 $this->config = $config;
40221 $this->process = $process;
40222 $this->filesystem = $fs;
40223 }
40224
40225 public function runCommand($commandCallable, $url, $cwd, $initialClone = false)
40226 {
40227
40228  $this->config->prohibitUrlByConfig($url, $this->io);
40229
40230 if ($initialClone) {
40231 $origCwd = $cwd;
40232 $cwd = null;
40233 }
40234
40235 if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $url)) {
40236 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.');
40237 }
40238
40239 if (!$initialClone) {
40240
40241  $this->process->execute('git remote -v', $output, $cwd);
40242 if (preg_match('{^(?:composer|origin)\s+https?://(.+):(.+)@([^/]+)}im', $output, $match)) {
40243 $this->io->setAuthentication($match[3], urldecode($match[1]), urldecode($match[2]));
40244 }
40245 }
40246
40247 $protocols = $this->config->get('github-protocols');
40248 if (!is_array($protocols)) {
40249 throw new \RuntimeException('Config value "github-protocols" must be an array, got ' . gettype($protocols));
40250 }
40251
40252  if (preg_match('{^(?:https?|git)://' . self::getGitHubDomainsRegex($this->config) . '/(.*)}', $url, $match)) {
40253 $messages = array();
40254 foreach ($protocols as $protocol) {
40255 if ('ssh' === $protocol) {
40256 $protoUrl = "git@" . $match[1] . ":" . $match[2];
40257 } else {
40258 $protoUrl = $protocol . "://" . $match[1] . "/" . $match[2];
40259 }
40260
40261 if (0 === $this->process->execute(call_user_func($commandCallable, $protoUrl), $ignoredOutput, $cwd)) {
40262 return;
40263 }
40264 $messages[] = '- ' . $protoUrl . "\n" . preg_replace('#^#m', '  ', $this->process->getErrorOutput());
40265 if ($initialClone) {
40266 $this->filesystem->removeDirectory($origCwd);
40267 }
40268 }
40269
40270
40271  $this->throwException('Failed to clone ' . $url . ' via ' . implode(', ', $protocols) . ' protocols, aborting.' . "\n\n" . implode("\n", $messages), $url);
40272 }
40273
40274
40275  $bypassSshForGitHub = preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url) && !in_array('ssh', $protocols, true);
40276
40277 $command = call_user_func($commandCallable, $url);
40278
40279 $auth = null;
40280 if ($bypassSshForGitHub || 0 !== $this->process->execute($command, $ignoredOutput, $cwd)) {
40281
40282  if (preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url, $match)) {
40283 if (!$this->io->hasAuthentication($match[1])) {
40284 $gitHubUtil = new GitHub($this->io, $this->config, $this->process);
40285 $message = 'Cloning failed using an ssh key for authentication, enter your GitHub credentials to access private repos';
40286
40287 if (!$gitHubUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
40288 $gitHubUtil->authorizeOAuthInteractively($match[1], $message);
40289 }
40290 }
40291
40292 if ($this->io->hasAuthentication($match[1])) {
40293 $auth = $this->io->getAuthentication($match[1]);
40294 $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git';
40295 $command = call_user_func($commandCallable, $authUrl);
40296 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
40297 return;
40298 }
40299 }
40300 } elseif (preg_match('{^https://(bitbucket\.org)/(.*)(\.git)?$}U', $url, $match)) { 
40301  $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process);
40302
40303 if (!$this->io->hasAuthentication($match[1])) {
40304 $message = 'Enter your Bitbucket credentials to access private repos';
40305
40306 if (!$bitbucketUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
40307 $bitbucketUtil->authorizeOAuthInteractively($match[1], $message);
40308 $accessToken = $bitbucketUtil->getToken();
40309 $this->io->setAuthentication($match[1], 'x-token-auth', $accessToken);
40310 }
40311 } else { 
40312  $auth = $this->io->getAuthentication($match[1]);
40313
40314
40315  if ($auth['username'] !== 'x-token-auth') {
40316 $accessToken = $bitbucketUtil->requestToken($match[1], $auth['username'], $auth['password']);
40317 if (! empty($accessToken)) {
40318 $this->io->setAuthentication($match[1], 'x-token-auth', $accessToken);
40319 }
40320 }
40321 }
40322
40323 if ($this->io->hasAuthentication($match[1])) {
40324 $auth = $this->io->getAuthentication($match[1]);
40325 $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git';
40326
40327 $command = call_user_func($commandCallable, $authUrl);
40328 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
40329 return;
40330 }
40331 } else { 
40332  $sshUrl = 'git@bitbucket.org:' . $match[2] . '.git';
40333 $this->io->writeError('    No bitbucket authentication configured. Falling back to ssh.');
40334 $command = call_user_func($commandCallable, $sshUrl);
40335 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
40336 return;
40337 }
40338 }
40339 } elseif ($this->isAuthenticationFailure($url, $match)) { 
40340  if (strpos($match[2], '@')) {
40341 list($authParts, $match[2]) = explode('@', $match[2], 2);
40342 }
40343
40344 $storeAuth = false;
40345 if ($this->io->hasAuthentication($match[2])) {
40346 $auth = $this->io->getAuthentication($match[2]);
40347 } elseif ($this->io->isInteractive()) {
40348 $defaultUsername = null;
40349 if (isset($authParts) && $authParts) {
40350 if (false !== strpos($authParts, ':')) {
40351 list($defaultUsername, ) = explode(':', $authParts, 2);
40352 } else {
40353 $defaultUsername = $authParts;
40354 }
40355 }
40356
40357 $this->io->writeError('    Authentication required (<info>' . parse_url($url, PHP_URL_HOST) . '</info>):');
40358 $auth = array(
40359 'username' => $this->io->ask('      Username: ', $defaultUsername),
40360 'password' => $this->io->askAndHideAnswer('      Password: '),
40361 );
40362 $storeAuth = $this->config->get('store-auths');
40363 }
40364
40365 if ($auth) {
40366 $authUrl = $match[1] . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[2] . $match[3];
40367
40368 $command = call_user_func($commandCallable, $authUrl);
40369 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
40370 $this->io->setAuthentication($match[2], $auth['username'], $auth['password']);
40371 $authHelper = new AuthHelper($this->io, $this->config);
40372 $authHelper->storeAuth($match[2], $storeAuth);
40373
40374 return;
40375 }
40376 }
40377 }
40378
40379 if ($initialClone) {
40380 $this->filesystem->removeDirectory($origCwd);
40381 }
40382 $this->throwException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput(), $url);
40383 }
40384 }
40385
40386 public function syncMirror($url, $dir)
40387 {
40388
40389  if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') {
40390 try {
40391 $commandCallable = function ($url) {
40392 return sprintf('git remote set-url origin %s && git remote update --prune origin', ProcessExecutor::escape($url));
40393 };
40394 $this->runCommand($commandCallable, $url, $dir);
40395 } catch (\Exception $e) {
40396 return false;
40397 }
40398
40399 return true;
40400 }
40401
40402
40403  $this->filesystem->removeDirectory($dir);
40404
40405 $commandCallable = function ($url) use ($dir) {
40406 return sprintf('git clone --mirror %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($dir));
40407 };
40408
40409 $this->runCommand($commandCallable, $url, $dir, true);
40410
40411 return true;
40412 }
40413
40414 private function isAuthenticationFailure($url, &$match)
40415 {
40416 if (!preg_match('{(https?://)([^/]+)(.*)$}i', $url, $match)) {
40417 return false;
40418 }
40419
40420 $authFailures = array(
40421 'fatal: Authentication failed',
40422 'remote error: Invalid username or password.',
40423 'error: 401 Unauthorized',
40424 'fatal: unable to access',
40425 );
40426
40427 foreach ($authFailures as $authFailure) {
40428 if (strpos($this->process->getErrorOutput(), $authFailure) !== false) {
40429 return true;
40430 }
40431 }
40432
40433 return false;
40434 }
40435
40436 public static function cleanEnv()
40437 {
40438 if (PHP_VERSION_ID < 50400 && ini_get('safe_mode') && false === strpos(ini_get('safe_mode_allowed_env_vars'), 'GIT_ASKPASS')) {
40439 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');
40440 }
40441
40442
40443  if (getenv('GIT_ASKPASS') !== 'echo') {
40444 putenv('GIT_ASKPASS=echo');
40445 unset($_SERVER['GIT_ASKPASS']);
40446 }
40447
40448
40449  if (getenv('GIT_DIR')) {
40450 putenv('GIT_DIR');
40451 unset($_SERVER['GIT_DIR']);
40452 }
40453 if (getenv('GIT_WORK_TREE')) {
40454 putenv('GIT_WORK_TREE');
40455 unset($_SERVER['GIT_WORK_TREE']);
40456 }
40457
40458
40459  if (getenv('LANGUAGE') !== 'C') {
40460 putenv('LANGUAGE=C');
40461 }
40462
40463
40464  putenv("DYLD_LIBRARY_PATH");
40465 unset($_SERVER['DYLD_LIBRARY_PATH']);
40466 }
40467
40468 public static function getGitHubDomainsRegex(Config $config)
40469 {
40470 return '(' . implode('|', array_map('preg_quote', $config->get('github-domains'))) . ')';
40471 }
40472
40473 public static function sanitizeUrl($message)
40474 {
40475 return preg_replace_callback('{://(?P<user>[^@]+?):(?P<password>.+?)@}', function ($m) {
40476 if (preg_match('{^[a-f0-9]{12,}$}', $m[1])) {
40477 return '://***:***@';
40478 }
40479
40480 return '://' . $m[1] . ':***@';
40481 }, $message);
40482 }
40483
40484 private function throwException($message, $url)
40485 {
40486
40487  clearstatcache();
40488
40489 if (0 !== $this->process->execute('git --version', $ignoredOutput)) {
40490 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()));
40491 }
40492
40493 throw new \RuntimeException(self::sanitizeUrl($message));
40494 }
40495
40496
40497
40498
40499
40500
40501 public function getVersion()
40502 {
40503 if (isset(self::$version)) {
40504 return self::$version;
40505 }
40506 if (0 !== $this->process->execute('git --version', $output)) {
40507 return;
40508 }
40509 if (preg_match('/^git version (\d+(?:\.\d+)+)/m', $output, $matches)) {
40510 return self::$version = $matches[1];
40511 }
40512 }
40513 }
40514 <?php
40515
40516
40517
40518
40519
40520
40521
40522
40523
40524
40525
40526 namespace Composer\Util;
40527
40528 use Composer\Factory;
40529 use Composer\IO\IOInterface;
40530 use Composer\Config;
40531 use Composer\Downloader\TransportException;
40532
40533
40534
40535
40536 class GitHub
40537 {
40538 protected $io;
40539 protected $config;
40540 protected $process;
40541 protected $remoteFilesystem;
40542
40543
40544
40545
40546
40547
40548
40549
40550
40551 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
40552 {
40553 $this->io = $io;
40554 $this->config = $config;
40555 $this->process = $process ?: new ProcessExecutor;
40556 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
40557 }
40558
40559
40560
40561
40562
40563
40564
40565 public function authorizeOAuth($originUrl)
40566 {
40567 if (!in_array($originUrl, $this->config->get('github-domains'))) {
40568 return false;
40569 }
40570
40571
40572  if (0 === $this->process->execute('git config github.accesstoken', $output)) {
40573 $this->io->setAuthentication($originUrl, trim($output), 'x-oauth-basic');
40574
40575 return true;
40576 }
40577
40578 return false;
40579 }
40580
40581
40582
40583
40584
40585
40586
40587
40588
40589
40590 public function authorizeOAuthInteractively($originUrl, $message = null)
40591 {
40592 if ($message) {
40593 $this->io->writeError($message);
40594 }
40595
40596 $note = 'Composer';
40597 if ($this->config->get('github-expose-hostname') === true && 0 === $this->process->execute('hostname', $output)) {
40598 $note .= ' on ' . trim($output);
40599 }
40600 $note .= ' ' . date('Y-m-d Hi');
40601
40602 $url = 'https://'.$originUrl.'/settings/tokens/new?scopes=repo&description=' . str_replace('%20', '+', rawurlencode($note));
40603 $this->io->writeError(sprintf('Head to %s', $url));
40604 $this->io->writeError(sprintf('to retrieve a token. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
40605
40606 $token = trim($this->io->askAndHideAnswer('Token (hidden): '));
40607
40608 if (!$token) {
40609 $this->io->writeError('<warning>No token given, aborting.</warning>');
40610 $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com <token>"');
40611
40612 return false;
40613 }
40614
40615 $this->io->setAuthentication($originUrl, $token, 'x-oauth-basic');
40616
40617 try {
40618 $apiUrl = ('github.com' === $originUrl) ? 'api.github.com/' : $originUrl . '/api/v3/';
40619
40620 $this->remoteFilesystem->getContents($originUrl, 'https://'. $apiUrl, false, array(
40621 'retry-auth-failure' => false,
40622 ));
40623 } catch (TransportException $e) {
40624 if (in_array($e->getCode(), array(403, 401))) {
40625 $this->io->writeError('<error>Invalid token provided.</error>');
40626 $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com <token>"');
40627
40628 return false;
40629 }
40630
40631 throw $e;
40632 }
40633
40634
40635  $this->config->getConfigSource()->removeConfigSetting('github-oauth.'.$originUrl);
40636 $this->config->getAuthConfigSource()->addConfigSetting('github-oauth.'.$originUrl, $token);
40637
40638 $this->io->writeError('<info>Token stored successfully.</info>');
40639
40640 return true;
40641 }
40642 }
40643 <?php
40644
40645
40646
40647
40648
40649
40650
40651
40652
40653
40654
40655 namespace Composer\Util;
40656
40657 use Composer\IO\IOInterface;
40658 use Composer\Config;
40659 use Composer\Factory;
40660 use Composer\Downloader\TransportException;
40661 use Composer\Json\JsonFile;
40662
40663
40664
40665
40666 class GitLab
40667 {
40668 protected $io;
40669 protected $config;
40670 protected $process;
40671 protected $remoteFilesystem;
40672
40673
40674
40675
40676
40677
40678
40679
40680
40681 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
40682 {
40683 $this->io = $io;
40684 $this->config = $config;
40685 $this->process = $process ?: new ProcessExecutor();
40686 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
40687 }
40688
40689
40690
40691
40692
40693
40694
40695
40696 public function authorizeOAuth($originUrl)
40697 {
40698 if (!in_array($originUrl, $this->config->get('gitlab-domains'), true)) {
40699 return false;
40700 }
40701
40702
40703  if (0 === $this->process->execute('git config gitlab.accesstoken', $output)) {
40704 $this->io->setAuthentication($originUrl, trim($output), 'oauth2');
40705
40706 return true;
40707 }
40708
40709
40710  $authTokens = $this->config->get('gitlab-token');
40711
40712 if (isset($authTokens[$originUrl])) {
40713 $this->io->setAuthentication($originUrl, $authTokens[$originUrl], 'private-token');
40714
40715 return true;
40716 }
40717
40718 return false;
40719 }
40720
40721
40722
40723
40724
40725
40726
40727
40728
40729
40730
40731
40732
40733 public function authorizeOAuthInteractively($scheme, $originUrl, $message = null)
40734 {
40735 if ($message) {
40736 $this->io->writeError($message);
40737 }
40738
40739 $this->io->writeError(sprintf('A token will be created and stored in "%s", your password will never be stored', $this->config->getAuthConfigSource()->getName()));
40740 $this->io->writeError('To revoke access to this token you can visit '.$originUrl.'/profile/applications');
40741
40742 $attemptCounter = 0;
40743
40744 while ($attemptCounter++ < 5) {
40745 try {
40746 $response = $this->createToken($scheme, $originUrl);
40747 } catch (TransportException $e) {
40748
40749  
40750  if (in_array($e->getCode(), array(403, 401))) {
40751 if (401 === $e->getCode()) {
40752 $this->io->writeError('Bad credentials.');
40753 } else {
40754 $this->io->writeError('Maximum number of login attempts exceeded. Please try again later.');
40755 }
40756
40757 $this->io->writeError('You can also manually create a personal token at '.$scheme.'://'.$originUrl.'/profile/personal_access_tokens');
40758 $this->io->writeError('Add it using "composer config --global --auth gitlab-token.'.$originUrl.' <token>"');
40759
40760 continue;
40761 }
40762
40763 throw $e;
40764 }
40765
40766 $this->io->setAuthentication($originUrl, $response['access_token'], 'oauth2');
40767
40768
40769  $this->config->getAuthConfigSource()->addConfigSetting('gitlab-oauth.'.$originUrl, $response['access_token']);
40770
40771 return true;
40772 }
40773
40774 throw new \RuntimeException('Invalid GitLab credentials 5 times in a row, aborting.');
40775 }
40776
40777 private function createToken($scheme, $originUrl)
40778 {
40779 $username = $this->io->ask('Username: ');
40780 $password = $this->io->askAndHideAnswer('Password: ');
40781
40782 $headers = array('Content-Type: application/x-www-form-urlencoded');
40783
40784 $apiUrl = $originUrl;
40785 $data = http_build_query(array(
40786 'username' => $username,
40787 'password' => $password,
40788 'grant_type' => 'password',
40789 ), null, '&');
40790 $options = array(
40791 'retry-auth-failure' => false,
40792 'http' => array(
40793 'method' => 'POST',
40794 'header' => $headers,
40795 'content' => $data,
40796 ),
40797 );
40798
40799 $json = $this->remoteFilesystem->getContents($originUrl, $scheme.'://'.$apiUrl.'/oauth/token', false, $options);
40800
40801 $this->io->writeError('Token successfully created');
40802
40803 return JsonFile::parseJson($json);
40804 }
40805 }
40806 <?php
40807
40808
40809
40810
40811
40812
40813
40814
40815
40816
40817
40818 namespace Composer\Util;
40819
40820
40821
40822
40823
40824
40825
40826
40827 class IniHelper
40828 {
40829 const ENV_ORIGINAL = 'COMPOSER_ORIGINAL_INIS';
40830
40831
40832
40833
40834
40835
40836
40837
40838
40839 public static function getAll()
40840 {
40841 $env = getenv(self::ENV_ORIGINAL);
40842
40843 if (false !== $env) {
40844 return explode(PATH_SEPARATOR, $env);
40845 }
40846
40847 $paths = array(strval(php_ini_loaded_file()));
40848
40849 if ($scanned = php_ini_scanned_files()) {
40850 $paths = array_merge($paths, array_map('trim', explode(',', $scanned)));
40851 }
40852
40853 return $paths;
40854 }
40855
40856
40857
40858
40859
40860
40861 public static function getMessage()
40862 {
40863 $paths = self::getAll();
40864
40865 if (empty($paths[0])) {
40866 array_shift($paths);
40867 }
40868
40869 $ini = array_shift($paths);
40870
40871 if (empty($ini)) {
40872 return 'A php.ini file does not exist. You will have to create one.';
40873 }
40874
40875 if (!empty($paths)) {
40876 return 'Your command-line PHP is using multiple ini files. Run `php --ini` to show them.';
40877 }
40878
40879 return 'The php.ini used by your command-line PHP is: '.$ini;
40880 }
40881 }
40882 <?php
40883
40884
40885
40886
40887
40888
40889
40890
40891
40892
40893
40894 namespace Composer\Util;
40895
40896
40897
40898
40899 class NoProxyPattern
40900 {
40901
40902
40903
40904 protected $rules = array();
40905
40906
40907
40908
40909 public function __construct($pattern)
40910 {
40911 $this->rules = preg_split("/[\s,]+/", $pattern);
40912 }
40913
40914
40915
40916
40917
40918
40919
40920
40921 public function test($url)
40922 {
40923 $host = parse_url($url, PHP_URL_HOST);
40924 $port = parse_url($url, PHP_URL_PORT);
40925
40926 if (empty($port)) {
40927 switch (parse_url($url, PHP_URL_SCHEME)) {
40928 case 'http':
40929 $port = 80;
40930 break;
40931 case 'https':
40932 $port = 443;
40933 break;
40934 }
40935 }
40936
40937 foreach ($this->rules as $rule) {
40938 if ($rule == '*') {
40939 return true;
40940 }
40941
40942 $match = false;
40943
40944 list($ruleHost) = explode(':', $rule);
40945 list($base) = explode('/', $ruleHost);
40946
40947 if (filter_var($base, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
40948
40949
40950 if (!isset($ip)) {
40951 $ip = gethostbyname($host);
40952 }
40953
40954 if (strpos($ruleHost, '/') === false) {
40955 $match = $ip === $ruleHost;
40956 } else {
40957
40958  
40959  if ($ip === $host) {
40960 $match = false;
40961 } else {
40962
40963  $match = self::inCIDRBlock($ruleHost, $ip);
40964 }
40965 }
40966 } else {
40967
40968
40969 $haystack = '.' . trim($host, '.') . '.';
40970 $needle = '.'. trim($ruleHost, '.') .'.';
40971 $match = stripos(strrev($haystack), strrev($needle)) === 0;
40972 }
40973
40974
40975  if ($match && strpos($rule, ':') !== false) {
40976 list(, $rulePort) = explode(':', $rule);
40977 if (!empty($rulePort) && $port != $rulePort) {
40978 $match = false;
40979 }
40980 }
40981
40982 if ($match) {
40983 return true;
40984 }
40985 }
40986
40987 return false;
40988 }
40989
40990
40991
40992
40993
40994
40995
40996
40997
40998
40999
41000 private static function inCIDRBlock($cidr, $ip)
41001 {
41002
41003  list($base, $bits) = explode('/', $cidr);
41004
41005
41006  list($a, $b, $c, $d) = explode('.', $base);
41007
41008
41009  $i = ($a << 24) + ($b << 16) + ($c << 8) + $d;
41010 $mask = $bits == 0 ? 0 : (~0 << (32 - $bits));
41011
41012
41013  $low = $i & $mask;
41014
41015
41016  $high = $i | (~$mask & 0xFFFFFFFF);
41017
41018
41019  list($a, $b, $c, $d) = explode('.', $ip);
41020
41021
41022  $check = ($a << 24) + ($b << 16) + ($c << 8) + $d;
41023
41024
41025  
41026  return $check >= $low && $check <= $high;
41027 }
41028 }
41029 <?php
41030
41031
41032
41033
41034
41035
41036
41037
41038
41039
41040
41041 namespace Composer\Util;
41042
41043 use Composer\IO\IOInterface;
41044 use Symfony\Component\Process\Process;
41045
41046
41047
41048
41049 class Perforce
41050 {
41051 protected $path;
41052 protected $p4Depot;
41053 protected $p4Client;
41054 protected $p4User;
41055 protected $p4Password;
41056 protected $p4Port;
41057 protected $p4Stream;
41058 protected $p4ClientSpec;
41059 protected $p4DepotType;
41060 protected $p4Branch;
41061 protected $process;
41062 protected $uniquePerforceClientName;
41063 protected $windowsFlag;
41064 protected $commandResult;
41065
41066 protected $io;
41067
41068 protected $filesystem;
41069
41070 public function __construct($repoConfig, $port, $path, ProcessExecutor $process, $isWindows, IOInterface $io)
41071 {
41072 $this->windowsFlag = $isWindows;
41073 $this->p4Port = $port;
41074 $this->initializePath($path);
41075 $this->process = $process;
41076 $this->initialize($repoConfig);
41077 $this->io = $io;
41078 }
41079
41080 public static function create($repoConfig, $port, $path, ProcessExecutor $process, IOInterface $io)
41081 {
41082 return new Perforce($repoConfig, $port, $path, $process, Platform::isWindows(), $io);
41083 }
41084
41085 public static function checkServerExists($url, ProcessExecutor $processExecutor)
41086 {
41087 $output = null;
41088
41089 return 0 === $processExecutor->execute('p4 -p ' . $url . ' info -s', $output);
41090 }
41091
41092 public function initialize($repoConfig)
41093 {
41094 $this->uniquePerforceClientName = $this->generateUniquePerforceClientName();
41095 if (!$repoConfig) {
41096 return;
41097 }
41098 if (isset($repoConfig['unique_perforce_client_name'])) {
41099 $this->uniquePerforceClientName = $repoConfig['unique_perforce_client_name'];
41100 }
41101
41102 if (isset($repoConfig['depot'])) {
41103 $this->p4Depot = $repoConfig['depot'];
41104 }
41105 if (isset($repoConfig['branch'])) {
41106 $this->p4Branch = $repoConfig['branch'];
41107 }
41108 if (isset($repoConfig['p4user'])) {
41109 $this->p4User = $repoConfig['p4user'];
41110 } else {
41111 $this->p4User = $this->getP4variable('P4USER');
41112 }
41113 if (isset($repoConfig['p4password'])) {
41114 $this->p4Password = $repoConfig['p4password'];
41115 }
41116 }
41117
41118 public function initializeDepotAndBranch($depot, $branch)
41119 {
41120 if (isset($depot)) {
41121 $this->p4Depot = $depot;
41122 }
41123 if (isset($branch)) {
41124 $this->p4Branch = $branch;
41125 }
41126 }
41127
41128 public function generateUniquePerforceClientName()
41129 {
41130 return gethostname() . "_" . time();
41131 }
41132
41133 public function cleanupClientSpec()
41134 {
41135 $client = $this->getClient();
41136 $task = 'client -d ' . $client;
41137 $useP4Client = false;
41138 $command = $this->generateP4Command($task, $useP4Client);
41139 $this->executeCommand($command);
41140 $clientSpec = $this->getP4ClientSpec();
41141 $fileSystem = $this->getFilesystem();
41142 $fileSystem->remove($clientSpec);
41143 }
41144
41145 protected function executeCommand($command)
41146 {
41147 $this->commandResult = "";
41148 $exit_code = $this->process->execute($command, $this->commandResult);
41149
41150 return $exit_code;
41151 }
41152
41153 public function getClient()
41154 {
41155 if (!isset($this->p4Client)) {
41156 $cleanStreamName = str_replace('@', '', str_replace('/', '_', str_replace('//', '', $this->getStream())));
41157 $this->p4Client = 'composer_perforce_' . $this->uniquePerforceClientName . '_' . $cleanStreamName;
41158 }
41159
41160 return $this->p4Client;
41161 }
41162
41163 protected function getPath()
41164 {
41165 return $this->path;
41166 }
41167
41168 public function initializePath($path)
41169 {
41170 $this->path = $path;
41171 $fs = $this->getFilesystem();
41172 $fs->ensureDirectoryExists($path);
41173 }
41174
41175 protected function getPort()
41176 {
41177 return $this->p4Port;
41178 }
41179
41180 public function setStream($stream)
41181 {
41182 $this->p4Stream = $stream;
41183 $index = strrpos($stream, '/');
41184
41185  if ($index > 2) {
41186 $this->p4DepotType = 'stream';
41187 }
41188 }
41189
41190 public function isStream()
41191 {
41192 return (strcmp($this->p4DepotType, 'stream') === 0);
41193 }
41194
41195 public function getStream()
41196 {
41197 if (!isset($this->p4Stream)) {
41198 if ($this->isStream()) {
41199 $this->p4Stream = '//' . $this->p4Depot . '/' . $this->p4Branch;
41200 } else {
41201 $this->p4Stream = '//' . $this->p4Depot;
41202 }
41203 }
41204
41205 return $this->p4Stream;
41206 }
41207
41208 public function getStreamWithoutLabel($stream)
41209 {
41210 $index = strpos($stream, '@');
41211 if ($index === false) {
41212 return $stream;
41213 }
41214
41215 return substr($stream, 0, $index);
41216 }
41217
41218 public function getP4ClientSpec()
41219 {
41220 $p4clientSpec = $this->path . '/' . $this->getClient() . '.p4.spec';
41221
41222 return $p4clientSpec;
41223 }
41224
41225 public function getUser()
41226 {
41227 return $this->p4User;
41228 }
41229
41230 public function setUser($user)
41231 {
41232 $this->p4User = $user;
41233 }
41234
41235 public function queryP4User()
41236 {
41237 $this->getUser();
41238 if (strlen($this->p4User) > 0) {
41239 return;
41240 }
41241 $this->p4User = $this->getP4variable('P4USER');
41242 if (strlen($this->p4User) > 0) {
41243 return;
41244 }
41245 $this->p4User = $this->io->ask('Enter P4 User:');
41246 if ($this->windowsFlag) {
41247 $command = 'p4 set P4USER=' . $this->p4User;
41248 } else {
41249 $command = 'export P4USER=' . $this->p4User;
41250 }
41251 $this->executeCommand($command);
41252 }
41253
41254 protected function getP4variable($name)
41255 {
41256 if ($this->windowsFlag) {
41257 $command = 'p4 set';
41258 $this->executeCommand($command);
41259 $result = trim($this->commandResult);
41260 $resArray = explode(PHP_EOL, $result);
41261 foreach ($resArray as $line) {
41262 $fields = explode('=', $line);
41263 if (strcmp($name, $fields[0]) == 0) {
41264 $index = strpos($fields[1], ' ');
41265 if ($index === false) {
41266 $value = $fields[1];
41267 } else {
41268 $value = substr($fields[1], 0, $index);
41269 }
41270 $value = trim($value);
41271
41272 return $value;
41273 }
41274 }
41275
41276 return null;
41277 } else {
41278 $command = 'echo $' . $name;
41279 $this->executeCommand($command);
41280 $result = trim($this->commandResult);
41281
41282 return $result;
41283 }
41284 }
41285
41286 public function queryP4Password()
41287 {
41288 if (isset($this->p4Password)) {
41289 return $this->p4Password;
41290 }
41291 $password = $this->getP4variable('P4PASSWD');
41292 if (strlen($password) <= 0) {
41293 $password = $this->io->askAndHideAnswer('Enter password for Perforce user ' . $this->getUser() . ': ');
41294 }
41295 $this->p4Password = $password;
41296
41297 return $password;
41298 }
41299
41300 public function generateP4Command($command, $useClient = true)
41301 {
41302 $p4Command = 'p4 ';
41303 $p4Command = $p4Command . '-u ' . $this->getUser() . ' ';
41304 if ($useClient) {
41305 $p4Command = $p4Command . '-c ' . $this->getClient() . ' ';
41306 }
41307 $p4Command = $p4Command . '-p ' . $this->getPort() . ' ';
41308 $p4Command = $p4Command . $command;
41309
41310 return $p4Command;
41311 }
41312
41313 public function isLoggedIn()
41314 {
41315 $command = $this->generateP4Command('login -s', false);
41316 $exitCode = $this->executeCommand($command);
41317 if ($exitCode) {
41318 $errorOutput = $this->process->getErrorOutput();
41319 $index = strpos($errorOutput, $this->getUser());
41320 if ($index === false) {
41321 $index = strpos($errorOutput, 'p4');
41322 if ($index === false) {
41323 return false;
41324 }
41325 throw new \Exception('p4 command not found in path: ' . $errorOutput);
41326 }
41327 throw new \Exception('Invalid user name: ' . $this->getUser());
41328 }
41329
41330 return true;
41331 }
41332
41333 public function connectClient()
41334 {
41335 $p4CreateClientCommand = $this->generateP4Command(
41336 'client -i < ' . str_replace(" ", "\\ ", $this->getP4ClientSpec())
41337 );
41338 $this->executeCommand($p4CreateClientCommand);
41339 }
41340
41341 public function syncCodeBase($sourceReference)
41342 {
41343 $prevDir = getcwd();
41344 chdir($this->path);
41345 $p4SyncCommand = $this->generateP4Command('sync -f ');
41346 if (null !== $sourceReference) {
41347 $p4SyncCommand = $p4SyncCommand . '@' . $sourceReference;
41348 }
41349 $this->executeCommand($p4SyncCommand);
41350 chdir($prevDir);
41351 }
41352
41353 public function writeClientSpecToFile($spec)
41354 {
41355 fwrite($spec, 'Client: ' . $this->getClient() . PHP_EOL . PHP_EOL);
41356 fwrite($spec, 'Update: ' . date('Y/m/d H:i:s') . PHP_EOL . PHP_EOL);
41357 fwrite($spec, 'Access: ' . date('Y/m/d H:i:s') . PHP_EOL);
41358 fwrite($spec, 'Owner:  ' . $this->getUser() . PHP_EOL . PHP_EOL);
41359 fwrite($spec, 'Description:' . PHP_EOL);
41360 fwrite($spec, '  Created by ' . $this->getUser() . ' from composer.' . PHP_EOL . PHP_EOL);
41361 fwrite($spec, 'Root: ' . $this->getPath() . PHP_EOL . PHP_EOL);
41362 fwrite($spec, 'Options:  noallwrite noclobber nocompress unlocked modtime rmdir' . PHP_EOL . PHP_EOL);
41363 fwrite($spec, 'SubmitOptions:  revertunchanged' . PHP_EOL . PHP_EOL);
41364 fwrite($spec, 'LineEnd:  local' . PHP_EOL . PHP_EOL);
41365 if ($this->isStream()) {
41366 fwrite($spec, 'Stream:' . PHP_EOL);
41367 fwrite($spec, '  ' . $this->getStreamWithoutLabel($this->p4Stream) . PHP_EOL);
41368 } else {
41369 fwrite(
41370 $spec,
41371 'View:  ' . $this->getStream() . '/...  //' . $this->getClient() . '/... ' . PHP_EOL
41372 );
41373 }
41374 }
41375
41376 public function writeP4ClientSpec()
41377 {
41378 $clientSpec = $this->getP4ClientSpec();
41379 $spec = fopen($clientSpec, 'w');
41380 try {
41381 $this->writeClientSpecToFile($spec);
41382 } catch (\Exception $e) {
41383 fclose($spec);
41384 throw $e;
41385 }
41386 fclose($spec);
41387 }
41388
41389 protected function read($pipe, $name)
41390 {
41391 if (feof($pipe)) {
41392 return;
41393 }
41394 $line = fgets($pipe);
41395 while ($line !== false) {
41396 $line = fgets($pipe);
41397 }
41398
41399 return;
41400 }
41401
41402 public function windowsLogin($password)
41403 {
41404 $command = $this->generateP4Command(' login -a');
41405 $process = new Process($command, null, null, $password);
41406
41407 return $process->run();
41408 }
41409
41410 public function p4Login()
41411 {
41412 $this->queryP4User();
41413 if (!$this->isLoggedIn()) {
41414 $password = $this->queryP4Password();
41415 if ($this->windowsFlag) {
41416 $this->windowsLogin($password);
41417 } else {
41418 $command = 'echo ' . $password . ' | ' . $this->generateP4Command(' login -a', false);
41419 $exitCode = $this->executeCommand($command);
41420 $result = trim($this->commandResult);
41421 if ($exitCode) {
41422 throw new \Exception("Error logging in:" . $this->process->getErrorOutput());
41423 }
41424 }
41425 }
41426 }
41427
41428 public function getComposerInformation($identifier)
41429 {
41430 $composerFileContent = $this->getFileContent('composer.json', $identifier);
41431
41432 if (!$composerFileContent) {
41433 return;
41434 }
41435
41436 return json_decode($composerFileContent, true);
41437 }
41438
41439 public function getFileContent($file, $identifier)
41440 {
41441 $path = $this->getFilePath($file, $identifier);
41442
41443 $command = $this->generateP4Command(' print ' . $path);
41444 $this->executeCommand($command);
41445 $result = $this->commandResult;
41446
41447 if (!trim($result)) {
41448 return null;
41449 }
41450
41451 return $result;
41452 }
41453
41454 public function getFilePath($file, $identifier)
41455 {
41456 $index = strpos($identifier, '@');
41457 if ($index === false) {
41458 $path = $identifier. '/' . $file;
41459
41460 return $path;
41461 } else {
41462 $path = substr($identifier, 0, $index) . '/' . $file . substr($identifier, $index);
41463 $command = $this->generateP4Command(' files ' . $path, false);
41464 $this->executeCommand($command);
41465 $result = $this->commandResult;
41466 $index2 = strpos($result, 'no such file(s).');
41467 if ($index2 === false) {
41468 $index3 = strpos($result, 'change');
41469 if ($index3 !== false) {
41470 $phrase = trim(substr($result, $index3));
41471 $fields = explode(' ', $phrase);
41472
41473 return substr($identifier, 0, $index) . '/' . $file . '@' . $fields[1];
41474 }
41475 }
41476 }
41477
41478 return null;
41479 }
41480
41481 public function getBranches()
41482 {
41483 $possibleBranches = array();
41484 if (!$this->isStream()) {
41485 $possibleBranches[$this->p4Branch] = $this->getStream();
41486 } else {
41487 $command = $this->generateP4Command('streams //' . $this->p4Depot . '/...');
41488 $this->executeCommand($command);
41489 $result = $this->commandResult;
41490 $resArray = explode(PHP_EOL, $result);
41491 foreach ($resArray as $line) {
41492 $resBits = explode(' ', $line);
41493 if (count($resBits) > 4) {
41494 $branch = preg_replace('/[^A-Za-z0-9 ]/', '', $resBits[4]);
41495 $possibleBranches[$branch] = $resBits[1];
41496 }
41497 }
41498 }
41499 $command = $this->generateP4Command('changes '. $this->getStream() . '/...', false);
41500 $this->executeCommand($command);
41501 $result = $this->commandResult;
41502 $resArray = explode(PHP_EOL, $result);
41503 $lastCommit = $resArray[0];
41504 $lastCommitArr = explode(' ', $lastCommit);
41505 $lastCommitNum = $lastCommitArr[1];
41506
41507 $branches = array('master' => $possibleBranches[$this->p4Branch] . '@'. $lastCommitNum);
41508
41509 return $branches;
41510 }
41511
41512 public function getTags()
41513 {
41514 $command = $this->generateP4Command('labels');
41515 $this->executeCommand($command);
41516 $result = $this->commandResult;
41517 $resArray = explode(PHP_EOL, $result);
41518 $tags = array();
41519 foreach ($resArray as $line) {
41520 $index = strpos($line, 'Label');
41521 if (!($index === false)) {
41522 $fields = explode(' ', $line);
41523 $tags[$fields[1]] = $this->getStream() . '@' . $fields[1];
41524 }
41525 }
41526
41527 return $tags;
41528 }
41529
41530 public function checkStream()
41531 {
41532 $command = $this->generateP4Command('depots', false);
41533 $this->executeCommand($command);
41534 $result = $this->commandResult;
41535 $resArray = explode(PHP_EOL, $result);
41536 foreach ($resArray as $line) {
41537 $index = strpos($line, 'Depot');
41538 if (!($index === false)) {
41539 $fields = explode(' ', $line);
41540 if (strcmp($this->p4Depot, $fields[1]) === 0) {
41541 $this->p4DepotType = $fields[3];
41542
41543 return $this->isStream();
41544 }
41545 }
41546 }
41547
41548 return false;
41549 }
41550
41551
41552
41553
41554
41555 protected function getChangeList($reference)
41556 {
41557 $index = strpos($reference, '@');
41558 if ($index === false) {
41559 return null;
41560 }
41561 $label = substr($reference, $index);
41562 $command = $this->generateP4Command(' changes -m1 ' . $label);
41563 $this->executeCommand($command);
41564 $changes = $this->commandResult;
41565 if (strpos($changes, 'Change') !== 0) {
41566 return null;
41567 }
41568 $fields = explode(' ', $changes);
41569 $changeList = $fields[1];
41570
41571 return $changeList;
41572 }
41573
41574
41575
41576
41577
41578
41579 public function getCommitLogs($fromReference, $toReference)
41580 {
41581 $fromChangeList = $this->getChangeList($fromReference);
41582 if ($fromChangeList === null) {
41583 return null;
41584 }
41585 $toChangeList = $this->getChangeList($toReference);
41586 if ($toChangeList === null) {
41587 return null;
41588 }
41589 $index = strpos($fromReference, '@');
41590 $main = substr($fromReference, 0, $index) . '/...';
41591 $command = $this->generateP4Command('filelog ' . $main . '@' . $fromChangeList. ',' . $toChangeList);
41592 $this->executeCommand($command);
41593 $result = $this->commandResult;
41594
41595 return $result;
41596 }
41597
41598 public function getFilesystem()
41599 {
41600 if (empty($this->filesystem)) {
41601 $this->filesystem = new Filesystem($this->process);
41602 }
41603
41604 return $this->filesystem;
41605 }
41606
41607 public function setFilesystem(Filesystem $fs)
41608 {
41609 $this->filesystem = $fs;
41610 }
41611 }
41612 <?php
41613
41614
41615
41616
41617
41618
41619
41620
41621
41622
41623
41624 namespace Composer\Util;
41625
41626
41627
41628
41629
41630
41631 class Platform
41632 {
41633
41634
41635
41636
41637
41638
41639 public static function expandPath($path)
41640 {
41641 if (preg_match('#^~[\\/]#', $path)) {
41642 return self::getUserDirectory() . substr($path, 1);
41643 }
41644
41645 return preg_replace_callback('#^(\$|(?P<percent>%))(?P<var>\w++)(?(percent)%)(?P<path>.*)#', function ($matches) {
41646
41647  if (Platform::isWindows() && $matches['var'] == 'HOME') {
41648 return (getenv('HOME') ?: getenv('USERPROFILE')) . $matches['path'];
41649 }
41650
41651 return getenv($matches['var']) . $matches['path'];
41652 }, $path);
41653 }
41654
41655
41656
41657
41658
41659 public static function getUserDirectory()
41660 {
41661 if (false !== ($home = getenv('HOME'))) {
41662 return $home;
41663 }
41664
41665 if (self::isWindows() && false !== ($home = getenv('USERPROFILE'))) {
41666 return $home;
41667 }
41668
41669 if (function_exists('posix_getuid') && function_exists('posix_getpwuid')) {
41670 $info = posix_getpwuid(posix_getuid());
41671
41672 return $info['dir'];
41673 }
41674
41675 throw new \RuntimeException('Could not determine user directory');
41676 }
41677
41678
41679
41680
41681 public static function isWindows()
41682 {
41683 return defined('PHP_WINDOWS_VERSION_BUILD');
41684 }
41685
41686
41687
41688
41689
41690 public static function strlen($str)
41691 {
41692 static $useMbString = null;
41693 if (null === $useMbString) {
41694 $useMbString = function_exists('mb_strlen') && ini_get('mbstring.func_overload');
41695 }
41696
41697 if ($useMbString) {
41698 return mb_strlen($str, '8bit');
41699 }
41700
41701 return strlen($str);
41702 }
41703 }
41704 <?php
41705
41706
41707
41708
41709
41710
41711
41712
41713
41714
41715
41716 namespace Composer\Util;
41717
41718 use Symfony\Component\Process\Process;
41719 use Symfony\Component\Process\ProcessUtils;
41720 use Composer\IO\IOInterface;
41721
41722
41723
41724
41725 class ProcessExecutor
41726 {
41727 protected static $timeout = 300;
41728
41729 protected $captureOutput;
41730 protected $errorOutput;
41731 protected $io;
41732
41733 public function __construct(IOInterface $io = null)
41734 {
41735 $this->io = $io;
41736 }
41737
41738
41739
41740
41741
41742
41743
41744
41745
41746
41747 public function execute($command, &$output = null, $cwd = null)
41748 {
41749 if ($this->io && $this->io->isDebug()) {
41750 $safeCommand = preg_replace_callback('{://(?P<user>[^:/\s]+):(?P<password>[^@\s/]+)@}i', function ($m) {
41751 if (preg_match('{^[a-f0-9]{12,}$}', $m['user'])) {
41752 return '://***:***@';
41753 }
41754
41755 return '://'.$m['user'].':***@';
41756 }, $command);
41757 $this->io->writeError('Executing command ('.($cwd ?: 'CWD').'): '.$safeCommand);
41758 }
41759
41760
41761  
41762  if (null === $cwd && Platform::isWindows() && false !== strpos($command, 'git') && getcwd()) {
41763 $cwd = realpath(getcwd());
41764 }
41765
41766 $this->captureOutput = count(func_get_args()) > 1;
41767 $this->errorOutput = null;
41768 $process = new Process($command, $cwd, null, null, static::getTimeout());
41769
41770 $callback = is_callable($output) ? $output : array($this, 'outputHandler');
41771 $process->run($callback);
41772
41773 if ($this->captureOutput && !is_callable($output)) {
41774 $output = $process->getOutput();
41775 }
41776
41777 $this->errorOutput = $process->getErrorOutput();
41778
41779 return $process->getExitCode();
41780 }
41781
41782 public function splitLines($output)
41783 {
41784 $output = trim($output);
41785
41786 return ((string) $output === '') ? array() : preg_split('{\r?\n}', $output);
41787 }
41788
41789
41790
41791
41792
41793
41794 public function getErrorOutput()
41795 {
41796 return $this->errorOutput;
41797 }
41798
41799 public function outputHandler($type, $buffer)
41800 {
41801 if ($this->captureOutput) {
41802 return;
41803 }
41804
41805 if (null === $this->io) {
41806 echo $buffer;
41807
41808 return;
41809 }
41810
41811 if (Process::ERR === $type) {
41812 $this->io->writeError($buffer, false);
41813 } else {
41814 $this->io->write($buffer, false);
41815 }
41816 }
41817
41818 public static function getTimeout()
41819 {
41820 return static::$timeout;
41821 }
41822
41823 public static function setTimeout($timeout)
41824 {
41825 static::$timeout = $timeout;
41826 }
41827
41828
41829
41830
41831
41832
41833
41834
41835 public static function escape($argument)
41836 {
41837 return ProcessUtils::escapeArgument($argument);
41838 }
41839 }
41840 <?php
41841
41842
41843
41844
41845
41846
41847
41848
41849
41850
41851
41852 namespace Composer\Util;
41853
41854 use Composer\Config;
41855 use Composer\IO\IOInterface;
41856 use Composer\Downloader\TransportException;
41857 use Composer\CaBundle\CaBundle;
41858 use Psr\Log\LoggerInterface;
41859
41860
41861
41862
41863
41864
41865 class RemoteFilesystem
41866 {
41867 private $io;
41868 private $config;
41869 private $scheme;
41870 private $bytesMax;
41871 private $originUrl;
41872 private $fileUrl;
41873 private $fileName;
41874 private $retry;
41875 private $progress;
41876 private $lastProgress;
41877 private $options = array();
41878 private $peerCertificateMap = array();
41879 private $disableTls = false;
41880 private $retryAuthFailure;
41881 private $lastHeaders;
41882 private $storeAuth;
41883 private $degradedMode = false;
41884 private $redirects;
41885 private $maxRedirects = 20;
41886
41887
41888
41889
41890
41891
41892
41893
41894
41895 public function __construct(IOInterface $io, Config $config = null, array $options = array(), $disableTls = false)
41896 {
41897 $this->io = $io;
41898
41899
41900  
41901  if ($disableTls === false) {
41902 $this->options = $this->getTlsDefaults($options);
41903 } else {
41904 $this->disableTls = true;
41905 }
41906
41907
41908  $this->options = array_replace_recursive($this->options, $options);
41909 $this->config = $config;
41910 }
41911
41912
41913
41914
41915
41916
41917
41918
41919
41920
41921
41922
41923 public function copy($originUrl, $fileUrl, $fileName, $progress = true, $options = array())
41924 {
41925 return $this->get($originUrl, $fileUrl, $options, $fileName, $progress);
41926 }
41927
41928
41929
41930
41931
41932
41933
41934
41935
41936
41937
41938 public function getContents($originUrl, $fileUrl, $progress = true, $options = array())
41939 {
41940 return $this->get($originUrl, $fileUrl, $options, null, $progress);
41941 }
41942
41943
41944
41945
41946
41947
41948 public function getOptions()
41949 {
41950 return $this->options;
41951 }
41952
41953
41954
41955
41956
41957
41958 public function setOptions(array $options)
41959 {
41960 $this->options = array_replace_recursive($this->options, $options);
41961 }
41962
41963 public function isTlsDisabled()
41964 {
41965 return $this->disableTls === true;
41966 }
41967
41968
41969
41970
41971
41972
41973 public function getLastHeaders()
41974 {
41975 return $this->lastHeaders;
41976 }
41977
41978
41979
41980
41981
41982
41983 public function findHeaderValue(array $headers, $name)
41984 {
41985 $value = null;
41986 foreach ($headers as $header) {
41987 if (preg_match('{^'.$name.':\s*(.+?)\s*$}i', $header, $match)) {
41988 $value = $match[1];
41989 } elseif (preg_match('{^HTTP/}i', $header)) {
41990
41991  
41992  $value = null;
41993 }
41994 }
41995
41996 return $value;
41997 }
41998
41999
42000
42001
42002
42003 public function findStatusCode(array $headers)
42004 {
42005 $value = null;
42006 foreach ($headers as $header) {
42007 if (preg_match('{^HTTP/\S+ (\d+)}i', $header, $match)) {
42008
42009  
42010  $value = (int) $match[1];
42011 }
42012 }
42013
42014 return $value;
42015 }
42016
42017
42018
42019
42020
42021
42022
42023
42024
42025
42026
42027
42028
42029
42030
42031 protected function get($originUrl, $fileUrl, $additionalOptions = array(), $fileName = null, $progress = true)
42032 {
42033 if (strpos($originUrl, '.github.com') === (strlen($originUrl) - 11)) {
42034 $originUrl = 'github.com';
42035 }
42036
42037
42038  
42039  if (
42040 $this->config
42041 && is_array($this->config->get('gitlab-domains'))
42042 && false === strpos($originUrl, '/')
42043 && !in_array($originUrl, $this->config->get('gitlab-domains'))
42044 ) {
42045 foreach ($this->config->get('gitlab-domains') as $gitlabDomain) {
42046 if (0 === strpos($gitlabDomain, $originUrl)) {
42047 $originUrl = $gitlabDomain;
42048 break;
42049 }
42050 }
42051 unset($gitlabDomain);
42052 }
42053
42054 $this->scheme = parse_url($fileUrl, PHP_URL_SCHEME);
42055 $this->bytesMax = 0;
42056 $this->originUrl = $originUrl;
42057 $this->fileUrl = $fileUrl;
42058 $this->fileName = $fileName;
42059 $this->progress = $progress;
42060 $this->lastProgress = null;
42061 $this->retryAuthFailure = true;
42062 $this->lastHeaders = array();
42063 $this->redirects = 1; 
42064
42065
42066  if (preg_match('{^https?://([^:/]+):([^@/]+)@([^/]+)}i', $fileUrl, $match)) {
42067 $this->io->setAuthentication($originUrl, urldecode($match[1]), urldecode($match[2]));
42068 }
42069
42070 $tempAdditionalOptions = $additionalOptions;
42071 if (isset($tempAdditionalOptions['retry-auth-failure'])) {
42072 $this->retryAuthFailure = (bool) $tempAdditionalOptions['retry-auth-failure'];
42073
42074 unset($tempAdditionalOptions['retry-auth-failure']);
42075 }
42076
42077 $isRedirect = false;
42078 if (isset($tempAdditionalOptions['redirects'])) {
42079 $this->redirects = $tempAdditionalOptions['redirects'];
42080 $isRedirect = true;
42081
42082 unset($tempAdditionalOptions['redirects']);
42083 }
42084
42085 $options = $this->getOptionsForUrl($originUrl, $tempAdditionalOptions);
42086 unset($tempAdditionalOptions);
42087
42088 $origFileUrl = $fileUrl;
42089
42090 if (isset($options['github-token'])) {
42091
42092  if (preg_match('{^https?://([a-z0-9-]+\.)*github\.com/}', $fileUrl)) {
42093 $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token='.$options['github-token'];
42094 }
42095 unset($options['github-token']);
42096 }
42097
42098 if (isset($options['gitlab-token'])) {
42099 $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token='.$options['gitlab-token'];
42100 unset($options['gitlab-token']);
42101 }
42102
42103 if (isset($options['http'])) {
42104 $options['http']['ignore_errors'] = true;
42105 }
42106
42107 if ($this->degradedMode && substr($fileUrl, 0, 21) === 'http://packagist.org/') {
42108
42109  $fileUrl = 'http://' . gethostbyname('packagist.org') . substr($fileUrl, 20);
42110 $degradedPackagist = true;
42111 }
42112
42113 $ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet')));
42114
42115 $actualContextOptions = stream_context_get_options($ctx);
42116 $usingProxy = !empty($actualContextOptions['http']['proxy']) ? ' using proxy ' . $actualContextOptions['http']['proxy'] : '';
42117 $this->io->writeError((substr($origFileUrl, 0, 4) === 'http' ? 'Downloading ' : 'Reading ') . $origFileUrl . $usingProxy, true, IOInterface::DEBUG);
42118 unset($origFileUrl, $actualContextOptions);
42119
42120
42121  if ((substr($fileUrl, 0, 23) !== 'http://packagist.org/p/' || (false === strpos($fileUrl, '$') && false === strpos($fileUrl, '%24'))) && empty($degradedPackagist) && $this->config) {
42122 $this->config->prohibitUrlByConfig($fileUrl, $this->io);
42123 }
42124
42125 if ($this->progress && !$isRedirect) {
42126 $this->io->writeError("Downloading (<comment>connecting...</comment>)", false);
42127 }
42128
42129 $errorMessage = '';
42130 $errorCode = 0;
42131 $result = false;
42132 set_error_handler(function ($code, $msg) use (&$errorMessage) {
42133 if ($errorMessage) {
42134 $errorMessage .= "\n";
42135 }
42136 $errorMessage .= preg_replace('{^file_get_contents\(.*?\): }', '', $msg);
42137 });
42138 try {
42139 $result = file_get_contents($fileUrl, false, $ctx);
42140
42141 $contentLength = !empty($http_response_header[0]) ? $this->findHeaderValue($http_response_header, 'content-length') : null;
42142 if ($contentLength && Platform::strlen($result) < $contentLength) {
42143
42144  $e = new TransportException('Content-Length mismatch, received '.Platform::strlen($result).' bytes out of the expected '.$contentLength);
42145 $e->setHeaders($http_response_header);
42146 $e->setStatusCode($this->findStatusCode($http_response_header));
42147 $e->setResponse($result);
42148 $this->io->writeError('Content-Length mismatch, received '.Platform::strlen($result).' out of '.$contentLength.' bytes: (' . base64_encode($result).')', true, IOInterface::DEBUG);
42149
42150 throw $e;
42151 }
42152
42153 if (PHP_VERSION_ID < 50600 && !empty($options['ssl']['peer_fingerprint'])) {
42154
42155  $params = stream_context_get_params($ctx);
42156 $expectedPeerFingerprint = $options['ssl']['peer_fingerprint'];
42157 $peerFingerprint = TlsHelper::getCertificateFingerprint($params['options']['ssl']['peer_certificate']);
42158
42159
42160  if ($expectedPeerFingerprint !== $peerFingerprint) {
42161 throw new TransportException('Peer fingerprint did not match');
42162 }
42163 }
42164 } catch (\Exception $e) {
42165 if ($e instanceof TransportException && !empty($http_response_header[0])) {
42166 $e->setHeaders($http_response_header);
42167 $e->setStatusCode($this->findStatusCode($http_response_header));
42168 }
42169 if ($e instanceof TransportException && $result !== false) {
42170 $e->setResponse($result);
42171 }
42172 $result = false;
42173 }
42174 if ($errorMessage && !ini_get('allow_url_fopen')) {
42175 $errorMessage = 'allow_url_fopen must be enabled in php.ini ('.$errorMessage.')';
42176 }
42177 restore_error_handler();
42178 if (isset($e) && !$this->retry) {
42179 if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
42180 $this->degradedMode = true;
42181 $this->io->writeError('');
42182 $this->io->writeError(array(
42183 '<error>'.$e->getMessage().'</error>',
42184 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
42185 ));
42186
42187 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
42188 }
42189
42190 throw $e;
42191 }
42192
42193 $statusCode = null;
42194 $contentType = null;
42195 if (!empty($http_response_header[0])) {
42196 $statusCode = $this->findStatusCode($http_response_header);
42197 $contentType = $this->findHeaderValue($http_response_header, 'content-type');
42198 }
42199
42200
42201  if ($originUrl === 'bitbucket.org'
42202 && !$this->isPublicBitBucketDownload($fileUrl)
42203 && substr($fileUrl, -4) === '.zip'
42204 && $contentType && preg_match('{^text/html\b}i', $contentType)
42205 ) {
42206 $result = false;
42207 if ($this->retryAuthFailure) {
42208 $this->promptAuthAndRetry(401);
42209 }
42210 }
42211
42212
42213  if ($statusCode === 404
42214 && $this->config && in_array($originUrl, $this->config->get('gitlab-domains'), true)
42215 && false !== strpos($fileUrl, 'archive.zip')
42216 ) {
42217 $result = false;
42218 if ($this->retryAuthFailure) {
42219 $this->promptAuthAndRetry(401);
42220 }
42221 }
42222
42223
42224  $hasFollowedRedirect = false;
42225 if ($statusCode >= 300 && $statusCode <= 399 && $statusCode !== 304 && $this->redirects < $this->maxRedirects) {
42226 $hasFollowedRedirect = true;
42227 $result = $this->handleRedirect($http_response_header, $additionalOptions, $result);
42228 }
42229
42230
42231  if ($statusCode && $statusCode >= 400 && $statusCode <= 599) {
42232 if (!$this->retry) {
42233 if ($this->progress && !$this->retry && !$isRedirect) {
42234 $this->io->overwriteError("Downloading (<error>failed</error>)", false);
42235 }
42236
42237 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded ('.$http_response_header[0].')', $statusCode);
42238 $e->setHeaders($http_response_header);
42239 $e->setResponse($result);
42240 $e->setStatusCode($statusCode);
42241 throw $e;
42242 }
42243 $result = false;
42244 }
42245
42246 if ($this->progress && !$this->retry && !$isRedirect) {
42247 $this->io->overwriteError("Downloading (".($result === false ? '<error>failed</error>' : '<comment>100%</comment>').")", false);
42248 }
42249
42250
42251  if ($result && extension_loaded('zlib') && substr($fileUrl, 0, 4) === 'http' && !$hasFollowedRedirect) {
42252 $contentEncoding = $this->findHeaderValue($http_response_header, 'content-encoding');
42253 $decode = $contentEncoding && 'gzip' === strtolower($contentEncoding);
42254
42255 if ($decode) {
42256 try {
42257 if (PHP_VERSION_ID >= 50400) {
42258 $result = zlib_decode($result);
42259 } else {
42260
42261  $result = file_get_contents('compress.zlib://data:application/octet-stream;base64,'.base64_encode($result));
42262 }
42263
42264 if (!$result) {
42265 throw new TransportException('Failed to decode zlib stream');
42266 }
42267 } catch (\Exception $e) {
42268 if ($this->degradedMode) {
42269 throw $e;
42270 }
42271
42272 $this->degradedMode = true;
42273 $this->io->writeError(array(
42274 '',
42275 '<error>Failed to decode response: '.$e->getMessage().'</error>',
42276 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
42277 ));
42278
42279 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
42280 }
42281 }
42282 }
42283
42284
42285  if (false !== $result && null !== $fileName && !$isRedirect) {
42286 if ('' === $result) {
42287 throw new TransportException('"'.$this->fileUrl.'" appears broken, and returned an empty 200 response');
42288 }
42289
42290 $errorMessage = '';
42291 set_error_handler(function ($code, $msg) use (&$errorMessage) {
42292 if ($errorMessage) {
42293 $errorMessage .= "\n";
42294 }
42295 $errorMessage .= preg_replace('{^file_put_contents\(.*?\): }', '', $msg);
42296 });
42297 $result = (bool) file_put_contents($fileName, $result);
42298 restore_error_handler();
42299 if (false === $result) {
42300 throw new TransportException('The "'.$this->fileUrl.'" file could not be written to '.$fileName.': '.$errorMessage);
42301 }
42302 }
42303
42304
42305  if (false === $result && false !== strpos($errorMessage, 'Peer certificate') && PHP_VERSION_ID < 50600) {
42306
42307  
42308  
42309  
42310  
42311  
42312  
42313  
42314  
42315  
42316  
42317  
42318  
42319  
42320  
42321  
42322  if (CaBundle::isOpensslParseSafe()) {
42323 $certDetails = $this->getCertificateCnAndFp($this->fileUrl, $options);
42324
42325 if ($certDetails) {
42326 $this->peerCertificateMap[$this->getUrlAuthority($this->fileUrl)] = $certDetails;
42327
42328 $this->retry = true;
42329 }
42330 } else {
42331 $this->io->writeError('');
42332 $this->io->writeError(sprintf(
42333 '<error>Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.</error>',
42334 PHP_VERSION
42335 ));
42336 }
42337 }
42338
42339 if ($this->retry) {
42340 $this->retry = false;
42341
42342 $result = $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
42343
42344 if ($this->storeAuth && $this->config) {
42345 $authHelper = new AuthHelper($this->io, $this->config);
42346 $authHelper->storeAuth($this->originUrl, $this->storeAuth);
42347 $this->storeAuth = false;
42348 }
42349
42350 return $result;
42351 }
42352
42353 if (false === $result) {
42354 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded: '.$errorMessage, $errorCode);
42355 if (!empty($http_response_header[0])) {
42356 $e->setHeaders($http_response_header);
42357 }
42358
42359 if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
42360 $this->degradedMode = true;
42361 $this->io->writeError('');
42362 $this->io->writeError(array(
42363 '<error>'.$e->getMessage().'</error>',
42364 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
42365 ));
42366
42367 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
42368 }
42369
42370 throw $e;
42371 }
42372
42373 if (!empty($http_response_header[0])) {
42374 $this->lastHeaders = $http_response_header;
42375 }
42376
42377 return $result;
42378 }
42379
42380
42381
42382
42383
42384
42385
42386
42387
42388
42389
42390
42391 protected function callbackGet($notificationCode, $severity, $message, $messageCode, $bytesTransferred, $bytesMax)
42392 {
42393 switch ($notificationCode) {
42394 case STREAM_NOTIFY_FAILURE:
42395 if (400 === $messageCode) {
42396
42397  
42398  throw new TransportException("The '" . $this->fileUrl . "' URL could not be accessed: " . $message, $messageCode);
42399 }
42400
42401  
42402
42403 case STREAM_NOTIFY_AUTH_REQUIRED:
42404 if (401 === $messageCode) {
42405
42406  if (!$this->retryAuthFailure) {
42407 break;
42408 }
42409
42410 $this->promptAuthAndRetry($messageCode);
42411 }
42412 break;
42413
42414 case STREAM_NOTIFY_AUTH_RESULT:
42415 if (403 === $messageCode) {
42416
42417  if (!$this->retryAuthFailure) {
42418 break;
42419 }
42420
42421 $this->promptAuthAndRetry($messageCode, $message);
42422 }
42423 break;
42424
42425 case STREAM_NOTIFY_FILE_SIZE_IS:
42426 $this->bytesMax = $bytesMax;
42427 break;
42428
42429 case STREAM_NOTIFY_PROGRESS:
42430 if ($this->bytesMax > 0 && $this->progress) {
42431 $progression = min(100, round($bytesTransferred / $this->bytesMax * 100));
42432
42433 if ((0 === $progression % 5) && 100 !== $progression && $progression !== $this->lastProgress) {
42434 $this->lastProgress = $progression;
42435 $this->io->overwriteError("Downloading (<comment>$progression%</comment>)", false);
42436 }
42437 }
42438 break;
42439
42440 default:
42441 break;
42442 }
42443 }
42444
42445 protected function promptAuthAndRetry($httpStatus, $reason = null)
42446 {
42447 if ($this->config && in_array($this->originUrl, $this->config->get('github-domains'), true)) {
42448 $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');
42449 $gitHubUtil = new GitHub($this->io, $this->config, null);
42450 if (!$gitHubUtil->authorizeOAuth($this->originUrl)
42451 && (!$this->io->isInteractive() || !$gitHubUtil->authorizeOAuthInteractively($this->originUrl, $message))
42452 ) {
42453 throw new TransportException('Could not authenticate against '.$this->originUrl, 401);
42454 }
42455 } elseif ($this->config && in_array($this->originUrl, $this->config->get('gitlab-domains'), true)) {
42456 $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');
42457 $gitLabUtil = new GitLab($this->io, $this->config, null);
42458
42459 if ($this->io->hasAuthentication($this->originUrl) && ($auth = $this->io->getAuthentication($this->originUrl)) && $auth['password'] === 'private-token') {
42460 throw new TransportException("Invalid credentials for '" . $this->fileUrl . "', aborting.", $httpStatus);
42461 }
42462
42463 if (!$gitLabUtil->authorizeOAuth($this->originUrl)
42464 && (!$this->io->isInteractive() || !$gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, $message))
42465 ) {
42466 throw new TransportException('Could not authenticate against '.$this->originUrl, 401);
42467 }
42468 } elseif ($this->config && $this->originUrl === 'bitbucket.org') {
42469 $askForOAuthToken = true;
42470 if ($this->io->hasAuthentication($this->originUrl)) {
42471 $auth = $this->io->getAuthentication($this->originUrl);
42472 if ($auth['username'] !== 'x-token-auth') {
42473 $bitbucketUtil = new Bitbucket($this->io, $this->config);
42474 $accessToken = $bitbucketUtil->requestToken($this->originUrl, $auth['username'], $auth['password']);
42475 if (!empty($accessToken)) {
42476 $this->io->setAuthentication($this->originUrl, 'x-token-auth', $accessToken);
42477 $askForOAuthToken = false;
42478 }
42479 } else {
42480 throw new TransportException('Could not authenticate against ' . $this->originUrl, 401);
42481 }
42482 }
42483
42484 if ($askForOAuthToken) {
42485 $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');
42486 $bitBucketUtil = new Bitbucket($this->io, $this->config);
42487 if (! $bitBucketUtil->authorizeOAuth($this->originUrl)
42488 && (! $this->io->isInteractive() || !$bitBucketUtil->authorizeOAuthInteractively($this->originUrl, $message))
42489 ) {
42490 throw new TransportException('Could not authenticate against ' . $this->originUrl, 401);
42491 }
42492 }
42493 } else {
42494
42495  if ($httpStatus === 404) {
42496 return;
42497 }
42498
42499
42500  if (!$this->io->isInteractive()) {
42501 if ($httpStatus === 401) {
42502 $message = "The '" . $this->fileUrl . "' URL required authentication.\nYou must be using the interactive console to authenticate";
42503 }
42504 if ($httpStatus === 403) {
42505 $message = "The '" . $this->fileUrl . "' URL could not be accessed: " . $reason;
42506 }
42507
42508 throw new TransportException($message, $httpStatus);
42509 }
42510
42511  if ($this->io->hasAuthentication($this->originUrl)) {
42512 throw new TransportException("Invalid credentials for '" . $this->fileUrl . "', aborting.", $httpStatus);
42513 }
42514
42515 $this->io->overwriteError('');
42516 $this->io->writeError('    Authentication required (<info>'.parse_url($this->fileUrl, PHP_URL_HOST).'</info>):');
42517 $username = $this->io->ask('      Username: ');
42518 $password = $this->io->askAndHideAnswer('      Password: ');
42519 $this->io->setAuthentication($this->originUrl, $username, $password);
42520 $this->storeAuth = $this->config->get('store-auths');
42521 }
42522
42523 $this->retry = true;
42524 throw new TransportException('RETRY');
42525 }
42526
42527 protected function getOptionsForUrl($originUrl, $additionalOptions)
42528 {
42529 $tlsOptions = array();
42530
42531
42532  if ($this->disableTls === false && PHP_VERSION_ID < 50600 && !stream_is_local($this->fileUrl)) {
42533 $host = parse_url($this->fileUrl, PHP_URL_HOST);
42534
42535 if (PHP_VERSION_ID < 50304) {
42536
42537  
42538  
42539  
42540
42541 if ($host === 'github.com' || $host === 'api.github.com') {
42542 $host = '*.github.com';
42543 }
42544 }
42545
42546 $tlsOptions['ssl']['CN_match'] = $host;
42547 $tlsOptions['ssl']['SNI_server_name'] = $host;
42548
42549 $urlAuthority = $this->getUrlAuthority($this->fileUrl);
42550
42551 if (isset($this->peerCertificateMap[$urlAuthority])) {
42552
42553  $certMap = $this->peerCertificateMap[$urlAuthority];
42554
42555 $this->io->writeError('', true, IOInterface::DEBUG);
42556 $this->io->writeError(sprintf(
42557 'Using <info>%s</info> as CN for subjectAltName enabled host <info>%s</info>',
42558 $certMap['cn'],
42559 $urlAuthority
42560 ), true, IOInterface::DEBUG);
42561
42562 $tlsOptions['ssl']['CN_match'] = $certMap['cn'];
42563 $tlsOptions['ssl']['peer_fingerprint'] = $certMap['fp'];
42564 }
42565 }
42566
42567 $headers = array();
42568
42569 if (extension_loaded('zlib')) {
42570 $headers[] = 'Accept-Encoding: gzip';
42571 }
42572
42573 $options = array_replace_recursive($this->options, $tlsOptions, $additionalOptions);
42574 if (!$this->degradedMode) {
42575
42576  
42577  $options['http']['protocol_version'] = 1.1;
42578 $headers[] = 'Connection: close';
42579 }
42580
42581 if ($this->io->hasAuthentication($originUrl)) {
42582 $auth = $this->io->getAuthentication($originUrl);
42583 if ('github.com' === $originUrl && 'x-oauth-basic' === $auth['password']) {
42584 $options['github-token'] = $auth['username'];
42585 } elseif ($this->config && in_array($originUrl, $this->config->get('gitlab-domains'), true)) {
42586 if ($auth['password'] === 'oauth2') {
42587 $headers[] = 'Authorization: Bearer '.$auth['username'];
42588 } elseif ($auth['password'] === 'private-token') {
42589 $headers[] = 'PRIVATE-TOKEN: '.$auth['username'];
42590 }
42591 } elseif ('bitbucket.org' === $originUrl
42592 && $this->fileUrl !== Bitbucket::OAUTH2_ACCESS_TOKEN_URL && 'x-token-auth' === $auth['username']
42593 ) {
42594 if (!$this->isPublicBitBucketDownload($this->fileUrl)) {
42595 $headers[] = 'Authorization: Bearer ' . $auth['password'];
42596 }
42597 } else {
42598 $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
42599 $headers[] = 'Authorization: Basic '.$authStr;
42600 }
42601 }
42602
42603 $options['http']['follow_location'] = 0;
42604
42605 if (isset($options['http']['header']) && !is_array($options['http']['header'])) {
42606 $options['http']['header'] = explode("\r\n", trim($options['http']['header'], "\r\n"));
42607 }
42608 foreach ($headers as $header) {
42609 $options['http']['header'][] = $header;
42610 }
42611
42612 return $options;
42613 }
42614
42615 private function handleRedirect(array $http_response_header, array $additionalOptions, $result)
42616 {
42617 if ($locationHeader = $this->findHeaderValue($http_response_header, 'location')) {
42618 if (parse_url($locationHeader, PHP_URL_SCHEME)) {
42619
42620  $targetUrl = $locationHeader;
42621 } elseif (parse_url($locationHeader, PHP_URL_HOST)) {
42622
42623  $targetUrl = $this->scheme.':'.$locationHeader;
42624 } elseif ('/' === $locationHeader[0]) {
42625
42626  $urlHost = parse_url($this->fileUrl, PHP_URL_HOST);
42627
42628
42629  $targetUrl = preg_replace('{^(.+(?://|@)'.preg_quote($urlHost).'(?::\d+)?)(?:[/\?].*)?$}', '\1'.$locationHeader, $this->fileUrl);
42630 } else {
42631
42632  
42633  $targetUrl = preg_replace('{^(.+/)[^/?]*(?:\?.*)?$}', '\1'.$locationHeader, $this->fileUrl);
42634 }
42635 }
42636
42637 if (!empty($targetUrl)) {
42638 $this->redirects++;
42639
42640 $this->io->writeError('', true, IOInterface::DEBUG);
42641 $this->io->writeError(sprintf('Following redirect (%u) %s', $this->redirects, $targetUrl), true, IOInterface::DEBUG);
42642
42643 $additionalOptions['redirects'] = $this->redirects;
42644
42645 return $this->get(parse_url($targetUrl, PHP_URL_HOST), $targetUrl, $additionalOptions, $this->fileName, $this->progress);
42646 }
42647
42648 if (!$this->retry) {
42649 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded, got redirect without Location ('.$http_response_header[0].')');
42650 $e->setHeaders($http_response_header);
42651 $e->setResponse($result);
42652
42653 throw $e;
42654 }
42655
42656 return false;
42657 }
42658
42659
42660
42661
42662
42663
42664 private function getTlsDefaults(array $options)
42665 {
42666 $ciphers = implode(':', array(
42667 'ECDHE-RSA-AES128-GCM-SHA256',
42668 'ECDHE-ECDSA-AES128-GCM-SHA256',
42669 'ECDHE-RSA-AES256-GCM-SHA384',
42670 'ECDHE-ECDSA-AES256-GCM-SHA384',
42671 'DHE-RSA-AES128-GCM-SHA256',
42672 'DHE-DSS-AES128-GCM-SHA256',
42673 'kEDH+AESGCM',
42674 'ECDHE-RSA-AES128-SHA256',
42675 'ECDHE-ECDSA-AES128-SHA256',
42676 'ECDHE-RSA-AES128-SHA',
42677 'ECDHE-ECDSA-AES128-SHA',
42678 'ECDHE-RSA-AES256-SHA384',
42679 'ECDHE-ECDSA-AES256-SHA384',
42680 'ECDHE-RSA-AES256-SHA',
42681 'ECDHE-ECDSA-AES256-SHA',
42682 'DHE-RSA-AES128-SHA256',
42683 'DHE-RSA-AES128-SHA',
42684 'DHE-DSS-AES128-SHA256',
42685 'DHE-RSA-AES256-SHA256',
42686 'DHE-DSS-AES256-SHA',
42687 'DHE-RSA-AES256-SHA',
42688 'AES128-GCM-SHA256',
42689 'AES256-GCM-SHA384',
42690 'AES128-SHA256',
42691 'AES256-SHA256',
42692 'AES128-SHA',
42693 'AES256-SHA',
42694 'AES',
42695 'CAMELLIA',
42696 'DES-CBC3-SHA',
42697 '!aNULL',
42698 '!eNULL',
42699 '!EXPORT',
42700 '!DES',
42701 '!RC4',
42702 '!MD5',
42703 '!PSK',
42704 '!aECDH',
42705 '!EDH-DSS-DES-CBC3-SHA',
42706 '!EDH-RSA-DES-CBC3-SHA',
42707 '!KRB5-DES-CBC3-SHA',
42708 ));
42709
42710
42711
42712
42713
42714
42715
42716 $defaults = array(
42717 'ssl' => array(
42718 'ciphers' => $ciphers,
42719 'verify_peer' => true,
42720 'verify_depth' => 7,
42721 'SNI_enabled' => true,
42722 'capture_peer_cert' => true,
42723 ),
42724 );
42725
42726 if (isset($options['ssl'])) {
42727 $defaults['ssl'] = array_replace_recursive($defaults['ssl'], $options['ssl']);
42728 }
42729
42730 $caBundleLogger = $this->io instanceof LoggerInterface ? $this->io : null;
42731
42732
42733
42734
42735
42736 if (!isset($defaults['ssl']['cafile']) && !isset($defaults['ssl']['capath'])) {
42737 $result = CaBundle::getSystemCaRootBundlePath($caBundleLogger);
42738
42739 if (preg_match('{^phar://}', $result)) {
42740 $hash = hash_file('sha256', $result);
42741 $targetPath = rtrim(sys_get_temp_dir(), '\\/') . '/composer-cacert-' . $hash . '.pem';
42742
42743 if (!file_exists($targetPath) || $hash !== hash_file('sha256', $targetPath)) {
42744 $this->streamCopy($result, $targetPath);
42745 chmod($targetPath, 0666);
42746 }
42747
42748 $defaults['ssl']['cafile'] = $targetPath;
42749 } elseif (is_dir($result)) {
42750 $defaults['ssl']['capath'] = $result;
42751 } else {
42752 $defaults['ssl']['cafile'] = $result;
42753 }
42754 }
42755
42756 if (isset($defaults['ssl']['cafile']) && (!is_readable($defaults['ssl']['cafile']) || !CaBundle::validateCaFile($defaults['ssl']['cafile'], $caBundleLogger))) {
42757 throw new TransportException('The configured cafile was not valid or could not be read.');
42758 }
42759
42760 if (isset($defaults['ssl']['capath']) && (!is_dir($defaults['ssl']['capath']) || !is_readable($defaults['ssl']['capath']))) {
42761 throw new TransportException('The configured capath was not valid or could not be read.');
42762 }
42763
42764
42765
42766
42767 if (PHP_VERSION_ID >= 50413) {
42768 $defaults['ssl']['disable_compression'] = true;
42769 }
42770
42771 return $defaults;
42772 }
42773
42774
42775
42776
42777
42778
42779
42780 private function streamCopy($source, $target)
42781 {
42782 $source = fopen($source, 'r');
42783 $target = fopen($target, 'w+');
42784
42785 stream_copy_to_stream($source, $target);
42786 fclose($source);
42787 fclose($target);
42788
42789 unset($source, $target);
42790 }
42791
42792
42793
42794
42795
42796
42797 private function getCertificateCnAndFp($url, $options)
42798 {
42799 if (PHP_VERSION_ID >= 50600) {
42800 throw new \BadMethodCallException(sprintf(
42801 '%s must not be used on PHP >= 5.6',
42802 __METHOD__
42803 ));
42804 }
42805
42806 $context = StreamContextFactory::getContext($url, $options, array('options' => array(
42807 'ssl' => array(
42808 'capture_peer_cert' => true,
42809 'verify_peer' => false, 
42810  ), ),
42811 ));
42812
42813
42814  
42815  if (false === $handle = @fopen($url, 'rb', false, $context)) {
42816 return;
42817 }
42818
42819
42820  fclose($handle);
42821 $handle = null;
42822
42823 $params = stream_context_get_params($context);
42824
42825 if (!empty($params['options']['ssl']['peer_certificate'])) {
42826 $peerCertificate = $params['options']['ssl']['peer_certificate'];
42827
42828 if (TlsHelper::checkCertificateHost($peerCertificate, parse_url($url, PHP_URL_HOST), $commonName)) {
42829 return array(
42830 'cn' => $commonName,
42831 'fp' => TlsHelper::getCertificateFingerprint($peerCertificate),
42832 );
42833 }
42834 }
42835 }
42836
42837 private function getUrlAuthority($url)
42838 {
42839 $defaultPorts = array(
42840 'ftp' => 21,
42841 'http' => 80,
42842 'https' => 443,
42843 'ssh2.sftp' => 22,
42844 'ssh2.scp' => 22,
42845 );
42846
42847 $scheme = parse_url($url, PHP_URL_SCHEME);
42848
42849 if (!isset($defaultPorts[$scheme])) {
42850 throw new \InvalidArgumentException(sprintf(
42851 'Could not get default port for unknown scheme: %s',
42852 $scheme
42853 ));
42854 }
42855
42856 $defaultPort = $defaultPorts[$scheme];
42857 $port = parse_url($url, PHP_URL_PORT) ?: $defaultPort;
42858
42859 return parse_url($url, PHP_URL_HOST).':'.$port;
42860 }
42861
42862
42863
42864
42865
42866
42867
42868
42869 private function isPublicBitBucketDownload($urlToBitBucketFile)
42870 {
42871 $domain = parse_url($urlToBitBucketFile, PHP_URL_HOST);
42872 if (strpos($domain, 'bitbucket.org') === false) {
42873
42874  
42875  return true;
42876 }
42877
42878 $path = parse_url($urlToBitBucketFile, PHP_URL_PATH);
42879
42880
42881  
42882  $pathParts = explode('/', $path);
42883 if (count($pathParts) >= 4 && $pathParts[3] == 'downloads') {
42884 return true;
42885 }
42886
42887 return false;
42888 }
42889 }
42890 <?php
42891
42892
42893
42894
42895
42896
42897
42898
42899
42900
42901
42902 namespace Composer\Util;
42903
42904
42905
42906
42907
42908
42909 class Silencer
42910 {
42911
42912
42913
42914 private static $stack = array();
42915
42916
42917
42918
42919
42920
42921
42922 public static function suppress($mask = null)
42923 {
42924 if (!isset($mask)) {
42925 $mask = E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE | E_DEPRECATED | E_USER_DEPRECATED | E_STRICT;
42926 }
42927 $old = error_reporting();
42928 array_push(self::$stack, $old);
42929 error_reporting($old & ~$mask);
42930
42931 return $old;
42932 }
42933
42934
42935
42936
42937 public static function restore()
42938 {
42939 if (!empty(self::$stack)) {
42940 error_reporting(array_pop(self::$stack));
42941 }
42942 }
42943
42944
42945
42946
42947
42948
42949
42950
42951
42952
42953 public static function call($callable )
42954 {
42955 try {
42956 self::suppress();
42957 $result = call_user_func_array($callable, array_slice(func_get_args(), 1));
42958 self::restore();
42959
42960 return $result;
42961 } catch (\Exception $e) {
42962
42963  self::restore();
42964 throw $e;
42965 }
42966 }
42967 }
42968 <?php
42969
42970
42971
42972
42973
42974
42975
42976
42977
42978
42979
42980 namespace Composer\Util;
42981
42982 use Composer\Spdx\SpdxLicenses;
42983
42984 trigger_error('The ' . __NAMESPACE__ . '\SpdxLicense class is deprecated, use Composer\Spdx\SpdxLicenses instead.', E_USER_DEPRECATED);
42985
42986
42987
42988
42989 class SpdxLicense extends SpdxLicenses
42990 {
42991 }
42992 <?php
42993
42994
42995
42996
42997
42998
42999
43000
43001
43002
43003
43004 namespace Composer\Util;
43005
43006 use Composer\Composer;
43007
43008
43009
43010
43011
43012
43013
43014 final class StreamContextFactory
43015 {
43016
43017
43018
43019
43020
43021
43022
43023
43024
43025 public static function getContext($url, array $defaultOptions = array(), array $defaultParams = array())
43026 {
43027 $options = array('http' => array(
43028
43029  'follow_location' => 1,
43030 'max_redirects' => 20,
43031 ));
43032
43033
43034  if (PHP_SAPI === 'cli' && (!empty($_SERVER['HTTP_PROXY']) || !empty($_SERVER['http_proxy']))) {
43035 $proxy = parse_url(!empty($_SERVER['http_proxy']) ? $_SERVER['http_proxy'] : $_SERVER['HTTP_PROXY']);
43036 }
43037
43038
43039  if (!empty($_SERVER['CGI_HTTP_PROXY'])) {
43040 $proxy = parse_url($_SERVER['CGI_HTTP_PROXY']);
43041 }
43042
43043
43044  if (preg_match('{^https://}i', $url) && (!empty($_SERVER['HTTPS_PROXY']) || !empty($_SERVER['https_proxy']))) {
43045 $proxy = parse_url(!empty($_SERVER['https_proxy']) ? $_SERVER['https_proxy'] : $_SERVER['HTTPS_PROXY']);
43046 }
43047
43048
43049  if (!empty($_SERVER['no_proxy']) && parse_url($url, PHP_URL_HOST)) {
43050 $pattern = new NoProxyPattern($_SERVER['no_proxy']);
43051 if ($pattern->test($url)) {
43052 unset($proxy);
43053 }
43054 }
43055
43056 if (!empty($proxy)) {
43057 $proxyURL = isset($proxy['scheme']) ? $proxy['scheme'] . '://' : '';
43058 $proxyURL .= isset($proxy['host']) ? $proxy['host'] : '';
43059
43060 if (isset($proxy['port'])) {
43061 $proxyURL .= ":" . $proxy['port'];
43062 } elseif ('http://' == substr($proxyURL, 0, 7)) {
43063 $proxyURL .= ":80";
43064 } elseif ('https://' == substr($proxyURL, 0, 8)) {
43065 $proxyURL .= ":443";
43066 }
43067
43068
43069  $proxyURL = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $proxyURL);
43070
43071 if (0 === strpos($proxyURL, 'ssl:') && !extension_loaded('openssl')) {
43072 throw new \RuntimeException('You must enable the openssl extension to use a proxy over https');
43073 }
43074
43075 $options['http']['proxy'] = $proxyURL;
43076
43077
43078  switch (parse_url($url, PHP_URL_SCHEME)) {
43079 case 'http': 
43080  $reqFullUriEnv = getenv('HTTP_PROXY_REQUEST_FULLURI');
43081 if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
43082 $options['http']['request_fulluri'] = true;
43083 }
43084 break;
43085 case 'https': 
43086  $reqFullUriEnv = getenv('HTTPS_PROXY_REQUEST_FULLURI');
43087 if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
43088 $options['http']['request_fulluri'] = true;
43089 }
43090 break;
43091 }
43092
43093
43094  if ('https' === parse_url($url, PHP_URL_SCHEME)) {
43095 $options['ssl']['SNI_enabled'] = true;
43096 if (PHP_VERSION_ID < 50600) {
43097 $options['ssl']['SNI_server_name'] = parse_url($url, PHP_URL_HOST);
43098 }
43099 }
43100
43101
43102  if (isset($proxy['user'])) {
43103 $auth = urldecode($proxy['user']);
43104 if (isset($proxy['pass'])) {
43105 $auth .= ':' . urldecode($proxy['pass']);
43106 }
43107 $auth = base64_encode($auth);
43108
43109
43110  if (isset($defaultOptions['http']['header'])) {
43111 if (is_string($defaultOptions['http']['header'])) {
43112 $defaultOptions['http']['header'] = array($defaultOptions['http']['header']);
43113 }
43114 $defaultOptions['http']['header'][] = "Proxy-Authorization: Basic {$auth}";
43115 } else {
43116 $options['http']['header'] = array("Proxy-Authorization: Basic {$auth}");
43117 }
43118 }
43119 }
43120
43121 $options = array_replace_recursive($options, $defaultOptions);
43122
43123 if (isset($options['http']['header'])) {
43124 $options['http']['header'] = self::fixHttpHeaderField($options['http']['header']);
43125 }
43126
43127 if (defined('HHVM_VERSION')) {
43128 $phpVersion = 'HHVM ' . HHVM_VERSION;
43129 } else {
43130 $phpVersion = 'PHP ' . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION;
43131 }
43132
43133 if (!isset($options['http']['header']) || false === strpos(strtolower(implode('', $options['http']['header'])), 'user-agent')) {
43134 $options['http']['header'][] = sprintf(
43135 'User-Agent: Composer/%s (%s; %s; %s%s)',
43136 Composer::VERSION === '@package_version@' ? 'source' : Composer::VERSION,
43137 function_exists('php_uname') ? php_uname('s') : 'Unknown',
43138 function_exists('php_uname') ? php_uname('r') : 'Unknown',
43139 $phpVersion,
43140 getenv('CI') ? '; CI' : ''
43141 );
43142 }
43143
43144 return stream_context_create($options, $defaultParams);
43145 }
43146
43147
43148
43149
43150
43151
43152
43153
43154
43155
43156
43157 private static function fixHttpHeaderField($header)
43158 {
43159 if (!is_array($header)) {
43160 $header = explode("\r\n", $header);
43161 }
43162 uasort($header, function ($el) {
43163 return preg_match('{^content-type}i', $el) ? 1 : -1;
43164 });
43165
43166 return $header;
43167 }
43168 }
43169 <?php
43170
43171
43172
43173
43174
43175
43176
43177
43178
43179
43180
43181 namespace Composer\Util;
43182
43183 use Composer\Config;
43184 use Composer\IO\IOInterface;
43185
43186
43187
43188
43189
43190 class Svn
43191 {
43192 const MAX_QTY_AUTH_TRIES = 5;
43193
43194
43195
43196
43197 protected $credentials;
43198
43199
43200
43201
43202 protected $hasAuth;
43203
43204
43205
43206
43207 protected $io;
43208
43209
43210
43211
43212 protected $url;
43213
43214
43215
43216
43217 protected $cacheCredentials = true;
43218
43219
43220
43221
43222 protected $process;
43223
43224
43225
43226
43227 protected $qtyAuthTries = 0;
43228
43229
43230
43231
43232 protected $config;
43233
43234
43235
43236
43237
43238
43239
43240 public function __construct($url, IOInterface $io, Config $config, ProcessExecutor $process = null)
43241 {
43242 $this->url = $url;
43243 $this->io = $io;
43244 $this->config = $config;
43245 $this->process = $process ?: new ProcessExecutor;
43246 }
43247
43248 public static function cleanEnv()
43249 {
43250
43251  putenv("DYLD_LIBRARY_PATH");
43252 unset($_SERVER['DYLD_LIBRARY_PATH']);
43253 }
43254
43255
43256
43257
43258
43259
43260
43261
43262
43263
43264
43265
43266
43267
43268 public function execute($command, $url, $cwd = null, $path = null, $verbose = false)
43269 {
43270
43271  $this->config->prohibitUrlByConfig($url, $this->io);
43272
43273 $svnCommand = $this->getCommand($command, $url, $path);
43274 $output = null;
43275 $io = $this->io;
43276 $handler = function ($type, $buffer) use (&$output, $io, $verbose) {
43277 if ($type !== 'out') {
43278 return;
43279 }
43280 if ('Redirecting to URL ' === substr($buffer, 0, 19)) {
43281 return;
43282 }
43283 $output .= $buffer;
43284 if ($verbose) {
43285 $io->writeError($buffer, false);
43286 }
43287 };
43288 $status = $this->process->execute($svnCommand, $handler, $cwd);
43289 if (0 === $status) {
43290 return $output;
43291 }
43292
43293 $errorOutput = $this->process->getErrorOutput();
43294 $fullOutput = implode("\n", array($output, $errorOutput));
43295
43296
43297  if (false === stripos($fullOutput, 'Could not authenticate to server:')
43298 && false === stripos($fullOutput, 'authorization failed')
43299 && false === stripos($fullOutput, 'svn: E170001:')
43300 && false === stripos($fullOutput, 'svn: E215004:')) {
43301 throw new \RuntimeException($fullOutput);
43302 }
43303
43304 if (!$this->hasAuth()) {
43305 $this->doAuthDance();
43306 }
43307
43308
43309  if ($this->qtyAuthTries++ < self::MAX_QTY_AUTH_TRIES) {
43310
43311  return $this->execute($command, $url, $cwd, $path, $verbose);
43312 }
43313
43314 throw new \RuntimeException(
43315 'wrong credentials provided ('.$fullOutput.')'
43316 );
43317 }
43318
43319
43320
43321
43322 public function setCacheCredentials($cacheCredentials)
43323 {
43324 $this->cacheCredentials = $cacheCredentials;
43325 }
43326
43327
43328
43329
43330
43331
43332
43333 protected function doAuthDance()
43334 {
43335
43336  if (!$this->io->isInteractive()) {
43337 throw new \RuntimeException(
43338 'can not ask for authentication in non interactive mode'
43339 );
43340 }
43341
43342 $this->io->writeError("The Subversion server ({$this->url}) requested credentials:");
43343
43344 $this->hasAuth = true;
43345 $this->credentials['username'] = $this->io->ask("Username: ");
43346 $this->credentials['password'] = $this->io->askAndHideAnswer("Password: ");
43347
43348 $this->cacheCredentials = $this->io->askConfirmation("Should Subversion cache these credentials? (yes/no) ", true);
43349
43350 return $this;
43351 }
43352
43353
43354
43355
43356
43357
43358
43359
43360
43361
43362 protected function getCommand($cmd, $url, $path = null)
43363 {
43364 $cmd = sprintf('%s %s%s %s',
43365 $cmd,
43366 '--non-interactive ',
43367 $this->getCredentialString(),
43368 ProcessExecutor::escape($url)
43369 );
43370
43371 if ($path) {
43372 $cmd .= ' ' . ProcessExecutor::escape($path);
43373 }
43374
43375 return $cmd;
43376 }
43377
43378
43379
43380
43381
43382
43383
43384
43385 protected function getCredentialString()
43386 {
43387 if (!$this->hasAuth()) {
43388 return '';
43389 }
43390
43391 return sprintf(
43392 ' %s--username %s --password %s ',
43393 $this->getAuthCache(),
43394 ProcessExecutor::escape($this->getUsername()),
43395 ProcessExecutor::escape($this->getPassword())
43396 );
43397 }
43398
43399
43400
43401
43402
43403
43404
43405 protected function getPassword()
43406 {
43407 if ($this->credentials === null) {
43408 throw new \LogicException("No svn auth detected.");
43409 }
43410
43411 return isset($this->credentials['password']) ? $this->credentials['password'] : '';
43412 }
43413
43414
43415
43416
43417
43418
43419
43420 protected function getUsername()
43421 {
43422 if ($this->credentials === null) {
43423 throw new \LogicException("No svn auth detected.");
43424 }
43425
43426 return $this->credentials['username'];
43427 }
43428
43429
43430
43431
43432
43433
43434 protected function hasAuth()
43435 {
43436 if (null !== $this->hasAuth) {
43437 return $this->hasAuth;
43438 }
43439
43440 if (false === $this->createAuthFromConfig()) {
43441 $this->createAuthFromUrl();
43442 }
43443
43444 return $this->hasAuth;
43445 }
43446
43447
43448
43449
43450
43451
43452 protected function getAuthCache()
43453 {
43454 return $this->cacheCredentials ? '' : '--no-auth-cache ';
43455 }
43456
43457
43458
43459
43460
43461
43462 private function createAuthFromConfig()
43463 {
43464 if (!$this->config->has('http-basic')) {
43465 return $this->hasAuth = false;
43466 }
43467
43468 $authConfig = $this->config->get('http-basic');
43469
43470 $host = parse_url($this->url, PHP_URL_HOST);
43471 if (isset($authConfig[$host])) {
43472 $this->credentials['username'] = $authConfig[$host]['username'];
43473 $this->credentials['password'] = $authConfig[$host]['password'];
43474
43475 return $this->hasAuth = true;
43476 }
43477
43478 return $this->hasAuth = false;
43479 }
43480
43481
43482
43483
43484
43485
43486 private function createAuthFromUrl()
43487 {
43488 $uri = parse_url($this->url);
43489 if (empty($uri['user'])) {
43490 return $this->hasAuth = false;
43491 }
43492
43493 $this->credentials['username'] = $uri['user'];
43494 if (!empty($uri['pass'])) {
43495 $this->credentials['password'] = $uri['pass'];
43496 }
43497
43498 return $this->hasAuth = true;
43499 }
43500 }
43501 <?php
43502
43503
43504
43505
43506
43507
43508
43509
43510
43511
43512
43513 namespace Composer\Util;
43514
43515 use Composer\CaBundle\CaBundle;
43516
43517
43518
43519
43520 final class TlsHelper
43521 {
43522 private static $useOpensslParse;
43523
43524
43525
43526
43527
43528
43529
43530
43531
43532
43533 public static function checkCertificateHost($certificate, $hostname, &$cn = null)
43534 {
43535 $names = self::getCertificateNames($certificate);
43536
43537 if (empty($names)) {
43538 return false;
43539 }
43540
43541 $combinedNames = array_merge($names['san'], array($names['cn']));
43542 $hostname = strtolower($hostname);
43543
43544 foreach ($combinedNames as $certName) {
43545 $matcher = self::certNameMatcher($certName);
43546
43547 if ($matcher && $matcher($hostname)) {
43548 $cn = $names['cn'];
43549
43550 return true;
43551 }
43552 }
43553
43554 return false;
43555 }
43556
43557
43558
43559
43560
43561
43562
43563
43564 public static function getCertificateNames($certificate)
43565 {
43566 if (is_array($certificate)) {
43567 $info = $certificate;
43568 } elseif (CaBundle::isOpensslParseSafe()) {
43569 $info = openssl_x509_parse($certificate, false);
43570 }
43571
43572 if (!isset($info['subject']['commonName'])) {
43573 return null;
43574 }
43575
43576 $commonName = strtolower($info['subject']['commonName']);
43577 $subjectAltNames = array();
43578
43579 if (isset($info['extensions']['subjectAltName'])) {
43580 $subjectAltNames = preg_split('{\s*,\s*}', $info['extensions']['subjectAltName']);
43581 $subjectAltNames = array_filter(array_map(function ($name) {
43582 if (0 === strpos($name, 'DNS:')) {
43583 return strtolower(ltrim(substr($name, 4)));
43584 }
43585
43586 return null;
43587 }, $subjectAltNames));
43588 $subjectAltNames = array_values($subjectAltNames);
43589 }
43590
43591 return array(
43592 'cn' => $commonName,
43593 'san' => $subjectAltNames,
43594 );
43595 }
43596
43597
43598
43599
43600
43601
43602
43603
43604
43605
43606
43607
43608
43609
43610
43611
43612
43613
43614
43615
43616
43617
43618
43619
43620
43621
43622
43623
43624
43625
43626
43627
43628
43629
43630
43631
43632
43633
43634
43635
43636 public static function getCertificateFingerprint($certificate)
43637 {
43638 $pubkeydetails = openssl_pkey_get_details(openssl_get_publickey($certificate));
43639 $pubkeypem = $pubkeydetails['key'];
43640
43641  $start = '-----BEGIN PUBLIC KEY-----';
43642 $end = '-----END PUBLIC KEY-----';
43643 $pemtrim = substr($pubkeypem, (strpos($pubkeypem, $start) + strlen($start)), (strlen($pubkeypem) - strpos($pubkeypem, $end)) * (-1));
43644 $der = base64_decode($pemtrim);
43645
43646 return sha1($der);
43647 }
43648
43649
43650
43651
43652
43653
43654
43655
43656
43657 public static function isOpensslParseSafe()
43658 {
43659 return CaBundle::isOpensslParseSafe();
43660 }
43661
43662
43663
43664
43665
43666
43667
43668
43669 private static function certNameMatcher($certName)
43670 {
43671 $wildcards = substr_count($certName, '*');
43672
43673 if (0 === $wildcards) {
43674
43675  return function ($hostname) use ($certName) {
43676 return $hostname === $certName;
43677 };
43678 }
43679
43680 if (1 === $wildcards) {
43681 $components = explode('.', $certName);
43682
43683 if (3 > count($components)) {
43684
43685  return;
43686 }
43687
43688 $firstComponent = $components[0];
43689
43690
43691  if ('*' !== $firstComponent[strlen($firstComponent) - 1]) {
43692 return;
43693 }
43694
43695 $wildcardRegex = preg_quote($certName);
43696 $wildcardRegex = str_replace('\\*', '[a-z0-9-]+', $wildcardRegex);
43697 $wildcardRegex = "{^{$wildcardRegex}$}";
43698
43699 return function ($hostname) use ($wildcardRegex) {
43700 return 1 === preg_match($wildcardRegex, $hostname);
43701 };
43702 }
43703 }
43704 }
43705 <?php
43706
43707
43708
43709
43710
43711
43712
43713
43714
43715
43716
43717 namespace Composer;
43718
43719 use Composer\Util\IniHelper;
43720 use Symfony\Component\Console\Output\OutputInterface;
43721
43722
43723
43724
43725 class XdebugHandler
43726 {
43727 const ENV_ALLOW = 'COMPOSER_ALLOW_XDEBUG';
43728 const ENV_VERSION = 'COMPOSER_XDEBUG_VERSION';
43729 const RESTART_ID = 'internal';
43730
43731 private $output;
43732 private $loaded;
43733 private $envScanDir;
43734 private $version;
43735 private $tmpIni;
43736
43737
43738
43739
43740 public function __construct(OutputInterface $output)
43741 {
43742 $this->output = $output;
43743 $this->loaded = extension_loaded('xdebug');
43744 $this->envScanDir = getenv('PHP_INI_SCAN_DIR');
43745
43746 if ($this->loaded) {
43747 $ext = new \ReflectionExtension('xdebug');
43748 $this->version = strval($ext->getVersion());
43749 }
43750 }
43751
43752
43753
43754
43755
43756
43757
43758
43759
43760
43761
43762
43763
43764
43765 public function check()
43766 {
43767 $args = explode('|', strval(getenv(self::ENV_ALLOW)), 2);
43768
43769 if ($this->needsRestart($args[0])) {
43770 if ($this->prepareRestart()) {
43771 $command = $this->getCommand();
43772 $this->restart($command);
43773 }
43774
43775 return;
43776 }
43777
43778
43779  if (self::RESTART_ID === $args[0]) {
43780 putenv(self::ENV_ALLOW);
43781
43782 if (false !== $this->envScanDir) {
43783
43784  if (isset($args[1])) {
43785 putenv('PHP_INI_SCAN_DIR='.$args[1]);
43786 } else {
43787 putenv('PHP_INI_SCAN_DIR');
43788 }
43789 }
43790
43791
43792  if ($this->loaded) {
43793 putenv(self::ENV_VERSION);
43794 }
43795 }
43796 }
43797
43798
43799
43800
43801
43802
43803 protected function restart($command)
43804 {
43805 passthru($command, $exitCode);
43806
43807 if (!empty($this->tmpIni)) {
43808 @unlink($this->tmpIni);
43809 }
43810
43811 exit($exitCode);
43812 }
43813
43814
43815
43816
43817
43818
43819
43820
43821 private function needsRestart($allow)
43822 {
43823 if (PHP_SAPI !== 'cli' || !defined('PHP_BINARY')) {
43824 return false;
43825 }
43826
43827 return empty($allow) && $this->loaded;
43828 }
43829
43830
43831
43832
43833
43834
43835
43836
43837
43838
43839
43840 private function prepareRestart()
43841 {
43842 $this->tmpIni = '';
43843 $iniPaths = IniHelper::getAll();
43844 $additional = count($iniPaths) > 1;
43845
43846 if ($this->writeTmpIni($iniPaths)) {
43847 return $this->setEnvironment($additional, $iniPaths);
43848 }
43849
43850 return false;
43851 }
43852
43853
43854
43855
43856
43857
43858
43859
43860
43861
43862 private function writeTmpIni(array $iniPaths)
43863 {
43864 if (!$this->tmpIni = tempnam(sys_get_temp_dir(), '')) {
43865 return false;
43866 }
43867
43868
43869  if (empty($iniPaths[0])) {
43870 array_shift($iniPaths);
43871 }
43872
43873 $content = '';
43874 $regex = '/^\s*(zend_extension\s*=.*xdebug.*)$/mi';
43875
43876 foreach ($iniPaths as $file) {
43877 $data = preg_replace($regex, ';$1', file_get_contents($file));
43878 $content .= $data.PHP_EOL;
43879 }
43880
43881 $content .= 'allow_url_fopen='.ini_get('allow_url_fopen').PHP_EOL;
43882 $content .= 'disable_functions="'.ini_get('disable_functions').'"'.PHP_EOL;
43883 $content .= 'memory_limit='.ini_get('memory_limit').PHP_EOL;
43884
43885 if (defined('PHP_WINDOWS_VERSION_BUILD')) {
43886
43887  $content .= 'opcache.enable_cli=0'.PHP_EOL;
43888 }
43889
43890 return @file_put_contents($this->tmpIni, $content);
43891 }
43892
43893
43894
43895
43896
43897
43898 private function getCommand()
43899 {
43900 $phpArgs = array(PHP_BINARY, '-c', $this->tmpIni);
43901 $params = array_merge($phpArgs, $this->getScriptArgs($_SERVER['argv']));
43902
43903 return implode(' ', array_map(array($this, 'escape'), $params));
43904 }
43905
43906
43907
43908
43909
43910
43911
43912
43913
43914 private function setEnvironment($additional, array $iniPaths)
43915 {
43916
43917  if ($additional && !putenv('PHP_INI_SCAN_DIR=')) {
43918 return false;
43919 }
43920
43921
43922  if (!putenv(IniHelper::ENV_ORIGINAL.'='.implode(PATH_SEPARATOR, $iniPaths))) {
43923 return false;
43924 }
43925
43926
43927  if (!putenv(self::ENV_VERSION.'='.$this->version)) {
43928 return false;
43929 }
43930
43931
43932  $args = array(self::RESTART_ID);
43933
43934 if (false !== $this->envScanDir) {
43935
43936  $args[] = $this->envScanDir;
43937 }
43938
43939 return putenv(self::ENV_ALLOW.'='.implode('|', $args));
43940 }
43941
43942
43943
43944
43945
43946
43947
43948
43949
43950
43951
43952 private function getScriptArgs(array $args)
43953 {
43954 if (in_array('--no-ansi', $args) || in_array('--ansi', $args)) {
43955 return $args;
43956 }
43957
43958 if ($this->output->isDecorated()) {
43959 $offset = count($args) > 1 ? 2 : 1;
43960 array_splice($args, $offset, 0, '--ansi');
43961 }
43962
43963 return $args;
43964 }
43965
43966
43967
43968
43969
43970
43971
43972
43973
43974
43975
43976
43977 private function escape($arg, $meta = true)
43978 {
43979 if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
43980 return escapeshellarg($arg);
43981 }
43982
43983 $quote = strpbrk($arg, " \t") !== false || $arg === '';
43984 $arg = preg_replace('/(\\\\*)"/', '$1$1\\"', $arg, -1, $dquotes);
43985
43986 if ($meta) {
43987 $meta = $dquotes || preg_match('/%[^%]+%/', $arg);
43988
43989 if (!$meta && !$quote) {
43990 $quote = strpbrk($arg, '^&|<>()') !== false;
43991 }
43992 }
43993
43994 if ($quote) {
43995 $arg = preg_replace('/(\\\\*)$/', '$1$1', $arg);
43996 $arg = '"'.$arg.'"';
43997 }
43998
43999 if ($meta) {
44000 $arg = preg_replace('/(["^&|<>()%])/', '^$1', $arg);
44001 }
44002
44003 return $arg;
44004 }
44005 }
44006 <?php
44007
44008
44009
44010
44011
44012
44013
44014
44015
44016
44017
44018 function includeIfExists($file)
44019 {
44020 return file_exists($file) ? include $file : false;
44021 }
44022
44023 if ((!$loader = includeIfExists(__DIR__.'/../vendor/autoload.php')) && (!$loader = includeIfExists(__DIR__.'/../../../autoload.php'))) {
44024 echo 'You must set up the project dependencies using `composer install`'.PHP_EOL.
44025 'See https://getcomposer.org/download/ for instructions on installing Composer'.PHP_EOL;
44026 exit(1);
44027 }
44028
44029 return $loader;
44030 <?php
44031
44032 /*
44033  * This file is part of Composer.
44034  *
44035  * (c) Nils Adermann <naderman@naderman.de>
44036  *     Jordi Boggiano <j.boggiano@seld.be>
44037  *
44038  * For the full copyright and license information, please view the LICENSE
44039  * file that was distributed with this source code.
44040  */
44041
44042 namespace Composer\Autoload;
44043
44044 /**
44045  * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
44046  *
44047  *     $loader = new \Composer\Autoload\ClassLoader();
44048  *
44049  *     // register classes with namespaces
44050  *     $loader->add('Symfony\Component', __DIR__.'/component');
44051  *     $loader->add('Symfony',           __DIR__.'/framework');
44052  *
44053  *     // activate the autoloader
44054  *     $loader->register();
44055  *
44056  *     // to enable searching the include path (eg. for PEAR packages)
44057  *     $loader->setUseIncludePath(true);
44058  *
44059  * In this example, if you try to use a class in the Symfony\Component
44060  * namespace or one of its children (Symfony\Component\Console for instance),
44061  * the autoloader will first look for the class under the component/
44062  * directory, and it will then fallback to the framework/ directory if not
44063  * found before giving up.
44064  *
44065  * This class is loosely based on the Symfony UniversalClassLoader.
44066  *
44067  * @author Fabien Potencier <fabien@symfony.com>
44068  * @author Jordi Boggiano <j.boggiano@seld.be>
44069  * @see    http://www.php-fig.org/psr/psr-0/
44070  * @see    http://www.php-fig.org/psr/psr-4/
44071  */
44072 class ClassLoader
44073 {
44074     // PSR-4
44075     private $prefixLengthsPsr4 = array();
44076     private $prefixDirsPsr4 = array();
44077     private $fallbackDirsPsr4 = array();
44078
44079     // PSR-0
44080     private $prefixesPsr0 = array();
44081     private $fallbackDirsPsr0 = array();
44082
44083     private $useIncludePath = false;
44084     private $classMap = array();
44085     private $classMapAuthoritative = false;
44086     private $missingClasses = array();
44087     private $apcuPrefix;
44088
44089     public function getPrefixes()
44090     {
44091         if (!empty($this->prefixesPsr0)) {
44092             return call_user_func_array('array_merge', $this->prefixesPsr0);
44093         }
44094
44095         return array();
44096     }
44097
44098     public function getPrefixesPsr4()
44099     {
44100         return $this->prefixDirsPsr4;
44101     }
44102
44103     public function getFallbackDirs()
44104     {
44105         return $this->fallbackDirsPsr0;
44106     }
44107
44108     public function getFallbackDirsPsr4()
44109     {
44110         return $this->fallbackDirsPsr4;
44111     }
44112
44113     public function getClassMap()
44114     {
44115         return $this->classMap;
44116     }
44117
44118     /**
44119      * @param array $classMap Class to filename map
44120      */
44121     public function addClassMap(array $classMap)
44122     {
44123         if ($this->classMap) {
44124             $this->classMap = array_merge($this->classMap, $classMap);
44125         } else {
44126             $this->classMap = $classMap;
44127         }
44128     }
44129
44130     /**
44131      * Registers a set of PSR-0 directories for a given prefix, either
44132      * appending or prepending to the ones previously set for this prefix.
44133      *
44134      * @param string       $prefix  The prefix
44135      * @param array|string $paths   The PSR-0 root directories
44136      * @param bool         $prepend Whether to prepend the directories
44137      */
44138     public function add($prefix, $paths, $prepend = false)
44139     {
44140         if (!$prefix) {
44141             if ($prepend) {
44142                 $this->fallbackDirsPsr0 = array_merge(
44143                     (array) $paths,
44144                     $this->fallbackDirsPsr0
44145                 );
44146             } else {
44147                 $this->fallbackDirsPsr0 = array_merge(
44148                     $this->fallbackDirsPsr0,
44149                     (array) $paths
44150                 );
44151             }
44152
44153             return;
44154         }
44155
44156         $first = $prefix[0];
44157         if (!isset($this->prefixesPsr0[$first][$prefix])) {
44158             $this->prefixesPsr0[$first][$prefix] = (array) $paths;
44159
44160             return;
44161         }
44162         if ($prepend) {
44163             $this->prefixesPsr0[$first][$prefix] = array_merge(
44164                 (array) $paths,
44165                 $this->prefixesPsr0[$first][$prefix]
44166             );
44167         } else {
44168             $this->prefixesPsr0[$first][$prefix] = array_merge(
44169                 $this->prefixesPsr0[$first][$prefix],
44170                 (array) $paths
44171             );
44172         }
44173     }
44174
44175     /**
44176      * Registers a set of PSR-4 directories for a given namespace, either
44177      * appending or prepending to the ones previously set for this namespace.
44178      *
44179      * @param string       $prefix  The prefix/namespace, with trailing '\\'
44180      * @param array|string $paths   The PSR-4 base directories
44181      * @param bool         $prepend Whether to prepend the directories
44182      *
44183      * @throws \InvalidArgumentException
44184      */
44185     public function addPsr4($prefix, $paths, $prepend = false)
44186     {
44187         if (!$prefix) {
44188             // Register directories for the root namespace.
44189             if ($prepend) {
44190                 $this->fallbackDirsPsr4 = array_merge(
44191                     (array) $paths,
44192                     $this->fallbackDirsPsr4
44193                 );
44194             } else {
44195                 $this->fallbackDirsPsr4 = array_merge(
44196                     $this->fallbackDirsPsr4,
44197                     (array) $paths
44198                 );
44199             }
44200         } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
44201             // Register directories for a new namespace.
44202             $length = strlen($prefix);
44203             if ('\\' !== $prefix[$length - 1]) {
44204                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
44205             }
44206             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
44207             $this->prefixDirsPsr4[$prefix] = (array) $paths;
44208         } elseif ($prepend) {
44209             // Prepend directories for an already registered namespace.
44210             $this->prefixDirsPsr4[$prefix] = array_merge(
44211                 (array) $paths,
44212                 $this->prefixDirsPsr4[$prefix]
44213             );
44214         } else {
44215             // Append directories for an already registered namespace.
44216             $this->prefixDirsPsr4[$prefix] = array_merge(
44217                 $this->prefixDirsPsr4[$prefix],
44218                 (array) $paths
44219             );
44220         }
44221     }
44222
44223     /**
44224      * Registers a set of PSR-0 directories for a given prefix,
44225      * replacing any others previously set for this prefix.
44226      *
44227      * @param string       $prefix The prefix
44228      * @param array|string $paths  The PSR-0 base directories
44229      */
44230     public function set($prefix, $paths)
44231     {
44232         if (!$prefix) {
44233             $this->fallbackDirsPsr0 = (array) $paths;
44234         } else {
44235             $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
44236         }
44237     }
44238
44239     /**
44240      * Registers a set of PSR-4 directories for a given namespace,
44241      * replacing any others previously set for this namespace.
44242      *
44243      * @param string       $prefix The prefix/namespace, with trailing '\\'
44244      * @param array|string $paths  The PSR-4 base directories
44245      *
44246      * @throws \InvalidArgumentException
44247      */
44248     public function setPsr4($prefix, $paths)
44249     {
44250         if (!$prefix) {
44251             $this->fallbackDirsPsr4 = (array) $paths;
44252         } else {
44253             $length = strlen($prefix);
44254             if ('\\' !== $prefix[$length - 1]) {
44255                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
44256             }
44257             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
44258             $this->prefixDirsPsr4[$prefix] = (array) $paths;
44259         }
44260     }
44261
44262     /**
44263      * Turns on searching the include path for class files.
44264      *
44265      * @param bool $useIncludePath
44266      */
44267     public function setUseIncludePath($useIncludePath)
44268     {
44269         $this->useIncludePath = $useIncludePath;
44270     }
44271
44272     /**
44273      * Can be used to check if the autoloader uses the include path to check
44274      * for classes.
44275      *
44276      * @return bool
44277      */
44278     public function getUseIncludePath()
44279     {
44280         return $this->useIncludePath;
44281     }
44282
44283     /**
44284      * Turns off searching the prefix and fallback directories for classes
44285      * that have not been registered with the class map.
44286      *
44287      * @param bool $classMapAuthoritative
44288      */
44289     public function setClassMapAuthoritative($classMapAuthoritative)
44290     {
44291         $this->classMapAuthoritative = $classMapAuthoritative;
44292     }
44293
44294     /**
44295      * Should class lookup fail if not found in the current class map?
44296      *
44297      * @return bool
44298      */
44299     public function isClassMapAuthoritative()
44300     {
44301         return $this->classMapAuthoritative;
44302     }
44303
44304     /**
44305      * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
44306      *
44307      * @param string|null $apcuPrefix
44308      */
44309     public function setApcuPrefix($apcuPrefix)
44310     {
44311         $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
44312     }
44313
44314     /**
44315      * The APCu prefix in use, or null if APCu caching is not enabled.
44316      *
44317      * @return string|null
44318      */
44319     public function getApcuPrefix()
44320     {
44321         return $this->apcuPrefix;
44322     }
44323
44324     /**
44325      * Registers this instance as an autoloader.
44326      *
44327      * @param bool $prepend Whether to prepend the autoloader or not
44328      */
44329     public function register($prepend = false)
44330     {
44331         spl_autoload_register(array($this, 'loadClass'), true, $prepend);
44332     }
44333
44334     /**
44335      * Unregisters this instance as an autoloader.
44336      */
44337     public function unregister()
44338     {
44339         spl_autoload_unregister(array($this, 'loadClass'));
44340     }
44341
44342     /**
44343      * Loads the given class or interface.
44344      *
44345      * @param  string    $class The name of the class
44346      * @return bool|null True if loaded, null otherwise
44347      */
44348     public function loadClass($class)
44349     {
44350         if ($file = $this->findFile($class)) {
44351             includeFile($file);
44352
44353             return true;
44354         }
44355     }
44356
44357     /**
44358      * Finds the path to the file where the class is defined.
44359      *
44360      * @param string $class The name of the class
44361      *
44362      * @return string|false The path if found, false otherwise
44363      */
44364     public function findFile($class)
44365     {
44366         // class map lookup
44367         if (isset($this->classMap[$class])) {
44368             return $this->classMap[$class];
44369         }
44370         if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
44371             return false;
44372         }
44373         if (null !== $this->apcuPrefix) {
44374             $file = apcu_fetch($this->apcuPrefix.$class, $hit);
44375             if ($hit) {
44376                 return $file;
44377             }
44378         }
44379
44380         $file = $this->findFileWithExtension($class, '.php');
44381
44382         // Search for Hack files if we are running on HHVM
44383         if (false === $file && defined('HHVM_VERSION')) {
44384             $file = $this->findFileWithExtension($class, '.hh');
44385         }
44386
44387         if (null !== $this->apcuPrefix) {
44388             apcu_add($this->apcuPrefix.$class, $file);
44389         }
44390
44391         if (false === $file) {
44392             // Remember that this class does not exist.
44393             $this->missingClasses[$class] = true;
44394         }
44395
44396         return $file;
44397     }
44398
44399     private function findFileWithExtension($class, $ext)
44400     {
44401         // PSR-4 lookup
44402         $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
44403
44404         $first = $class[0];
44405         if (isset($this->prefixLengthsPsr4[$first])) {
44406             $subPath = $class;
44407             while (false !== $lastPos = strrpos($subPath, '\\')) {
44408                 $subPath = substr($subPath, 0, $lastPos);
44409                 $search = $subPath.'\\';
44410                 if (isset($this->prefixDirsPsr4[$search])) {
44411                     foreach ($this->prefixDirsPsr4[$search] as $dir) {
44412                         $length = $this->prefixLengthsPsr4[$first][$search];
44413                         if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
44414                             return $file;
44415                         }
44416                     }
44417                 }
44418             }
44419         }
44420
44421         // PSR-4 fallback dirs
44422         foreach ($this->fallbackDirsPsr4 as $dir) {
44423             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
44424                 return $file;
44425             }
44426         }
44427
44428         // PSR-0 lookup
44429         if (false !== $pos = strrpos($class, '\\')) {
44430             // namespaced class name
44431             $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
44432                 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
44433         } else {
44434             // PEAR-like class name
44435             $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
44436         }
44437
44438         if (isset($this->prefixesPsr0[$first])) {
44439             foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
44440                 if (0 === strpos($class, $prefix)) {
44441                     foreach ($dirs as $dir) {
44442                         if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
44443                             return $file;
44444                         }
44445                     }
44446                 }
44447             }
44448         }
44449
44450         // PSR-0 fallback dirs
44451         foreach ($this->fallbackDirsPsr0 as $dir) {
44452             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
44453                 return $file;
44454             }
44455         }
44456
44457         // PSR-0 include paths.
44458         if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
44459             return $file;
44460         }
44461
44462         return false;
44463     }
44464 }
44465
44466 /**
44467  * Scope isolated include.
44468  *
44469  * Prevents access to $this/self from included files.
44470  */
44471 function includeFile($file)
44472 {
44473     include $file;
44474 }
44475 {
44476     "$schema": "http://json-schema.org/draft-04/schema#",
44477     "description": "A representation of packages metadata.",
44478     "type": "object",
44479     "oneOf": [
44480         { "required": [ "packages" ] },
44481         { "required": [ "providers" ] },
44482         { "required": [ "provider-includes", "providers-url" ] }
44483     ],
44484     "properties": {
44485         "packages": {
44486             "type": ["object", "array"],
44487             "description": "A hashmap of package names in the form of <vendor>/<name>.",
44488             "additionalProperties": { "$ref": "#/definitions/versions" }
44489         },
44490         "providers-url": {
44491             "type": "string",
44492             "description": "Endpoint to retrieve provider data from, e.g. '/p/%package%$%hash%.json'."
44493         },
44494         "provider-includes": {
44495             "type": "object",
44496             "description": "A hashmap of provider listings.",
44497             "additionalProperties": { "$ref": "#/definitions/provider" }
44498         },
44499         "providers": {
44500             "type": "object",
44501             "description": "A hashmap of package names in the form of <vendor>/<name>.",
44502             "additionalProperties": { "$ref": "#/definitions/provider" }
44503         },
44504         "notify-batch": {
44505             "type": "string",
44506             "description": "Endpoint to call after multiple packages have been installed, e.g. '/downloads/'."
44507         },
44508         "search": {
44509             "type": "string",
44510             "description": "Endpoint that provides search capabilities, e.g. '/search.json?q=%query%&type=%type%'."
44511         },
44512         "warning": {
44513             "type": "string",
44514             "description": "A message that will be output by Composer as a warning when this source is consulted."
44515         }
44516     },
44517     "definitions": {
44518         "versions": {
44519             "type": "object",
44520             "description": "A hashmap of versions and their metadata.",
44521             "additionalProperties": { "$ref": "#/definitions/version" }
44522         },
44523         "version": {
44524             "type": "object",
44525             "oneOf": [
44526                 { "$ref": "#/definitions/package" },
44527                 { "$ref": "#/definitions/metapackage" }
44528             ]
44529         },
44530         "package-base": {
44531             "properties": {
44532                 "name": { "type": "string" },
44533                 "type": { "type": "string" },
44534                 "version": { "type": "string" },
44535                 "version_normalized": {
44536                     "type": "string",
44537                     "description": "Normalized version, optional but can save computational time on client side."
44538                 },
44539                 "autoload": { "type": "object" },
44540                 "require": { "type": "object" },
44541                 "replace": { "type": "object" },
44542                 "conflict": { "type": "object" },
44543                 "provide": { "type": "object" },
44544                 "time": { "type": "string" }
44545             },
44546             "additionalProperties": true
44547         },
44548         "package": {
44549             "allOf": [
44550                 { "$ref": "#/definitions/package-base" },
44551                 {
44552                     "properties": {
44553                         "dist": { "type": "object" },
44554                         "source": { "type": "object" }
44555                     }
44556                 },
44557                 { "oneOf": [
44558                     { "required": [ "name", "version", "source" ] },
44559                     { "required": [ "name", "version", "dist" ] }
44560                 ] }
44561             ]
44562         },
44563         "metapackage": {
44564             "allOf": [
44565                 { "$ref": "#/definitions/package-base" },
44566                 {
44567                     "properties": {
44568                         "type": { "type": "string", "enum": [ "metapackage" ] }
44569                     },
44570                     "required": [ "name", "version", "type" ]
44571                 }
44572             ]
44573         },
44574         "provider": {
44575             "type": "object",
44576             "properties": {
44577                 "sha256": {
44578                     "type": "string",
44579                     "description": "Hash value that can be used to validate the resource."
44580                 }
44581             }
44582         }
44583     }
44584 }
44585 {
44586     "$schema": "http://json-schema.org/draft-04/schema#",
44587     "name": "Package",
44588     "type": "object",
44589     "additionalProperties": false,
44590     "required": [ "name", "description" ],
44591     "properties": {
44592         "name": {
44593             "type": "string",
44594             "description": "Package name, including 'vendor-name/' prefix."
44595         },
44596         "type": {
44597             "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.",
44598             "type": "string"
44599         },
44600         "target-dir": {
44601             "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.",
44602             "type": "string"
44603         },
44604         "description": {
44605             "type": "string",
44606             "description": "Short package description."
44607         },
44608         "keywords": {
44609             "type": "array",
44610             "items": {
44611                 "type": "string",
44612                 "description": "A tag/keyword that this package relates to."
44613             }
44614         },
44615         "homepage": {
44616             "type": "string",
44617             "description": "Homepage URL for the project.",
44618             "format": "uri"
44619         },
44620         "version": {
44621             "type": "string",
44622             "description": "Package version, see https://getcomposer.org/doc/04-schema.md#version for more info on valid schemes."
44623         },
44624         "time": {
44625             "type": "string",
44626             "description": "Package release date, in 'YYYY-MM-DD', 'YYYY-MM-DD HH:MM:SS' or 'YYYY-MM-DDTHH:MM:SSZ' format."
44627         },
44628         "license": {
44629             "type": ["string", "array"],
44630             "description": "License name. Or an array of license names."
44631         },
44632         "authors": {
44633             "$ref": "#/definitions/authors"
44634         },
44635         "require": {
44636             "type": "object",
44637             "description": "This is a hash of package name (keys) and version constraints (values) that are required to run this package.",
44638             "additionalProperties": {
44639                 "type": "string"
44640             }
44641         },
44642         "replace": {
44643             "type": "object",
44644             "description": "This is a hash of package name (keys) and version constraints (values) that can be replaced by this package.",
44645             "additionalProperties": {
44646                 "type": "string"
44647             }
44648         },
44649         "conflict": {
44650             "type": "object",
44651             "description": "This is a hash of package name (keys) and version constraints (values) that conflict with this package.",
44652             "additionalProperties": {
44653                 "type": "string"
44654             }
44655         },
44656         "provide": {
44657             "type": "object",
44658             "description": "This is a hash of package name (keys) and version constraints (values) that this package provides in addition to this package's name.",
44659             "additionalProperties": {
44660                 "type": "string"
44661             }
44662         },
44663         "require-dev": {
44664             "type": "object",
44665             "description": "This is a hash of package name (keys) and version constraints (values) that this package requires for developing it (testing tools and such).",
44666             "additionalProperties": {
44667                 "type": "string"
44668             }
44669         },
44670         "suggest": {
44671             "type": "object",
44672             "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).",
44673             "additionalProperties": {
44674                 "type": "string"
44675             }
44676         },
44677         "config": {
44678             "type": "object",
44679             "description": "Composer options.",
44680             "properties": {
44681                 "process-timeout": {
44682                     "type": "integer",
44683                     "description": "The timeout in seconds for process executions, defaults to 300 (5mins)."
44684                 },
44685                 "use-include-path": {
44686                     "type": "boolean",
44687                     "description": "If true, the Composer autoloader will also look for classes in the PHP include path."
44688                 },
44689                 "preferred-install": {
44690                     "type": ["string", "object"],
44691                     "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\"}."
44692                 },
44693                 "notify-on-install": {
44694                     "type": "boolean",
44695                     "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."
44696                 },
44697                 "github-protocols": {
44698                     "type": "array",
44699                     "description": "A list of protocols to use for github.com clones, in priority order, defaults to [\"git\", \"https\", \"http\"].",
44700                     "items": {
44701                         "type": "string"
44702                     }
44703                 },
44704                 "github-oauth": {
44705                     "type": "object",
44706                     "description": "A hash of domain name => github API oauth tokens, typically {\"github.com\":\"<token>\"}.",
44707                     "additionalProperties": {
44708                         "type": "string"
44709                     }
44710                 },
44711                 "gitlab-oauth": {
44712                     "type": "object",
44713                     "description": "A hash of domain name => gitlab API oauth tokens, typically {\"gitlab.com\":\"<token>\"}.",
44714                     "additionalProperties": {
44715                         "type": "string"
44716                     }
44717                 },
44718                 "gitlab-token": {
44719                     "type": "object",
44720                     "description": "A hash of domain name => gitlab private tokens, typically {\"gitlab.com\":\"<token>\"}.",
44721                     "additionalProperties": true
44722                 },
44723                 "disable-tls": {
44724                     "type": "boolean",
44725                     "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."
44726                 },
44727                 "secure-http": {
44728                     "type": "boolean",
44729                     "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."
44730                 },
44731                 "cafile": {
44732                     "type": "string",
44733                     "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."
44734                 },
44735                 "capath": {
44736                     "type": "string",
44737                     "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."
44738                 },
44739                 "http-basic": {
44740                     "type": "object",
44741                     "description": "A hash of domain name => {\"username\": \"...\", \"password\": \"...\"}.",
44742                     "additionalProperties": {
44743                         "type": "object",
44744                         "required": ["username", "password"],
44745                         "properties": {
44746                             "username": {
44747                                 "type": "string",
44748                                 "description": "The username used for HTTP Basic authentication"
44749                             },
44750                             "password": {
44751                                 "type": "string",
44752                                 "description": "The password used for HTTP Basic authentication"
44753                             }
44754                         }
44755                     }
44756                 },
44757                 "store-auths": {
44758                     "type": ["string", "boolean"],
44759                     "description": "What to do after prompting for authentication, one of: true (store), false (do not store) or \"prompt\" (ask every time), defaults to prompt."
44760                 },
44761                 "platform": {
44762                     "type": "object",
44763                     "description": "This is a hash of package name (keys) and version (values) that will be used to mock the platform packages on this machine.",
44764                     "additionalProperties": {
44765                         "type": "string"
44766                     }
44767                 },
44768                 "vendor-dir": {
44769                     "type": "string",
44770                     "description": "The location where all packages are installed, defaults to \"vendor\"."
44771                 },
44772                 "bin-dir": {
44773                     "type": "string",
44774                     "description": "The location where all binaries are linked, defaults to \"vendor/bin\"."
44775                 },
44776                 "data-dir": {
44777                     "type": "string",
44778                     "description": "The location where old phar files are stored, defaults to \"$home\" except on XDG Base Directory compliant unixes."
44779                 },
44780                 "cache-dir": {
44781                     "type": "string",
44782                     "description": "The location where all caches are located, defaults to \"~/.composer/cache\" on *nix and \"%LOCALAPPDATA%\\Composer\" on windows."
44783                 },
44784                 "cache-files-dir": {
44785                     "type": "string",
44786                     "description": "The location where files (zip downloads) are cached, defaults to \"{$cache-dir}/files\"."
44787                 },
44788                 "cache-repo-dir": {
44789                     "type": "string",
44790                     "description": "The location where repo (git/hg repo clones) are cached, defaults to \"{$cache-dir}/repo\"."
44791                 },
44792                 "cache-vcs-dir": {
44793                     "type": "string",
44794                     "description": "The location where vcs infos (git clones, github api calls, etc. when reading vcs repos) are cached, defaults to \"{$cache-dir}/vcs\"."
44795                 },
44796                 "cache-ttl": {
44797                     "type": "integer",
44798                     "description": "The default cache time-to-live, defaults to 15552000 (6 months)."
44799                 },
44800                 "cache-files-ttl": {
44801                     "type": "integer",
44802                     "description": "The cache time-to-live for files, defaults to the value of cache-ttl."
44803                 },
44804                 "cache-files-maxsize": {
44805                     "type": ["string", "integer"],
44806                     "description": "The cache max size for the files cache, defaults to \"300MiB\"."
44807                 },
44808                 "bin-compat": {
44809                     "enum": ["auto", "full"],
44810                     "description": "The compatibility of the binaries, defaults to \"auto\" (automatically guessed) and can be \"full\" (compatible with both Windows and Unix-based systems)."
44811                 },
44812                 "discard-changes": {
44813                     "type": ["string", "boolean"],
44814                     "description": "The default style of handling dirty updates, defaults to false and can be any of true, false or \"stash\"."
44815                 },
44816                 "autoloader-suffix": {
44817                     "type": "string",
44818                     "description": "Optional string to be used as a suffix for the generated Composer autoloader. When null a random one will be generated."
44819                 },
44820                 "optimize-autoloader": {
44821                     "type": "boolean",
44822                     "description": "Always optimize when dumping the autoloader."
44823                 },
44824                 "prepend-autoloader": {
44825                     "type": "boolean",
44826                     "description": "If false, the composer autoloader will not be prepended to existing autoloaders, defaults to true."
44827                 },
44828                 "classmap-authoritative": {
44829                     "type": "boolean",
44830                     "description": "If true, the composer autoloader will not scan the filesystem for classes that are not found in the class map, defaults to false."
44831                 },
44832                 "apcu-autoloader": {
44833                     "type": "boolean",
44834                     "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."
44835                 },
44836                 "github-domains": {
44837                     "type": "array",
44838                     "description": "A list of domains to use in github mode. This is used for GitHub Enterprise setups, defaults to [\"github.com\"].",
44839                     "items": {
44840                         "type": "string"
44841                     }
44842                 },
44843                 "github-expose-hostname": {
44844                     "type": "boolean",
44845                     "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."
44846                 },
44847                 "gitlab-domains": {
44848                     "type": "array",
44849                     "description": "A list of domains to use in gitlab mode. This is used for custom GitLab setups, defaults to [\"gitlab.com\"].",
44850                     "items": {
44851                         "type": "string"
44852                     }
44853                 },
44854                 "archive-format": {
44855                     "type": "string",
44856                     "description": "The default archiving format when not provided on cli, defaults to \"tar\"."
44857                 },
44858                 "archive-dir": {
44859                     "type": "string",
44860                     "description": "The default archive path when not provided on cli, defaults to \".\"."
44861                 },
44862                 "htaccess-protect": {
44863                     "type": "boolean",
44864                     "description": "Defaults to true. If set to false, Composer will not create .htaccess files in the composer home, cache, and data directories."
44865                 }
44866             }
44867         },
44868         "extra": {
44869             "type": ["object", "array"],
44870             "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.",
44871             "additionalProperties": true
44872         },
44873         "autoload": {
44874             "$ref": "#/definitions/autoload"
44875         },
44876         "autoload-dev": {
44877             "type": "object",
44878             "description": "Description of additional autoload rules for development purpose (eg. a test suite).",
44879             "properties": {
44880                 "psr-0": {
44881                     "type": "object",
44882                     "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.",
44883                     "additionalProperties": {
44884                         "type": ["string", "array"],
44885                         "items": {
44886                             "type": "string"
44887                         }
44888                     }
44889                 },
44890                 "psr-4": {
44891                     "type": "object",
44892                     "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.",
44893                     "additionalProperties": {
44894                         "type": ["string", "array"],
44895                         "items": {
44896                             "type": "string"
44897                         }
44898                     }
44899                 },
44900                 "classmap": {
44901                     "type": "array",
44902                     "description": "This is an array of directories that contain classes to be included in the class-map generation process."
44903                 },
44904                 "files": {
44905                     "type": "array",
44906                     "description": "This is an array of files that are always required on every request."
44907                 }
44908             }
44909         },
44910         "archive": {
44911             "type": ["object"],
44912             "description": "Options for creating package archives for distribution.",
44913             "properties": {
44914                 "exclude": {
44915                     "type": "array",
44916                     "description": "A list of patterns for paths to exclude or include if prefixed with an exclamation mark."
44917                 }
44918             }
44919         },
44920         "repositories": {
44921             "type": ["object", "array"],
44922             "description": "A set of additional repositories where packages can be found.",
44923             "additionalProperties": {
44924                 "oneOf": [
44925                     { "$ref": "#/definitions/repository" },
44926                     { "type": "boolean", "enum": [false] }
44927                 ]
44928             },
44929             "items": {
44930                 "oneOf": [
44931                     { "$ref": "#/definitions/repository" },
44932                     {
44933                         "type": "object",
44934                         "additionalProperties": { "type": "boolean", "enum": [false] },
44935                         "minProperties": 1,
44936                         "maxProperties": 1
44937                     }
44938                 ]
44939             }
44940         },
44941         "minimum-stability": {
44942             "type": ["string"],
44943             "description": "The minimum stability the packages must have to be install-able. Possible values are: dev, alpha, beta, RC, stable.",
44944             "pattern": "^dev|alpha|beta|rc|RC|stable$"
44945         },
44946         "prefer-stable": {
44947             "type": ["boolean"],
44948             "description": "If set to true, stable packages will be preferred to dev packages when possible, even if the minimum-stability allows unstable packages."
44949         },
44950         "bin": {
44951             "type": ["array"],
44952             "description": "A set of files that should be treated as binaries and symlinked into bin-dir (from config).",
44953             "items": {
44954                 "type": "string"
44955             }
44956         },
44957         "include-path": {
44958             "type": ["array"],
44959             "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.",
44960             "items": {
44961                 "type": "string"
44962             }
44963         },
44964         "scripts": {
44965             "type": ["object"],
44966             "description": "Scripts listeners that will be executed before/after some events.",
44967             "properties": {
44968                 "pre-install-cmd": {
44969                     "type": ["array", "string"],
44970                     "description": "Occurs before the install command is executed, contains one or more Class::method callables or shell commands."
44971                 },
44972                 "post-install-cmd": {
44973                     "type": ["array", "string"],
44974                     "description": "Occurs after the install command is executed, contains one or more Class::method callables or shell commands."
44975                 },
44976                 "pre-update-cmd": {
44977                     "type": ["array", "string"],
44978                     "description": "Occurs before the update command is executed, contains one or more Class::method callables or shell commands."
44979                 },
44980                 "post-update-cmd": {
44981                     "type": ["array", "string"],
44982                     "description": "Occurs after the update command is executed, contains one or more Class::method callables or shell commands."
44983                 },
44984                 "pre-status-cmd": {
44985                     "type": ["array", "string"],
44986                     "description": "Occurs before the status command is executed, contains one or more Class::method callables or shell commands."
44987                 },
44988                 "post-status-cmd": {
44989                     "type": ["array", "string"],
44990                     "description": "Occurs after the status command is executed, contains one or more Class::method callables or shell commands."
44991                 },
44992                 "pre-package-install": {
44993                     "type": ["array", "string"],
44994                     "description": "Occurs before a package is installed, contains one or more Class::method callables or shell commands."
44995                 },
44996                 "post-package-install": {
44997                     "type": ["array", "string"],
44998                     "description": "Occurs after a package is installed, contains one or more Class::method callables or shell commands."
44999                 },
45000                 "pre-package-update": {
45001                     "type": ["array", "string"],
45002                     "description": "Occurs before a package is updated, contains one or more Class::method callables or shell commands."
45003                 },
45004                 "post-package-update": {
45005                     "type": ["array", "string"],
45006                     "description": "Occurs after a package is updated, contains one or more Class::method callables or shell commands."
45007                 },
45008                 "pre-package-uninstall": {
45009                     "type": ["array", "string"],
45010                     "description": "Occurs before a package has been uninstalled, contains one or more Class::method callables or shell commands."
45011                 },
45012                 "post-package-uninstall": {
45013                     "type": ["array", "string"],
45014                     "description": "Occurs after a package has been uninstalled, contains one or more Class::method callables or shell commands."
45015                 },
45016                 "pre-autoload-dump": {
45017                     "type": ["array", "string"],
45018                     "description": "Occurs before the autoloader is dumped, contains one or more Class::method callables or shell commands."
45019                 },
45020                 "post-autoload-dump": {
45021                     "type": ["array", "string"],
45022                     "description": "Occurs after the autoloader is dumped, contains one or more Class::method callables or shell commands."
45023                 },
45024                 "post-root-package-install": {
45025                     "type": ["array", "string"],
45026                     "description": "Occurs after the root-package is installed, contains one or more Class::method callables or shell commands."
45027                 },
45028                 "post-create-project-cmd": {
45029                     "type": ["array", "string"],
45030                     "description": "Occurs after the create-project command is executed, contains one or more Class::method callables or shell commands."
45031                 }
45032             }
45033         },
45034         "support": {
45035             "type": "object",
45036             "properties": {
45037                 "email": {
45038                     "type": "string",
45039                     "description": "Email address for support.",
45040                     "format": "email"
45041                 },
45042                 "issues": {
45043                     "type": "string",
45044                     "description": "URL to the issue tracker.",
45045                     "format": "uri"
45046                 },
45047                 "forum": {
45048                     "type": "string",
45049                     "description": "URL to the forum.",
45050                     "format": "uri"
45051                 },
45052                 "wiki": {
45053                     "type": "string",
45054                     "description": "URL to the wiki.",
45055                     "format": "uri"
45056                 },
45057                 "irc": {
45058                     "type": "string",
45059                     "description": "IRC channel for support, as irc://server/channel.",
45060                     "format": "uri"
45061                 },
45062                 "source": {
45063                     "type": "string",
45064                     "description": "URL to browse or download the sources.",
45065                     "format": "uri"
45066                 },
45067                 "docs": {
45068                     "type": "string",
45069                     "description": "URL to the documentation.",
45070                     "format": "uri"
45071                 },
45072                 "rss": {
45073                     "type": "string",
45074                     "description": "URL to the RSS feed.",
45075                     "format": "uri"
45076                 }
45077             }
45078         },
45079         "non-feature-branches": {
45080             "type": ["array"],
45081             "description": "A set of string or regex patterns for non-numeric branch names that will not be handled as feature branches.",
45082             "items": {
45083                 "type": "string"
45084             }
45085         },
45086         "abandoned": {
45087             "type": ["boolean", "string"],
45088             "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."
45089         },
45090         "_comment": {
45091             "type": ["array", "string"],
45092             "description": "A key to store comments in"
45093         }
45094     },
45095     "definitions": {
45096         "authors": {
45097             "type": "array",
45098             "description": "List of authors that contributed to the package. This is typically the main maintainers, not the full list.",
45099             "items": {
45100                 "type": "object",
45101                 "additionalProperties": false,
45102                 "required": [ "name"],
45103                 "properties": {
45104                     "name": {
45105                         "type": "string",
45106                         "description": "Full name of the author."
45107                     },
45108                     "email": {
45109                         "type": "string",
45110                         "description": "Email address of the author.",
45111                         "format": "email"
45112                     },
45113                     "homepage": {
45114                         "type": "string",
45115                         "description": "Homepage URL for the author.",
45116                         "format": "uri"
45117                     },
45118                     "role": {
45119                         "type": "string",
45120                         "description": "Author's role in the project."
45121                     }
45122                 }
45123             }
45124         },
45125         "autoload": {
45126             "type": "object",
45127             "description": "Description of how the package can be autoloaded.",
45128             "properties": {
45129                 "psr-0": {
45130                     "type": "object",
45131                     "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.",
45132                     "additionalProperties": {
45133                         "type": ["string", "array"],
45134                         "items": {
45135                             "type": "string"
45136                         }
45137                     }
45138                 },
45139                 "psr-4": {
45140                     "type": "object",
45141                     "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.",
45142                     "additionalProperties": {
45143                         "type": ["string", "array"],
45144                         "items": {
45145                             "type": "string"
45146                         }
45147                     }
45148                 },
45149                 "classmap": {
45150                     "type": "array",
45151                     "description": "This is an array of directories that contain classes to be included in the class-map generation process."
45152                 },
45153                 "files": {
45154                     "type": "array",
45155                     "description": "This is an array of files that are always required on every request."
45156                 },
45157                 "exclude-from-classmap": {
45158                     "type": "array",
45159                     "description": "This is an array of patterns to exclude from autoload classmap generation. (e.g. \"exclude-from-classmap\": [\"/test/\", \"/tests/\", \"/Tests/\"]"
45160                 }
45161             }
45162         },
45163         "repository": {
45164             "type": "object",
45165             "oneOf": [
45166                 { "$ref": "#/definitions/composer-repository" },
45167                 { "$ref": "#/definitions/vcs-repository" },
45168                 { "$ref": "#/definitions/path-repository" },
45169                 { "$ref": "#/definitions/artifact-repository" },
45170                 { "$ref": "#/definitions/pear-repository" },
45171                 { "$ref": "#/definitions/package-repository" }
45172             ]
45173         },
45174         "composer-repository": {
45175             "type": "object",
45176             "required": ["type", "url"],
45177             "properties": {
45178                 "type": { "type": "string", "enum": ["composer"] },
45179                 "url": { "type": "string" },
45180                 "options": {
45181                     "type": "object",
45182                     "additionalProperties": true
45183                 },
45184                 "allow_ssl_downgrade": { "type": "boolean" },
45185                 "force-lazy-providers": { "type": "boolean" }
45186             }
45187         },
45188         "vcs-repository": {
45189             "type": "object",
45190             "required": ["type", "url"],
45191             "properties": {
45192                 "type": { "type": "string", "enum": ["vcs", "github", "git", "gitlab", "git-bitbucket", "hg", "hg-bitbucket", "fossil", "perforce", "svn"] },
45193                 "url": { "type": "string" },
45194                 "no-api": { "type": "boolean" },
45195                 "secure-http": { "type": "boolean" },
45196                 "svn-cache-credentials": { "type": "boolean" },
45197                 "trunk-path": { "type": ["string", "boolean"] },
45198                 "branches-path": { "type": ["string", "boolean"] },
45199                 "tags-path": { "type": ["string", "boolean"] },
45200                 "package-path": { "type": "string" },
45201                 "depot": { "type": "string" },
45202                 "branch": { "type": "string" },
45203                 "unique_perforce_client_name": { "type": "string" },
45204                 "p4user": { "type": "string" },
45205                 "p4password": { "type": "string" }
45206             }
45207         },
45208         "path-repository": {
45209             "type": "object",
45210             "required": ["type", "url"],
45211             "properties": {
45212                 "type": { "type": "string", "enum": ["path"] },
45213                 "url": { "type": "string" },
45214                 "options": {
45215                     "type": "object",
45216                     "properties": {
45217                         "symlink": { "type": ["boolean", "null"] }
45218                     },
45219                     "additionalProperties": true
45220                 }
45221             }
45222         },
45223         "artifact-repository": {
45224             "type": "object",
45225             "required": ["type", "url"],
45226             "properties": {
45227                 "type": { "type": "string", "enum": ["artifact"] },
45228                 "url": { "type": "string" }
45229             }
45230         },
45231         "pear-repository": {
45232             "type": "object",
45233             "required": ["type", "url"],
45234             "properties": {
45235                 "type": { "type": "string", "enum": ["pear"] },
45236                 "url": { "type": "string" },
45237                 "vendor-alias": { "type": "string" }
45238             }
45239         },
45240         "package-repository": {
45241             "type": "object",
45242             "required": ["type", "package"],
45243             "properties": {
45244                 "type": { "type": "string", "enum": ["package"] },
45245                 "package": {
45246                     "oneOf": [
45247                         { "$ref": "#/definitions/inline-package" },
45248                         {
45249                             "type": "array",
45250                             "items": {
45251                                 "type": { "$ref": "#/definitions/inline-package" }
45252                             }
45253                         }
45254                     ]
45255                 }
45256             }
45257         },
45258         "inline-package": {
45259             "required": ["name", "version"],
45260             "properties": {
45261                 "name": {
45262                     "type": "string",
45263                     "description": "Package name, including 'vendor-name/' prefix."
45264                 },
45265                 "type": {
45266                     "type": "string"
45267                 },
45268                 "target-dir": {
45269                     "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.",
45270                     "type": "string"
45271                 },
45272                 "description": {
45273                     "type": "string"
45274                 },
45275                 "keywords": {
45276                     "type": "array",
45277                     "items": {
45278                         "type": "string"
45279                     }
45280                 },
45281                 "homepage": {
45282                     "type": "string",
45283                     "format": "uri"
45284                 },
45285                 "version": {
45286                     "type": "string"
45287                 },
45288                 "time": {
45289                     "type": "string"
45290                 },
45291                 "license": {
45292                     "type": [
45293                         "string",
45294                         "array"
45295                     ]
45296                 },
45297                 "authors": {
45298                     "$ref": "#/definitions/authors"
45299                 },
45300                 "require": {
45301                     "type": "object",
45302                     "additionalProperties": {
45303                         "type": "string"
45304                     }
45305                 },
45306                 "replace": {
45307                     "type": "object",
45308                     "additionalProperties": {
45309                         "type": "string"
45310                     }
45311                 },
45312                 "conflict": {
45313                     "type": "object",
45314                     "additionalProperties": {
45315                         "type": "string"
45316                     }
45317                 },
45318                 "provide": {
45319                     "type": "object",
45320                     "additionalProperties": {
45321                         "type": "string"
45322                     }
45323                 },
45324                 "require-dev": {
45325                     "type": "object",
45326                     "additionalProperties": {
45327                         "type": "string"
45328                     }
45329                 },
45330                 "suggest": {
45331                     "type": "object",
45332                     "additionalProperties": {
45333                         "type": "string"
45334                     }
45335                 },
45336                 "extra": {
45337                     "type": ["object", "array"],
45338                     "additionalProperties": true
45339                 },
45340                 "autoload": {
45341                     "$ref": "#/definitions/autoload"
45342                 },
45343                 "archive": {
45344                     "type": ["object"],
45345                     "properties": {
45346                         "exclude": {
45347                             "type": "array"
45348                         }
45349                     }
45350                 },
45351                 "bin": {
45352                     "type": ["array"],
45353                     "description": "A set of files that should be treated as binaries and symlinked into bin-dir (from config).",
45354                     "items": {
45355                         "type": "string"
45356                     }
45357                 },
45358                 "include-path": {
45359                     "type": ["array"],
45360                     "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.",
45361                     "items": {
45362                         "type": "string"
45363                     }
45364                 },
45365                 "source": {
45366                     "type": "object",
45367                     "required": ["type", "url", "reference"],
45368                     "properties": {
45369                         "type": {
45370                             "type": "string"
45371                         },
45372                         "url": {
45373                             "type": "string"
45374                         },
45375                         "reference": {
45376                             "type": "string"
45377                         },
45378                         "mirrors": {
45379                             "type": "array"
45380                         }
45381                     }
45382                 },
45383                 "dist": {
45384                     "type": "object",
45385                     "required": ["type", "url"],
45386                     "properties": {
45387                         "type": {
45388                             "type": "string"
45389                         },
45390                         "url": {
45391                             "type": "string"
45392                         },
45393                         "reference": {
45394                             "type": "string"
45395                         },
45396                         "shasum": {
45397                             "type": "string"
45398                         },
45399                         "mirrors": {
45400                             "type": "array"
45401                         }
45402                     }
45403                 }
45404             },
45405             "additionalProperties": true
45406         }
45407     }
45408 }
45409 {
45410     "389-exception": [
45411         "389 Directory Server\nException"
45412     ],
45413     "Autoconf-exception-2.0": [
45414         "Autoconf exception 2.0"
45415     ],
45416     "Autoconf-exception-3.0": [
45417         "Autoconf exception 3.0"
45418     ],
45419     "Bison-exception-2.2": [
45420         "Bison exception 2.2"
45421     ],
45422     "Classpath-exception-2.0": [
45423         "Classpath exception 2.0"
45424     ],
45425     "CLISP-exception-2.0": [
45426         "CLISP exception 2.0"
45427     ],
45428     "DigiRule-FOSS-exception": [
45429         "DigiRule FOSS License Exception"
45430     ],
45431     "eCos-exception-2.0": [
45432         "eCos exception 2.0"
45433     ],
45434     "Fawkes-Runtime-exception": [
45435         "Fawkes Runtime Exception"
45436     ],
45437     "FLTK-exception": [
45438         "FLTK exception"
45439     ],
45440     "Font-exception-2.0": [
45441         "Font exception 2.0"
45442     ],
45443     "freertos-exception-2.0": [
45444         "FreeRTOS Exception 2.0"
45445     ],
45446     "GCC-exception-2.0": [
45447         "GCC Runtime Library exception 2.0"
45448     ],
45449     "GCC-exception-3.1": [
45450         "GCC Runtime Library exception 3.1"
45451     ],
45452     "gnu-javamail-exception": [
45453         "GNU JavaMail exception"
45454     ],
45455     "i2p-gpl-java-exception": [
45456         "i2p GPL+Java Exception"
45457     ],
45458     "Libtool-exception": [
45459         "Libtool Exception"
45460     ],
45461     "LZMA-exception": [
45462         "LZMA exception"
45463     ],
45464     "mif-exception": [
45465         "Macros and Inline Functions Exception"
45466     ],
45467     "Nokia-Qt-exception-1.1": [
45468         "Nokia Qt LGPL exception 1.1"
45469     ],
45470     "OCCT-exception-1.0": [
45471         "Open CASCADE Exception 1.0"
45472     ],
45473     "openvpn-openssl-exception": [
45474         "OpenVPN OpenSSL Exception"
45475     ],
45476     "Qwt-exception-1.0": [
45477         "Qwt exception 1.0"
45478     ],
45479     "u-boot-exception-2.0": [
45480         "U-Boot exception 2.0"
45481     ],
45482     "WxWindows-exception-3.1": [
45483         "WxWindows Library Exception 3.1"
45484     ]
45485 }{
45486     "0BSD": [
45487         "BSD Zero Clause License",
45488         true
45489     ],
45490     "AAL": [
45491         "Attribution Assurance License",
45492         true
45493     ],
45494     "Abstyles": [
45495         "Abstyles License",
45496         false
45497     ],
45498     "Adobe-2006": [
45499         "Adobe Systems Incorporated Source Code License Agreement",
45500         false
45501     ],
45502     "Adobe-Glyph": [
45503         "Adobe Glyph List License",
45504         false
45505     ],
45506     "ADSL": [
45507         "Amazon Digital Services License",
45508         false
45509     ],
45510     "AFL-1.1": [
45511         "Academic Free License v1.1",
45512         true
45513     ],
45514     "AFL-1.2": [
45515         "Academic Free License v1.2",
45516         true
45517     ],
45518     "AFL-2.0": [
45519         "Academic Free License v2.0",
45520         true
45521     ],
45522     "AFL-2.1": [
45523         "Academic Free License v2.1",
45524         true
45525     ],
45526     "AFL-3.0": [
45527         "Academic Free License v3.0",
45528         true
45529     ],
45530     "Afmparse": [
45531         "Afmparse License",
45532         false
45533     ],
45534     "AGPL-1.0": [
45535         "Affero General Public License v1.0",
45536         false
45537     ],
45538     "AGPL-3.0": [
45539         "GNU Affero General Public License v3.0",
45540         true
45541     ],
45542     "Aladdin": [
45543         "Aladdin Free Public License",
45544         false
45545     ],
45546     "AMDPLPA": [
45547         "AMD's plpa_map.c License",
45548         false
45549     ],
45550     "AML": [
45551         "Apple MIT License",
45552         false
45553     ],
45554     "AMPAS": [
45555         "Academy of Motion Picture Arts and Sciences BSD",
45556         false
45557     ],
45558     "ANTLR-PD": [
45559         "ANTLR Software Rights Notice",
45560         false
45561     ],
45562     "Apache-1.0": [
45563         "Apache License 1.0",
45564         false
45565     ],
45566     "Apache-1.1": [
45567         "Apache License 1.1",
45568         true
45569     ],
45570     "Apache-2.0": [
45571         "Apache License 2.0",
45572         true
45573     ],
45574     "APAFML": [
45575         "Adobe Postscript AFM License",
45576         false
45577     ],
45578     "APL-1.0": [
45579         "Adaptive Public License 1.0",
45580         true
45581     ],
45582     "APSL-1.0": [
45583         "Apple Public Source License 1.0",
45584         true
45585     ],
45586     "APSL-1.1": [
45587         "Apple Public Source License 1.1",
45588         true
45589     ],
45590     "APSL-1.2": [
45591         "Apple Public Source License 1.2",
45592         true
45593     ],
45594     "APSL-2.0": [
45595         "Apple Public Source License 2.0",
45596         true
45597     ],
45598     "Artistic-1.0": [
45599         "Artistic License 1.0",
45600         true
45601     ],
45602     "Artistic-1.0-cl8": [
45603         "Artistic License 1.0 w/clause 8",
45604         true
45605     ],
45606     "Artistic-1.0-Perl": [
45607         "Artistic License 1.0 (Perl)",
45608         true
45609     ],
45610     "Artistic-2.0": [
45611         "Artistic License 2.0",
45612         true
45613     ],
45614     "Bahyph": [
45615         "Bahyph License",
45616         false
45617     ],
45618     "Barr": [
45619         "Barr License",
45620         false
45621     ],
45622     "Beerware": [
45623         "Beerware License",
45624         false
45625     ],
45626     "BitTorrent-1.0": [
45627         "BitTorrent Open Source License v1.0",
45628         false
45629     ],
45630     "BitTorrent-1.1": [
45631         "BitTorrent Open Source License v1.1",
45632         false
45633     ],
45634     "Borceux": [
45635         "Borceux license",
45636         false
45637     ],
45638     "BSD-2-Clause": [
45639         "BSD 2-clause \"Simplified\" License",
45640         true
45641     ],
45642     "BSD-2-Clause-FreeBSD": [
45643         "BSD 2-clause FreeBSD License",
45644         false
45645     ],
45646     "BSD-2-Clause-NetBSD": [
45647         "BSD 2-clause NetBSD License",
45648         false
45649     ],
45650     "BSD-3-Clause": [
45651         "BSD 3-clause \"New\" or \"Revised\" License",
45652         true
45653     ],
45654     "BSD-3-Clause-Attribution": [
45655         "BSD with attribution",
45656         false
45657     ],
45658     "BSD-3-Clause-Clear": [
45659         "BSD 3-clause Clear License",
45660         false
45661     ],
45662     "BSD-3-Clause-LBNL": [
45663         "Lawrence Berkeley National Labs BSD variant license",
45664         false
45665     ],
45666     "BSD-3-Clause-No-Nuclear-License": [
45667         "BSD 3-Clause No Nuclear License",
45668         false
45669     ],
45670     "BSD-3-Clause-No-Nuclear-License-2014": [
45671         "BSD 3-Clause No Nuclear License 2014",
45672         false
45673     ],
45674     "BSD-3-Clause-No-Nuclear-Warranty": [
45675         "BSD 3-Clause No Nuclear Warranty",
45676         false
45677     ],
45678     "BSD-4-Clause": [
45679         "BSD 4-clause \"Original\" or \"Old\" License",
45680         false
45681     ],
45682     "BSD-4-Clause-UC": [
45683         "BSD-4-Clause (University of California-Specific)",
45684         false
45685     ],
45686     "BSD-Protection": [
45687         "BSD Protection License",
45688         false
45689     ],
45690     "BSD-Source-Code": [
45691         "BSD Source Code Attribution",
45692         false
45693     ],
45694     "BSL-1.0": [
45695         "Boost Software License 1.0",
45696         true
45697     ],
45698     "bzip2-1.0.5": [
45699         "bzip2 and libbzip2 License v1.0.5",
45700         false
45701     ],
45702     "bzip2-1.0.6": [
45703         "bzip2 and libbzip2 License v1.0.6",
45704         false
45705     ],
45706     "Caldera": [
45707         "Caldera License",
45708         false
45709     ],
45710     "CATOSL-1.1": [
45711         "Computer Associates Trusted Open Source License 1.1",
45712         true
45713     ],
45714     "CC-BY-1.0": [
45715         "Creative Commons Attribution 1.0",
45716         false
45717     ],
45718     "CC-BY-2.0": [
45719         "Creative Commons Attribution 2.0",
45720         false
45721     ],
45722     "CC-BY-2.5": [
45723         "Creative Commons Attribution 2.5",
45724         false
45725     ],
45726     "CC-BY-3.0": [
45727         "Creative Commons Attribution 3.0",
45728         false
45729     ],
45730     "CC-BY-4.0": [
45731         "Creative Commons Attribution 4.0",
45732         false
45733     ],
45734     "CC-BY-NC-1.0": [
45735         "Creative Commons Attribution Non Commercial 1.0",
45736         false
45737     ],
45738     "CC-BY-NC-2.0": [
45739         "Creative Commons Attribution Non Commercial 2.0",
45740         false
45741     ],
45742     "CC-BY-NC-2.5": [
45743         "Creative Commons Attribution Non Commercial 2.5",
45744         false
45745     ],
45746     "CC-BY-NC-3.0": [
45747         "Creative Commons Attribution Non Commercial 3.0",
45748         false
45749     ],
45750     "CC-BY-NC-4.0": [
45751         "Creative Commons Attribution Non Commercial 4.0",
45752         false
45753     ],
45754     "CC-BY-NC-ND-1.0": [
45755         "Creative Commons Attribution Non Commercial No Derivatives 1.0",
45756         false
45757     ],
45758     "CC-BY-NC-ND-2.0": [
45759         "Creative Commons Attribution Non Commercial No Derivatives 2.0",
45760         false
45761     ],
45762     "CC-BY-NC-ND-2.5": [
45763         "Creative Commons Attribution Non Commercial No Derivatives 2.5",
45764         false
45765     ],
45766     "CC-BY-NC-ND-3.0": [
45767         "Creative Commons Attribution Non Commercial No Derivatives 3.0",
45768         false
45769     ],
45770     "CC-BY-NC-ND-4.0": [
45771         "Creative Commons Attribution Non Commercial No Derivatives 4.0",
45772         false
45773     ],
45774     "CC-BY-NC-SA-1.0": [
45775         "Creative Commons Attribution Non Commercial Share Alike 1.0",
45776         false
45777     ],
45778     "CC-BY-NC-SA-2.0": [
45779         "Creative Commons Attribution Non Commercial Share Alike 2.0",
45780         false
45781     ],
45782     "CC-BY-NC-SA-2.5": [
45783         "Creative Commons Attribution Non Commercial Share Alike 2.5",
45784         false
45785     ],
45786     "CC-BY-NC-SA-3.0": [
45787         "Creative Commons Attribution Non Commercial Share Alike 3.0",
45788         false
45789     ],
45790     "CC-BY-NC-SA-4.0": [
45791         "Creative Commons Attribution Non Commercial Share Alike 4.0",
45792         false
45793     ],
45794     "CC-BY-ND-1.0": [
45795         "Creative Commons Attribution No Derivatives 1.0",
45796         false
45797     ],
45798     "CC-BY-ND-2.0": [
45799         "Creative Commons Attribution No Derivatives 2.0",
45800         false
45801     ],
45802     "CC-BY-ND-2.5": [
45803         "Creative Commons Attribution No Derivatives 2.5",
45804         false
45805     ],
45806     "CC-BY-ND-3.0": [
45807         "Creative Commons Attribution No Derivatives 3.0",
45808         false
45809     ],
45810     "CC-BY-ND-4.0": [
45811         "Creative Commons Attribution No Derivatives 4.0",
45812         false
45813     ],
45814     "CC-BY-SA-1.0": [
45815         "Creative Commons Attribution Share Alike 1.0",
45816         false
45817     ],
45818     "CC-BY-SA-2.0": [
45819         "Creative Commons Attribution Share Alike 2.0",
45820         false
45821     ],
45822     "CC-BY-SA-2.5": [
45823         "Creative Commons Attribution Share Alike 2.5",
45824         false
45825     ],
45826     "CC-BY-SA-3.0": [
45827         "Creative Commons Attribution Share Alike 3.0",
45828         false
45829     ],
45830     "CC-BY-SA-4.0": [
45831         "Creative Commons Attribution Share Alike 4.0",
45832         false
45833     ],
45834     "CC0-1.0": [
45835         "Creative Commons Zero v1.0 Universal",
45836         false
45837     ],
45838     "CDDL-1.0": [
45839         "Common Development and Distribution License 1.0",
45840         true
45841     ],
45842     "CDDL-1.1": [
45843         "Common Development and Distribution License 1.1",
45844         false
45845     ],
45846     "CECILL-1.0": [
45847         "CeCILL Free Software License Agreement v1.0",
45848         false
45849     ],
45850     "CECILL-1.1": [
45851         "CeCILL Free Software License Agreement v1.1",
45852         false
45853     ],
45854     "CECILL-2.0": [
45855         "CeCILL Free Software License Agreement v2.0",
45856         false
45857     ],
45858     "CECILL-2.1": [
45859         "CeCILL Free Software License Agreement v2.1",
45860         true
45861     ],
45862     "CECILL-B": [
45863         "CeCILL-B Free Software License Agreement",
45864         false
45865     ],
45866     "CECILL-C": [
45867         "CeCILL-C Free Software License Agreement",
45868         false
45869     ],
45870     "ClArtistic": [
45871         "Clarified Artistic License",
45872         false
45873     ],
45874     "CNRI-Jython": [
45875         "CNRI Jython License",
45876         false
45877     ],
45878     "CNRI-Python": [
45879         "CNRI Python License",
45880         true
45881     ],
45882     "CNRI-Python-GPL-Compatible": [
45883         "CNRI Python Open Source GPL Compatible License Agreement",
45884         false
45885     ],
45886     "Condor-1.1": [
45887         "Condor Public License v1.1",
45888         false
45889     ],
45890     "CPAL-1.0": [
45891         "Common Public Attribution License 1.0",
45892         true
45893     ],
45894     "CPL-1.0": [
45895         "Common Public License 1.0",
45896         true
45897     ],
45898     "CPOL-1.02": [
45899         "Code Project Open License 1.02",
45900         false
45901     ],
45902     "Crossword": [
45903         "Crossword License",
45904         false
45905     ],
45906     "CrystalStacker": [
45907         "CrystalStacker License",
45908         false
45909     ],
45910     "CUA-OPL-1.0": [
45911         "CUA Office Public License v1.0",
45912         true
45913     ],
45914     "Cube": [
45915         "Cube License",
45916         false
45917     ],
45918     "curl": [
45919         "curl License",
45920         false
45921     ],
45922     "D-FSL-1.0": [
45923         "Deutsche Freie Software Lizenz",
45924         false
45925     ],
45926     "diffmark": [
45927         "diffmark license",
45928         false
45929     ],
45930     "DOC": [
45931         "DOC License",
45932         false
45933     ],
45934     "Dotseqn": [
45935         "Dotseqn License",
45936         false
45937     ],
45938     "DSDP": [
45939         "DSDP License",
45940         false
45941     ],
45942     "dvipdfm": [
45943         "dvipdfm License",
45944         false
45945     ],
45946     "ECL-1.0": [
45947         "Educational Community License v1.0",
45948         true
45949     ],
45950     "ECL-2.0": [
45951         "Educational Community License v2.0",
45952         true
45953     ],
45954     "EFL-1.0": [
45955         "Eiffel Forum License v1.0",
45956         true
45957     ],
45958     "EFL-2.0": [
45959         "Eiffel Forum License v2.0",
45960         true
45961     ],
45962     "eGenix": [
45963         "eGenix.com Public License 1.1.0",
45964         false
45965     ],
45966     "Entessa": [
45967         "Entessa Public License v1.0",
45968         true
45969     ],
45970     "EPL-1.0": [
45971         "Eclipse Public License 1.0",
45972         true
45973     ],
45974     "ErlPL-1.1": [
45975         "Erlang Public License v1.1",
45976         false
45977     ],
45978     "EUDatagrid": [
45979         "EU DataGrid Software License",
45980         true
45981     ],
45982     "EUPL-1.0": [
45983         "European Union Public License 1.0",
45984         false
45985     ],
45986     "EUPL-1.1": [
45987         "European Union Public License 1.1",
45988         true
45989     ],
45990     "Eurosym": [
45991         "Eurosym License",
45992         false
45993     ],
45994     "Fair": [
45995         "Fair License",
45996         true
45997     ],
45998     "Frameworx-1.0": [
45999         "Frameworx Open License 1.0",
46000         true
46001     ],
46002     "FreeImage": [
46003         "FreeImage Public License v1.0",
46004         false
46005     ],
46006     "FSFAP": [
46007         "FSF All Permissive License",
46008         false
46009     ],
46010     "FSFUL": [
46011         "FSF Unlimited License",
46012         false
46013     ],
46014     "FSFULLR": [
46015         "FSF Unlimited License (with License Retention)",
46016         false
46017     ],
46018     "FTL": [
46019         "Freetype Project License",
46020         false
46021     ],
46022     "GFDL-1.1": [
46023         "GNU Free Documentation License v1.1",
46024         false
46025     ],
46026     "GFDL-1.2": [
46027         "GNU Free Documentation License v1.2",
46028         false
46029     ],
46030     "GFDL-1.3": [
46031         "GNU Free Documentation License v1.3",
46032         false
46033     ],
46034     "Giftware": [
46035         "Giftware License",
46036         false
46037     ],
46038     "GL2PS": [
46039         "GL2PS License",
46040         false
46041     ],
46042     "Glide": [
46043         "3dfx Glide License",
46044         false
46045     ],
46046     "Glulxe": [
46047         "Glulxe License",
46048         false
46049     ],
46050     "gnuplot": [
46051         "gnuplot License",
46052         false
46053     ],
46054     "GPL-1.0": [
46055         "GNU General Public License v1.0 only",
46056         false
46057     ],
46058     "GPL-2.0": [
46059         "GNU General Public License v2.0 only",
46060         true
46061     ],
46062     "GPL-3.0": [
46063         "GNU General Public License v3.0 only",
46064         true
46065     ],
46066     "gSOAP-1.3b": [
46067         "gSOAP Public License v1.3b",
46068         false
46069     ],
46070     "HaskellReport": [
46071         "Haskell Language Report License",
46072         false
46073     ],
46074     "HPND": [
46075         "Historic Permission Notice and Disclaimer",
46076         true
46077     ],
46078     "IBM-pibs": [
46079         "IBM PowerPC Initialization and Boot Software",
46080         false
46081     ],
46082     "ICU": [
46083         "ICU License",
46084         false
46085     ],
46086     "IJG": [
46087         "Independent JPEG Group License",
46088         false
46089     ],
46090     "ImageMagick": [
46091         "ImageMagick License",
46092         false
46093     ],
46094     "iMatix": [
46095         "iMatix Standard Function Library Agreement",
46096         false
46097     ],
46098     "Imlib2": [
46099         "Imlib2 License",
46100         false
46101     ],
46102     "Info-ZIP": [
46103         "Info-ZIP License",
46104         false
46105     ],
46106     "Intel": [
46107         "Intel Open Source License",
46108         true
46109     ],
46110     "Intel-ACPI": [
46111         "Intel ACPI Software License Agreement",
46112         false
46113     ],
46114     "Interbase-1.0": [
46115         "Interbase Public License v1.0",
46116         false
46117     ],
46118     "IPA": [
46119         "IPA Font License",
46120         true
46121     ],
46122     "IPL-1.0": [
46123         "IBM Public License v1.0",
46124         true
46125     ],
46126     "ISC": [
46127         "ISC License",
46128         true
46129     ],
46130     "JasPer-2.0": [
46131         "JasPer License",
46132         false
46133     ],
46134     "JSON": [
46135         "JSON License",
46136         false
46137     ],
46138     "LAL-1.2": [
46139         "Licence Art Libre 1.2",
46140         false
46141     ],
46142     "LAL-1.3": [
46143         "Licence Art Libre 1.3",
46144         false
46145     ],
46146     "Latex2e": [
46147         "Latex2e License",
46148         false
46149     ],
46150     "Leptonica": [
46151         "Leptonica License",
46152         false
46153     ],
46154     "LGPL-2.0": [
46155         "GNU Library General Public License v2 only",
46156         true
46157     ],
46158     "LGPL-2.1": [
46159         "GNU Lesser General Public License v2.1 only",
46160         true
46161     ],
46162     "LGPL-3.0": [
46163         "GNU Lesser General Public License v3.0 only",
46164         true
46165     ],
46166     "LGPLLR": [
46167         "Lesser General Public License For Linguistic Resources",
46168         false
46169     ],
46170     "Libpng": [
46171         "libpng License",
46172         false
46173     ],
46174     "libtiff": [
46175         "libtiff License",
46176         false
46177     ],
46178     "LiLiQ-P-1.1": [
46179         "Licence Libre du Qu\u00e9bec \u2013 Permissive version 1.1",
46180         true
46181     ],
46182     "LiLiQ-R-1.1": [
46183         "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 version 1.1",
46184         true
46185     ],
46186     "LiLiQ-Rplus-1.1": [
46187         "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 forte version 1.1",
46188         true
46189     ],
46190     "LPL-1.0": [
46191         "Lucent Public License Version 1.0",
46192         true
46193     ],
46194     "LPL-1.02": [
46195         "Lucent Public License v1.02",
46196         true
46197     ],
46198     "LPPL-1.0": [
46199         "LaTeX Project Public License v1.0",
46200         false
46201     ],
46202     "LPPL-1.1": [
46203         "LaTeX Project Public License v1.1",
46204         false
46205     ],
46206     "LPPL-1.2": [
46207         "LaTeX Project Public License v1.2",
46208         false
46209     ],
46210     "LPPL-1.3a": [
46211         "LaTeX Project Public License v1.3a",
46212         false
46213     ],
46214     "LPPL-1.3c": [
46215         "LaTeX Project Public License v1.3c",
46216         true
46217     ],
46218     "MakeIndex": [
46219         "MakeIndex License",
46220         false
46221     ],
46222     "MirOS": [
46223         "MirOS Licence",
46224         true
46225     ],
46226     "MIT": [
46227         "MIT License",
46228         true
46229     ],
46230     "MIT-advertising": [
46231         "Enlightenment License (e16)",
46232         false
46233     ],
46234     "MIT-CMU": [
46235         "CMU License",
46236         false
46237     ],
46238     "MIT-enna": [
46239         "enna License",
46240         false
46241     ],
46242     "MIT-feh": [
46243         "feh License",
46244         false
46245     ],
46246     "MITNFA": [
46247         "MIT +no-false-attribs license",
46248         false
46249     ],
46250     "Motosoto": [
46251         "Motosoto License",
46252         true
46253     ],
46254     "mpich2": [
46255         "mpich2 License",
46256         false
46257     ],
46258     "MPL-1.0": [
46259         "Mozilla Public License 1.0",
46260         true
46261     ],
46262     "MPL-1.1": [
46263         "Mozilla Public License 1.1",
46264         true
46265     ],
46266     "MPL-2.0": [
46267         "Mozilla Public License 2.0",
46268         true
46269     ],
46270     "MPL-2.0-no-copyleft-exception": [
46271         "Mozilla Public License 2.0 (no copyleft exception)",
46272         true
46273     ],
46274     "MS-PL": [
46275         "Microsoft Public License",
46276         true
46277     ],
46278     "MS-RL": [
46279         "Microsoft Reciprocal License",
46280         true
46281     ],
46282     "MTLL": [
46283         "Matrix Template Library License",
46284         false
46285     ],
46286     "Multics": [
46287         "Multics License",
46288         true
46289     ],
46290     "Mup": [
46291         "Mup License",
46292         false
46293     ],
46294     "NASA-1.3": [
46295         "NASA Open Source Agreement 1.3",
46296         true
46297     ],
46298     "Naumen": [
46299         "Naumen Public License",
46300         true
46301     ],
46302     "NBPL-1.0": [
46303         "Net Boolean Public License v1",
46304         false
46305     ],
46306     "NCSA": [
46307         "University of Illinois/NCSA Open Source License",
46308         true
46309     ],
46310     "Net-SNMP": [
46311         "Net-SNMP License",
46312         false
46313     ],
46314     "NetCDF": [
46315         "NetCDF license",
46316         false
46317     ],
46318     "Newsletr": [
46319         "Newsletr License",
46320         false
46321     ],
46322     "NGPL": [
46323         "Nethack General Public License",
46324         true
46325     ],
46326     "NLOD-1.0": [
46327         "Norwegian Licence for Open Government Data",
46328         false
46329     ],
46330     "NLPL": [
46331         "No Limit Public License",
46332         false
46333     ],
46334     "Nokia": [
46335         "Nokia Open Source License",
46336         true
46337     ],
46338     "NOSL": [
46339         "Netizen Open Source License",
46340         false
46341     ],
46342     "Noweb": [
46343         "Noweb License",
46344         false
46345     ],
46346     "NPL-1.0": [
46347         "Netscape Public License v1.0",
46348         false
46349     ],
46350     "NPL-1.1": [
46351         "Netscape Public License v1.1",
46352         false
46353     ],
46354     "NPOSL-3.0": [
46355         "Non-Profit Open Software License 3.0",
46356         true
46357     ],
46358     "NRL": [
46359         "NRL License",
46360         false
46361     ],
46362     "NTP": [
46363         "NTP License",
46364         true
46365     ],
46366     "Nunit": [
46367         "Nunit License",
46368         false
46369     ],
46370     "OCCT-PL": [
46371         "Open CASCADE Technology Public License",
46372         false
46373     ],
46374     "OCLC-2.0": [
46375         "OCLC Research Public License 2.0",
46376         true
46377     ],
46378     "ODbL-1.0": [
46379         "ODC Open Database License v1.0",
46380         false
46381     ],
46382     "OFL-1.0": [
46383         "SIL Open Font License 1.0",
46384         false
46385     ],
46386     "OFL-1.1": [
46387         "SIL Open Font License 1.1",
46388         true
46389     ],
46390     "OGTSL": [
46391         "Open Group Test Suite License",
46392         true
46393     ],
46394     "OLDAP-1.1": [
46395         "Open LDAP Public License v1.1",
46396         false
46397     ],
46398     "OLDAP-1.2": [
46399         "Open LDAP Public License v1.2",
46400         false
46401     ],
46402     "OLDAP-1.3": [
46403         "Open LDAP Public License v1.3",
46404         false
46405     ],
46406     "OLDAP-1.4": [
46407         "Open LDAP Public License v1.4",
46408         false
46409     ],
46410     "OLDAP-2.0": [
46411         "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)",
46412         false
46413     ],
46414     "OLDAP-2.0.1": [
46415         "Open LDAP Public License v2.0.1",
46416         false
46417     ],
46418     "OLDAP-2.1": [
46419         "Open LDAP Public License v2.1",
46420         false
46421     ],
46422     "OLDAP-2.2": [
46423         "Open LDAP Public License v2.2",
46424         false
46425     ],
46426     "OLDAP-2.2.1": [
46427         "Open LDAP Public License v2.2.1",
46428         false
46429     ],
46430     "OLDAP-2.2.2": [
46431         "Open LDAP Public License  2.2.2",
46432         false
46433     ],
46434     "OLDAP-2.3": [
46435         "Open LDAP Public License v2.3",
46436         false
46437     ],
46438     "OLDAP-2.4": [
46439         "Open LDAP Public License v2.4",
46440         false
46441     ],
46442     "OLDAP-2.5": [
46443         "Open LDAP Public License v2.5",
46444         false
46445     ],
46446     "OLDAP-2.6": [
46447         "Open LDAP Public License v2.6",
46448         false
46449     ],
46450     "OLDAP-2.7": [
46451         "Open LDAP Public License v2.7",
46452         false
46453     ],
46454     "OLDAP-2.8": [
46455         "Open LDAP Public License v2.8",
46456         false
46457     ],
46458     "OML": [
46459         "Open Market License",
46460         false
46461     ],
46462     "OpenSSL": [
46463         "OpenSSL License",
46464         false
46465     ],
46466     "OPL-1.0": [
46467         "Open Public License v1.0",
46468         false
46469     ],
46470     "OSET-PL-2.1": [
46471         "OSET Public License version 2.1",
46472         true
46473     ],
46474     "OSL-1.0": [
46475         "Open Software License 1.0",
46476         true
46477     ],
46478     "OSL-1.1": [
46479         "Open Software License 1.1",
46480         false
46481     ],
46482     "OSL-2.0": [
46483         "Open Software License 2.0",
46484         true
46485     ],
46486     "OSL-2.1": [
46487         "Open Software License 2.1",
46488         true
46489     ],
46490     "OSL-3.0": [
46491         "Open Software License 3.0",
46492         true
46493     ],
46494     "PDDL-1.0": [
46495         "ODC Public Domain Dedication & License 1.0",
46496         false
46497     ],
46498     "PHP-3.0": [
46499         "PHP License v3.0",
46500         true
46501     ],
46502     "PHP-3.01": [
46503         "PHP License v3.01",
46504         false
46505     ],
46506     "Plexus": [
46507         "Plexus Classworlds License",
46508         false
46509     ],
46510     "PostgreSQL": [
46511         "PostgreSQL License",
46512         true
46513     ],
46514     "psfrag": [
46515         "psfrag License",
46516         false
46517     ],
46518     "psutils": [
46519         "psutils License",
46520         false
46521     ],
46522     "Python-2.0": [
46523         "Python License 2.0",
46524         true
46525     ],
46526     "Qhull": [
46527         "Qhull License",
46528         false
46529     ],
46530     "QPL-1.0": [
46531         "Q Public License 1.0",
46532         true
46533     ],
46534     "Rdisc": [
46535         "Rdisc License",
46536         false
46537     ],
46538     "RHeCos-1.1": [
46539         "Red Hat eCos Public License v1.1",
46540         false
46541     ],
46542     "RPL-1.1": [
46543         "Reciprocal Public License 1.1",
46544         true
46545     ],
46546     "RPL-1.5": [
46547         "Reciprocal Public License 1.5",
46548         true
46549     ],
46550     "RPSL-1.0": [
46551         "RealNetworks Public Source License v1.0",
46552         true
46553     ],
46554     "RSA-MD": [
46555         "RSA Message-Digest License",
46556         false
46557     ],
46558     "RSCPL": [
46559         "Ricoh Source Code Public License",
46560         true
46561     ],
46562     "Ruby": [
46563         "Ruby License",
46564         false
46565     ],
46566     "SAX-PD": [
46567         "Sax Public Domain Notice",
46568         false
46569     ],
46570     "Saxpath": [
46571         "Saxpath License",
46572         false
46573     ],
46574     "SCEA": [
46575         "SCEA Shared Source License",
46576         false
46577     ],
46578     "Sendmail": [
46579         "Sendmail License",
46580         false
46581     ],
46582     "SGI-B-1.0": [
46583         "SGI Free Software License B v1.0",
46584         false
46585     ],
46586     "SGI-B-1.1": [
46587         "SGI Free Software License B v1.1",
46588         false
46589     ],
46590     "SGI-B-2.0": [
46591         "SGI Free Software License B v2.0",
46592         false
46593     ],
46594     "SimPL-2.0": [
46595         "Simple Public License 2.0",
46596         true
46597     ],
46598     "SISSL": [
46599         "Sun Industry Standards Source License v1.1",
46600         true
46601     ],
46602     "SISSL-1.2": [
46603         "Sun Industry Standards Source License v1.2",
46604         false
46605     ],
46606     "Sleepycat": [
46607         "Sleepycat License",
46608         true
46609     ],
46610     "SMLNJ": [
46611         "Standard ML of New Jersey License",
46612         false
46613     ],
46614     "SMPPL": [
46615         "Secure Messaging Protocol Public License",
46616         false
46617     ],
46618     "SNIA": [
46619         "SNIA Public License 1.1",
46620         false
46621     ],
46622     "Spencer-86": [
46623         "Spencer License 86",
46624         false
46625     ],
46626     "Spencer-94": [
46627         "Spencer License 94",
46628         false
46629     ],
46630     "Spencer-99": [
46631         "Spencer License 99",
46632         false
46633     ],
46634     "SPL-1.0": [
46635         "Sun Public License v1.0",
46636         true
46637     ],
46638     "SugarCRM-1.1.3": [
46639         "SugarCRM Public License v1.1.3",
46640         false
46641     ],
46642     "SWL": [
46643         "Scheme Widget Library (SWL) Software License Agreement",
46644         false
46645     ],
46646     "TCL": [
46647         "TCL/TK License",
46648         false
46649     ],
46650     "TCP-wrappers": [
46651         "TCP Wrappers License",
46652         false
46653     ],
46654     "TMate": [
46655         "TMate Open Source License",
46656         false
46657     ],
46658     "TORQUE-1.1": [
46659         "TORQUE v2.5+ Software License v1.1",
46660         false
46661     ],
46662     "TOSL": [
46663         "Trusster Open Source License",
46664         false
46665     ],
46666     "Unicode-DFS-2015": [
46667         "Unicode License Agreement - Data Files and Software (2015)",
46668         false
46669     ],
46670     "Unicode-DFS-2016": [
46671         "Unicode License Agreement - Data Files and Software (2016)",
46672         false
46673     ],
46674     "Unicode-TOU": [
46675         "Unicode Terms of Use",
46676         false
46677     ],
46678     "Unlicense": [
46679         "The Unlicense",
46680         false
46681     ],
46682     "UPL-1.0": [
46683         "Universal Permissive License v1.0",
46684         true
46685     ],
46686     "Vim": [
46687         "Vim License",
46688         false
46689     ],
46690     "VOSTROM": [
46691         "VOSTROM Public License for Open Source",
46692         false
46693     ],
46694     "VSL-1.0": [
46695         "Vovida Software License v1.0",
46696         true
46697     ],
46698     "W3C": [
46699         "W3C Software Notice and License (2002-12-31)",
46700         true
46701     ],
46702     "W3C-19980720": [
46703         "W3C Software Notice and License (1998-07-20)",
46704         false
46705     ],
46706     "W3C-20150513": [
46707         "W3C Software Notice and Document License (2015-05-13)",
46708         false
46709     ],
46710     "Watcom-1.0": [
46711         "Sybase Open Watcom Public License 1.0",
46712         true
46713     ],
46714     "Wsuipa": [
46715         "Wsuipa License",
46716         false
46717     ],
46718     "WTFPL": [
46719         "Do What The F*ck You Want To Public License",
46720         false
46721     ],
46722     "X11": [
46723         "X11 License",
46724         false
46725     ],
46726     "Xerox": [
46727         "Xerox License",
46728         false
46729     ],
46730     "XFree86-1.1": [
46731         "XFree86 License 1.1",
46732         false
46733     ],
46734     "xinetd": [
46735         "xinetd License",
46736         false
46737     ],
46738     "Xnet": [
46739         "X.Net License",
46740         true
46741     ],
46742     "xpp": [
46743         "XPP License",
46744         false
46745     ],
46746     "XSkat": [
46747         "XSkat License",
46748         false
46749     ],
46750     "YPL-1.0": [
46751         "Yahoo! Public License v1.0",
46752         false
46753     ],
46754     "YPL-1.1": [
46755         "Yahoo! Public License v1.1",
46756         false
46757     ],
46758     "Zed": [
46759         "Zed License",
46760         false
46761     ],
46762     "Zend-2.0": [
46763         "Zend License v2.0",
46764         false
46765     ],
46766     "Zimbra-1.3": [
46767         "Zimbra Public License v1.3",
46768         false
46769     ],
46770     "Zimbra-1.4": [
46771         "Zimbra Public License v1.4",
46772         false
46773     ],
46774     "Zlib": [
46775         "zlib License",
46776         true
46777     ],
46778     "zlib-acknowledgement": [
46779         "zlib/libpng License with Acknowledgement",
46780         false
46781     ],
46782     "ZPL-1.1": [
46783         "Zope Public License 1.1",
46784         false
46785     ],
46786     "ZPL-2.0": [
46787         "Zope Public License 2.0",
46788         true
46789     ],
46790     "ZPL-2.1": [
46791         "Zope Public License 2.1",
46792         false
46793     ]
46794 }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
46795 $\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
46796 \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
46797 \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
46798 \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
46799 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
46800 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
46801 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
46802   <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">\r
46803     <security>\r
46804       <requestedPrivileges>\r
46805         <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>\r
46806       </requestedPrivileges>\r
46807     </security>\r
46808   </trustInfo>\r
46809   <dependency>\r
46810     <dependentAssembly>\r
46811       <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>\r
46812     </dependentAssembly>\r
46813   </dependency>\r
46814 </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
46815
46816
46817
46818
46819
46820
46821
46822
46823
46824
46825 namespace Symfony\Component\Console;
46826
46827 use Symfony\Component\Console\Descriptor\TextDescriptor;
46828 use Symfony\Component\Console\Descriptor\XmlDescriptor;
46829 use Symfony\Component\Console\Exception\ExceptionInterface;
46830 use Symfony\Component\Console\Formatter\OutputFormatter;
46831 use Symfony\Component\Console\Helper\DebugFormatterHelper;
46832 use Symfony\Component\Console\Helper\Helper;
46833 use Symfony\Component\Console\Helper\ProcessHelper;
46834 use Symfony\Component\Console\Helper\QuestionHelper;
46835 use Symfony\Component\Console\Input\InputInterface;
46836 use Symfony\Component\Console\Input\ArgvInput;
46837 use Symfony\Component\Console\Input\ArrayInput;
46838 use Symfony\Component\Console\Input\InputDefinition;
46839 use Symfony\Component\Console\Input\InputOption;
46840 use Symfony\Component\Console\Input\InputArgument;
46841 use Symfony\Component\Console\Input\InputAwareInterface;
46842 use Symfony\Component\Console\Output\BufferedOutput;
46843 use Symfony\Component\Console\Output\OutputInterface;
46844 use Symfony\Component\Console\Output\ConsoleOutput;
46845 use Symfony\Component\Console\Output\ConsoleOutputInterface;
46846 use Symfony\Component\Console\Command\Command;
46847 use Symfony\Component\Console\Command\HelpCommand;
46848 use Symfony\Component\Console\Command\ListCommand;
46849 use Symfony\Component\Console\Helper\HelperSet;
46850 use Symfony\Component\Console\Helper\FormatterHelper;
46851 use Symfony\Component\Console\Helper\DialogHelper;
46852 use Symfony\Component\Console\Helper\ProgressHelper;
46853 use Symfony\Component\Console\Helper\TableHelper;
46854 use Symfony\Component\Console\Event\ConsoleCommandEvent;
46855 use Symfony\Component\Console\Event\ConsoleExceptionEvent;
46856 use Symfony\Component\Console\Event\ConsoleTerminateEvent;
46857 use Symfony\Component\Console\Exception\CommandNotFoundException;
46858 use Symfony\Component\Console\Exception\LogicException;
46859 use Symfony\Component\Debug\Exception\FatalThrowableError;
46860 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
46861
46862
46863
46864
46865
46866
46867
46868
46869
46870
46871
46872
46873
46874
46875
46876
46877 class Application
46878 {
46879 private $commands = array();
46880 private $wantHelps = false;
46881 private $runningCommand;
46882 private $name;
46883 private $version;
46884 private $catchExceptions = true;
46885 private $autoExit = true;
46886 private $definition;
46887 private $helperSet;
46888 private $dispatcher;
46889 private $terminalDimensions;
46890 private $defaultCommand;
46891
46892
46893
46894
46895
46896
46897
46898 public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
46899 {
46900 $this->name = $name;
46901 $this->version = $version;
46902 $this->defaultCommand = 'list';
46903 $this->helperSet = $this->getDefaultHelperSet();
46904 $this->definition = $this->getDefaultInputDefinition();
46905
46906 foreach ($this->getDefaultCommands() as $command) {
46907 $this->add($command);
46908 }
46909 }
46910
46911 public function setDispatcher(EventDispatcherInterface $dispatcher)
46912 {
46913 $this->dispatcher = $dispatcher;
46914 }
46915
46916
46917
46918
46919
46920
46921
46922
46923
46924
46925
46926 public function run(InputInterface $input = null, OutputInterface $output = null)
46927 {
46928 if (null === $input) {
46929 $input = new ArgvInput();
46930 }
46931
46932 if (null === $output) {
46933 $output = new ConsoleOutput();
46934 }
46935
46936 $this->configureIO($input, $output);
46937
46938 try {
46939 $e = null;
46940 $exitCode = $this->doRun($input, $output);
46941 } catch (\Exception $x) {
46942 $e = $x;
46943 } catch (\Throwable $x) {
46944 $e = new FatalThrowableError($x);
46945 }
46946
46947 if (null !== $e) {
46948 if (!$this->catchExceptions || !$x instanceof \Exception) {
46949 throw $x;
46950 }
46951
46952 if ($output instanceof ConsoleOutputInterface) {
46953 $this->renderException($e, $output->getErrorOutput());
46954 } else {
46955 $this->renderException($e, $output);
46956 }
46957
46958 $exitCode = $e->getCode();
46959 if (is_numeric($exitCode)) {
46960 $exitCode = (int) $exitCode;
46961 if (0 === $exitCode) {
46962 $exitCode = 1;
46963 }
46964 } else {
46965 $exitCode = 1;
46966 }
46967 }
46968
46969 if ($this->autoExit) {
46970 if ($exitCode > 255) {
46971 $exitCode = 255;
46972 }
46973
46974 exit($exitCode);
46975 }
46976
46977 return $exitCode;
46978 }
46979
46980
46981
46982
46983
46984
46985
46986
46987
46988 public function doRun(InputInterface $input, OutputInterface $output)
46989 {
46990 if (true === $input->hasParameterOption(array('--version', '-V'))) {
46991 $output->writeln($this->getLongVersion());
46992
46993 return 0;
46994 }
46995
46996 $name = $this->getCommandName($input);
46997 if (true === $input->hasParameterOption(array('--help', '-h'))) {
46998 if (!$name) {
46999 $name = 'help';
47000 $input = new ArrayInput(array('command' => 'help'));
47001 } else {
47002 $this->wantHelps = true;
47003 }
47004 }
47005
47006 if (!$name) {
47007 $name = $this->defaultCommand;
47008 $this->definition->setArguments(array_merge(
47009 $this->definition->getArguments(),
47010 array(
47011 'command' => new InputArgument('command', InputArgument::OPTIONAL, $this->definition->getArgument('command')->getDescription(), $name),
47012 )
47013 ));
47014 }
47015
47016 $this->runningCommand = null;
47017
47018  $command = $this->find($name);
47019
47020 $this->runningCommand = $command;
47021 $exitCode = $this->doRunCommand($command, $input, $output);
47022 $this->runningCommand = null;
47023
47024 return $exitCode;
47025 }
47026
47027
47028
47029
47030
47031
47032 public function setHelperSet(HelperSet $helperSet)
47033 {
47034 $this->helperSet = $helperSet;
47035 }
47036
47037
47038
47039
47040
47041
47042 public function getHelperSet()
47043 {
47044 return $this->helperSet;
47045 }
47046
47047
47048
47049
47050
47051
47052 public function setDefinition(InputDefinition $definition)
47053 {
47054 $this->definition = $definition;
47055 }
47056
47057
47058
47059
47060
47061
47062 public function getDefinition()
47063 {
47064 return $this->definition;
47065 }
47066
47067
47068
47069
47070
47071
47072 public function getHelp()
47073 {
47074 return $this->getLongVersion();
47075 }
47076
47077
47078
47079
47080
47081
47082 public function setCatchExceptions($boolean)
47083 {
47084 $this->catchExceptions = (bool) $boolean;
47085 }
47086
47087
47088
47089
47090
47091
47092 public function setAutoExit($boolean)
47093 {
47094 $this->autoExit = (bool) $boolean;
47095 }
47096
47097
47098
47099
47100
47101
47102 public function getName()
47103 {
47104 return $this->name;
47105 }
47106
47107
47108
47109
47110
47111
47112 public function setName($name)
47113 {
47114 $this->name = $name;
47115 }
47116
47117
47118
47119
47120
47121
47122 public function getVersion()
47123 {
47124 return $this->version;
47125 }
47126
47127
47128
47129
47130
47131
47132 public function setVersion($version)
47133 {
47134 $this->version = $version;
47135 }
47136
47137
47138
47139
47140
47141
47142 public function getLongVersion()
47143 {
47144 if ('UNKNOWN' !== $this->getName()) {
47145 if ('UNKNOWN' !== $this->getVersion()) {
47146 return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion());
47147 }
47148
47149 return sprintf('<info>%s</info>', $this->getName());
47150 }
47151
47152 return '<info>Console Tool</info>';
47153 }
47154
47155
47156
47157
47158
47159
47160
47161
47162 public function register($name)
47163 {
47164 return $this->add(new Command($name));
47165 }
47166
47167
47168
47169
47170
47171
47172
47173
47174 public function addCommands(array $commands)
47175 {
47176 foreach ($commands as $command) {
47177 $this->add($command);
47178 }
47179 }
47180
47181
47182
47183
47184
47185
47186
47187
47188
47189
47190
47191 public function add(Command $command)
47192 {
47193 $command->setApplication($this);
47194
47195 if (!$command->isEnabled()) {
47196 $command->setApplication(null);
47197
47198 return;
47199 }
47200
47201 if (null === $command->getDefinition()) {
47202 throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command)));
47203 }
47204
47205 $this->commands[$command->getName()] = $command;
47206
47207 foreach ($command->getAliases() as $alias) {
47208 $this->commands[$alias] = $command;
47209 }
47210
47211 return $command;
47212 }
47213
47214
47215
47216
47217
47218
47219
47220
47221
47222
47223 public function get($name)
47224 {
47225 if (!isset($this->commands[$name])) {
47226 throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name));
47227 }
47228
47229 $command = $this->commands[$name];
47230
47231 if ($this->wantHelps) {
47232 $this->wantHelps = false;
47233
47234 $helpCommand = $this->get('help');
47235 $helpCommand->setCommand($command);
47236
47237 return $helpCommand;
47238 }
47239
47240 return $command;
47241 }
47242
47243
47244
47245
47246
47247
47248
47249
47250 public function has($name)
47251 {
47252 return isset($this->commands[$name]);
47253 }
47254
47255
47256
47257
47258
47259
47260
47261
47262 public function getNamespaces()
47263 {
47264 $namespaces = array();
47265 foreach ($this->all() as $command) {
47266 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName()));
47267
47268 foreach ($command->getAliases() as $alias) {
47269 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias));
47270 }
47271 }
47272
47273 return array_values(array_unique(array_filter($namespaces)));
47274 }
47275
47276
47277
47278
47279
47280
47281
47282
47283
47284
47285 public function findNamespace($namespace)
47286 {
47287 $allNamespaces = $this->getNamespaces();
47288 $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace);
47289 $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces);
47290
47291 if (empty($namespaces)) {
47292 $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
47293
47294 if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
47295 if (1 == count($alternatives)) {
47296 $message .= "\n\nDid you mean this?\n    ";
47297 } else {
47298 $message .= "\n\nDid you mean one of these?\n    ";
47299 }
47300
47301 $message .= implode("\n    ", $alternatives);
47302 }
47303
47304 throw new CommandNotFoundException($message, $alternatives);
47305 }
47306
47307 $exact = in_array($namespace, $namespaces, true);
47308 if (count($namespaces) > 1 && !$exact) {
47309 throw new CommandNotFoundException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces));
47310 }
47311
47312 return $exact ? $namespace : reset($namespaces);
47313 }
47314
47315
47316
47317
47318
47319
47320
47321
47322
47323
47324
47325
47326
47327 public function find($name)
47328 {
47329 $allCommands = array_keys($this->commands);
47330 $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
47331 $commands = preg_grep('{^'.$expr.'}', $allCommands);
47332
47333 if (empty($commands) || count(preg_grep('{^'.$expr.'$}', $commands)) < 1) {
47334 if (false !== $pos = strrpos($name, ':')) {
47335
47336  $this->findNamespace(substr($name, 0, $pos));
47337 }
47338
47339 $message = sprintf('Command "%s" is not defined.', $name);
47340
47341 if ($alternatives = $this->findAlternatives($name, $allCommands)) {
47342 if (1 == count($alternatives)) {
47343 $message .= "\n\nDid you mean this?\n    ";
47344 } else {
47345 $message .= "\n\nDid you mean one of these?\n    ";
47346 }
47347 $message .= implode("\n    ", $alternatives);
47348 }
47349
47350 throw new CommandNotFoundException($message, $alternatives);
47351 }
47352
47353
47354  if (count($commands) > 1) {
47355 $commandList = $this->commands;
47356 $commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) {
47357 $commandName = $commandList[$nameOrAlias]->getName();
47358
47359 return $commandName === $nameOrAlias || !in_array($commandName, $commands);
47360 });
47361 }
47362
47363 $exact = in_array($name, $commands, true);
47364 if (count($commands) > 1 && !$exact) {
47365 $suggestions = $this->getAbbreviationSuggestions(array_values($commands));
47366
47367 throw new CommandNotFoundException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions), array_values($commands));
47368 }
47369
47370 return $this->get($exact ? $name : reset($commands));
47371 }
47372
47373
47374
47375
47376
47377
47378
47379
47380
47381
47382 public function all($namespace = null)
47383 {
47384 if (null === $namespace) {
47385 return $this->commands;
47386 }
47387
47388 $commands = array();
47389 foreach ($this->commands as $name => $command) {
47390 if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
47391 $commands[$name] = $command;
47392 }
47393 }
47394
47395 return $commands;
47396 }
47397
47398
47399
47400
47401
47402
47403
47404
47405 public static function getAbbreviations($names)
47406 {
47407 $abbrevs = array();
47408 foreach ($names as $name) {
47409 for ($len = strlen($name); $len > 0; --$len) {
47410 $abbrev = substr($name, 0, $len);
47411 $abbrevs[$abbrev][] = $name;
47412 }
47413 }
47414
47415 return $abbrevs;
47416 }
47417
47418
47419
47420
47421
47422
47423
47424
47425
47426
47427
47428 public function asText($namespace = null, $raw = false)
47429 {
47430 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
47431
47432 $descriptor = new TextDescriptor();
47433 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, !$raw);
47434 $descriptor->describe($output, $this, array('namespace' => $namespace, 'raw_output' => true));
47435
47436 return $output->fetch();
47437 }
47438
47439
47440
47441
47442
47443
47444
47445
47446
47447
47448
47449 public function asXml($namespace = null, $asDom = false)
47450 {
47451 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
47452
47453 $descriptor = new XmlDescriptor();
47454
47455 if ($asDom) {
47456 return $descriptor->getApplicationDocument($this, $namespace);
47457 }
47458
47459 $output = new BufferedOutput();
47460 $descriptor->describe($output, $this, array('namespace' => $namespace));
47461
47462 return $output->fetch();
47463 }
47464
47465
47466
47467
47468
47469
47470
47471 public function renderException($e, $output)
47472 {
47473 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
47474
47475 do {
47476 $title = sprintf('  [%s]  ', get_class($e));
47477
47478 $len = Helper::strlen($title);
47479
47480 $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX;
47481
47482  if (defined('HHVM_VERSION') && $width > 1 << 31) {
47483 $width = 1 << 31;
47484 }
47485 $lines = array();
47486 foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) {
47487 foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
47488
47489  $lineLength = Helper::strlen($line) + 4;
47490 $lines[] = array($line, $lineLength);
47491
47492 $len = max($lineLength, $len);
47493 }
47494 }
47495
47496 $messages = array();
47497 $messages[] = $emptyLine = sprintf('<error>%s</error>', str_repeat(' ', $len));
47498 $messages[] = sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - Helper::strlen($title))));
47499 foreach ($lines as $line) {
47500 $messages[] = sprintf('<error>  %s  %s</error>', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1]));
47501 }
47502 $messages[] = $emptyLine;
47503 $messages[] = '';
47504
47505 $output->writeln($messages, OutputInterface::VERBOSITY_QUIET);
47506
47507 if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
47508 $output->writeln('<comment>Exception trace:</comment>', OutputInterface::VERBOSITY_QUIET);
47509
47510
47511  $trace = $e->getTrace();
47512 array_unshift($trace, array(
47513 'function' => '',
47514 'file' => $e->getFile() !== null ? $e->getFile() : 'n/a',
47515 'line' => $e->getLine() !== null ? $e->getLine() : 'n/a',
47516 'args' => array(),
47517 ));
47518
47519 for ($i = 0, $count = count($trace); $i < $count; ++$i) {
47520 $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
47521 $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
47522 $function = $trace[$i]['function'];
47523 $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
47524 $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';
47525
47526 $output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line), OutputInterface::VERBOSITY_QUIET);
47527 }
47528
47529 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
47530 }
47531 } while ($e = $e->getPrevious());
47532
47533 if (null !== $this->runningCommand) {
47534 $output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET);
47535 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
47536 }
47537 }
47538
47539
47540
47541
47542
47543
47544 protected function getTerminalWidth()
47545 {
47546 $dimensions = $this->getTerminalDimensions();
47547
47548 return $dimensions[0];
47549 }
47550
47551
47552
47553
47554
47555
47556 protected function getTerminalHeight()
47557 {
47558 $dimensions = $this->getTerminalDimensions();
47559
47560 return $dimensions[1];
47561 }
47562
47563
47564
47565
47566
47567
47568 public function getTerminalDimensions()
47569 {
47570 if ($this->terminalDimensions) {
47571 return $this->terminalDimensions;
47572 }
47573
47574 if ('\\' === DIRECTORY_SEPARATOR) {
47575
47576  if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) {
47577 return array((int) $matches[1], (int) $matches[2]);
47578 }
47579
47580  if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) {
47581 return array((int) $matches[1], (int) $matches[2]);
47582 }
47583 }
47584
47585 if ($sttyString = $this->getSttyColumns()) {
47586
47587  if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) {
47588 return array((int) $matches[2], (int) $matches[1]);
47589 }
47590
47591  if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) {
47592 return array((int) $matches[2], (int) $matches[1]);
47593 }
47594 }
47595
47596 return array(null, null);
47597 }
47598
47599
47600
47601
47602
47603
47604
47605
47606
47607
47608
47609 public function setTerminalDimensions($width, $height)
47610 {
47611 $this->terminalDimensions = array($width, $height);
47612
47613 return $this;
47614 }
47615
47616
47617
47618
47619
47620
47621
47622 protected function configureIO(InputInterface $input, OutputInterface $output)
47623 {
47624 if (true === $input->hasParameterOption(array('--ansi'))) {
47625 $output->setDecorated(true);
47626 } elseif (true === $input->hasParameterOption(array('--no-ansi'))) {
47627 $output->setDecorated(false);
47628 }
47629
47630 if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) {
47631 $input->setInteractive(false);
47632 } elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('question')) {
47633 $inputStream = $this->getHelperSet()->get('question')->getInputStream();
47634 if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) {
47635 $input->setInteractive(false);
47636 }
47637 }
47638
47639 if (true === $input->hasParameterOption(array('--quiet', '-q'))) {
47640 $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
47641 $input->setInteractive(false);
47642 } else {
47643 if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) {
47644 $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
47645 } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || $input->getParameterOption('--verbose') === 2) {
47646 $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
47647 } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) {
47648 $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
47649 }
47650 }
47651 }
47652
47653
47654
47655
47656
47657
47658
47659
47660
47661
47662
47663
47664
47665 protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
47666 {
47667 foreach ($command->getHelperSet() as $helper) {
47668 if ($helper instanceof InputAwareInterface) {
47669 $helper->setInput($input);
47670 }
47671 }
47672
47673 if (null === $this->dispatcher) {
47674 return $command->run($input, $output);
47675 }
47676
47677
47678  try {
47679 $command->mergeApplicationDefinition();
47680 $input->bind($command->getDefinition());
47681 } catch (ExceptionInterface $e) {
47682
47683  }
47684
47685 $event = new ConsoleCommandEvent($command, $input, $output);
47686 $e = null;
47687
47688 try {
47689 $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
47690
47691 if ($event->commandShouldRun()) {
47692 $exitCode = $command->run($input, $output);
47693 } else {
47694 $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
47695 }
47696 } catch (\Exception $e) {
47697 } catch (\Throwable $e) {
47698 }
47699 if (null !== $e) {
47700 $x = $e instanceof \Exception ? $e : new FatalThrowableError($e);
47701 $event = new ConsoleExceptionEvent($command, $input, $output, $x, $x->getCode());
47702 $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
47703
47704 if ($x !== $event->getException()) {
47705 $e = $event->getException();
47706 }
47707 $exitCode = $e->getCode();
47708 }
47709
47710 $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
47711 $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
47712
47713 if (null !== $e) {
47714 throw $e;
47715 }
47716
47717 return $event->getExitCode();
47718 }
47719
47720
47721
47722
47723
47724
47725
47726
47727 protected function getCommandName(InputInterface $input)
47728 {
47729 return $input->getFirstArgument();
47730 }
47731
47732
47733
47734
47735
47736
47737 protected function getDefaultInputDefinition()
47738 {
47739 return new InputDefinition(array(
47740 new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
47741
47742 new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'),
47743 new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'),
47744 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'),
47745 new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'),
47746 new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'),
47747 new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'),
47748 new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
47749 ));
47750 }
47751
47752
47753
47754
47755
47756
47757 protected function getDefaultCommands()
47758 {
47759 return array(new HelpCommand(), new ListCommand());
47760 }
47761
47762
47763
47764
47765
47766
47767 protected function getDefaultHelperSet()
47768 {
47769 return new HelperSet(array(
47770 new FormatterHelper(),
47771 new DialogHelper(false),
47772 new ProgressHelper(false),
47773 new TableHelper(false),
47774 new DebugFormatterHelper(),
47775 new ProcessHelper(),
47776 new QuestionHelper(),
47777 ));
47778 }
47779
47780
47781
47782
47783
47784
47785 private function getSttyColumns()
47786 {
47787 if (!function_exists('proc_open')) {
47788 return;
47789 }
47790
47791 $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
47792 $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
47793 if (is_resource($process)) {
47794 $info = stream_get_contents($pipes[1]);
47795 fclose($pipes[1]);
47796 fclose($pipes[2]);
47797 proc_close($process);
47798
47799 return $info;
47800 }
47801 }
47802
47803
47804
47805
47806
47807
47808 private function getConsoleMode()
47809 {
47810 if (!function_exists('proc_open')) {
47811 return;
47812 }
47813
47814 $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
47815 $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
47816 if (is_resource($process)) {
47817 $info = stream_get_contents($pipes[1]);
47818 fclose($pipes[1]);
47819 fclose($pipes[2]);
47820 proc_close($process);
47821
47822 if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
47823 return $matches[2].'x'.$matches[1];
47824 }
47825 }
47826 }
47827
47828
47829
47830
47831
47832
47833
47834
47835 private function getAbbreviationSuggestions($abbrevs)
47836 {
47837 return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : '');
47838 }
47839
47840
47841
47842
47843
47844
47845
47846
47847
47848
47849
47850 public function extractNamespace($name, $limit = null)
47851 {
47852 $parts = explode(':', $name);
47853 array_pop($parts);
47854
47855 return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit));
47856 }
47857
47858
47859
47860
47861
47862
47863
47864
47865
47866
47867 private function findAlternatives($name, $collection)
47868 {
47869 $threshold = 1e3;
47870 $alternatives = array();
47871
47872 $collectionParts = array();
47873 foreach ($collection as $item) {
47874 $collectionParts[$item] = explode(':', $item);
47875 }
47876
47877 foreach (explode(':', $name) as $i => $subname) {
47878 foreach ($collectionParts as $collectionName => $parts) {
47879 $exists = isset($alternatives[$collectionName]);
47880 if (!isset($parts[$i]) && $exists) {
47881 $alternatives[$collectionName] += $threshold;
47882 continue;
47883 } elseif (!isset($parts[$i])) {
47884 continue;
47885 }
47886
47887 $lev = levenshtein($subname, $parts[$i]);
47888 if ($lev <= strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) {
47889 $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
47890 } elseif ($exists) {
47891 $alternatives[$collectionName] += $threshold;
47892 }
47893 }
47894 }
47895
47896 foreach ($collection as $item) {
47897 $lev = levenshtein($name, $item);
47898 if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
47899 $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
47900 }
47901 }
47902
47903 $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; });
47904 asort($alternatives);
47905
47906 return array_keys($alternatives);
47907 }
47908
47909
47910
47911
47912
47913
47914 public function setDefaultCommand($commandName)
47915 {
47916 $this->defaultCommand = $commandName;
47917 }
47918
47919 private function splitStringByWidth($string, $width)
47920 {
47921
47922  
47923  
47924  if (false === $encoding = mb_detect_encoding($string, null, true)) {
47925 return str_split($string, $width);
47926 }
47927
47928 $utf8String = mb_convert_encoding($string, 'utf8', $encoding);
47929 $lines = array();
47930 $line = '';
47931 foreach (preg_split('//u', $utf8String) as $char) {
47932
47933  if (mb_strwidth($line.$char, 'utf8') <= $width) {
47934 $line .= $char;
47935 continue;
47936 }
47937
47938  $lines[] = str_pad($line, $width);
47939 $line = $char;
47940 }
47941 if ('' !== $line) {
47942 $lines[] = count($lines) ? str_pad($line, $width) : $line;
47943 }
47944
47945 mb_convert_variables($encoding, 'utf8', $lines);
47946
47947 return $lines;
47948 }
47949
47950
47951
47952
47953
47954
47955
47956
47957 private function extractAllNamespaces($name)
47958 {
47959
47960  $parts = explode(':', $name, -1);
47961 $namespaces = array();
47962
47963 foreach ($parts as $part) {
47964 if (count($namespaces)) {
47965 $namespaces[] = end($namespaces).':'.$part;
47966 } else {
47967 $namespaces[] = $part;
47968 }
47969 }
47970
47971 return $namespaces;
47972 }
47973 }
47974 <?php
47975
47976
47977
47978
47979
47980
47981
47982
47983
47984
47985 namespace Symfony\Component\Console\Command;
47986
47987 use Symfony\Component\Console\Descriptor\TextDescriptor;
47988 use Symfony\Component\Console\Descriptor\XmlDescriptor;
47989 use Symfony\Component\Console\Exception\ExceptionInterface;
47990 use Symfony\Component\Console\Input\InputDefinition;
47991 use Symfony\Component\Console\Input\InputOption;
47992 use Symfony\Component\Console\Input\InputArgument;
47993 use Symfony\Component\Console\Input\InputInterface;
47994 use Symfony\Component\Console\Output\BufferedOutput;
47995 use Symfony\Component\Console\Output\OutputInterface;
47996 use Symfony\Component\Console\Application;
47997 use Symfony\Component\Console\Helper\HelperSet;
47998 use Symfony\Component\Console\Exception\InvalidArgumentException;
47999 use Symfony\Component\Console\Exception\LogicException;
48000
48001
48002
48003
48004
48005
48006 class Command
48007 {
48008 private $application;
48009 private $name;
48010 private $processTitle;
48011 private $aliases = array();
48012 private $definition;
48013 private $help;
48014 private $description;
48015 private $ignoreValidationErrors = false;
48016 private $applicationDefinitionMerged = false;
48017 private $applicationDefinitionMergedWithArgs = false;
48018 private $code;
48019 private $synopsis = array();
48020 private $usages = array();
48021 private $helperSet;
48022
48023
48024
48025
48026
48027
48028
48029
48030 public function __construct($name = null)
48031 {
48032 $this->definition = new InputDefinition();
48033
48034 if (null !== $name) {
48035 $this->setName($name);
48036 }
48037
48038 $this->configure();
48039
48040 if (!$this->name) {
48041 throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($this)));
48042 }
48043 }
48044
48045
48046
48047
48048
48049
48050 public function ignoreValidationErrors()
48051 {
48052 $this->ignoreValidationErrors = true;
48053 }
48054
48055
48056
48057
48058
48059
48060 public function setApplication(Application $application = null)
48061 {
48062 $this->application = $application;
48063 if ($application) {
48064 $this->setHelperSet($application->getHelperSet());
48065 } else {
48066 $this->helperSet = null;
48067 }
48068 }
48069
48070
48071
48072
48073
48074
48075 public function setHelperSet(HelperSet $helperSet)
48076 {
48077 $this->helperSet = $helperSet;
48078 }
48079
48080
48081
48082
48083
48084
48085 public function getHelperSet()
48086 {
48087 return $this->helperSet;
48088 }
48089
48090
48091
48092
48093
48094
48095 public function getApplication()
48096 {
48097 return $this->application;
48098 }
48099
48100
48101
48102
48103
48104
48105
48106
48107
48108 public function isEnabled()
48109 {
48110 return true;
48111 }
48112
48113
48114
48115
48116 protected function configure()
48117 {
48118 }
48119
48120
48121
48122
48123
48124
48125
48126
48127
48128
48129
48130
48131
48132
48133
48134
48135
48136
48137 protected function execute(InputInterface $input, OutputInterface $output)
48138 {
48139 throw new LogicException('You must override the execute() method in the concrete command class.');
48140 }
48141
48142
48143
48144
48145
48146
48147
48148
48149
48150
48151
48152 protected function interact(InputInterface $input, OutputInterface $output)
48153 {
48154 }
48155
48156
48157
48158
48159
48160
48161
48162
48163
48164
48165 protected function initialize(InputInterface $input, OutputInterface $output)
48166 {
48167 }
48168
48169
48170
48171
48172
48173
48174
48175
48176
48177
48178
48179
48180
48181
48182
48183
48184
48185
48186 public function run(InputInterface $input, OutputInterface $output)
48187 {
48188
48189  $this->getSynopsis(true);
48190 $this->getSynopsis(false);
48191
48192
48193  $this->mergeApplicationDefinition();
48194
48195
48196  try {
48197 $input->bind($this->definition);
48198 } catch (ExceptionInterface $e) {
48199 if (!$this->ignoreValidationErrors) {
48200 throw $e;
48201 }
48202 }
48203
48204 $this->initialize($input, $output);
48205
48206 if (null !== $this->processTitle) {
48207 if (function_exists('cli_set_process_title')) {
48208 if (false === @cli_set_process_title($this->processTitle)) {
48209 if ('Darwin' === PHP_OS) {
48210 $output->writeln('<comment>Running "cli_get_process_title" as an unprivileged user is not supported on MacOS.</comment>');
48211 } else {
48212 $error = error_get_last();
48213 trigger_error($error['message'], E_USER_WARNING);
48214 }
48215 }
48216 } elseif (function_exists('setproctitle')) {
48217 setproctitle($this->processTitle);
48218 } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
48219 $output->writeln('<comment>Install the proctitle PECL to be able to change the process title.</comment>');
48220 }
48221 }
48222
48223 if ($input->isInteractive()) {
48224 $this->interact($input, $output);
48225 }
48226
48227
48228  
48229  
48230  if ($input->hasArgument('command') && null === $input->getArgument('command')) {
48231 $input->setArgument('command', $this->getName());
48232 }
48233
48234 $input->validate();
48235
48236 if ($this->code) {
48237 $statusCode = call_user_func($this->code, $input, $output);
48238 } else {
48239 $statusCode = $this->execute($input, $output);
48240 }
48241
48242 return is_numeric($statusCode) ? (int) $statusCode : 0;
48243 }
48244
48245
48246
48247
48248
48249
48250
48251
48252
48253
48254
48255
48256
48257
48258
48259 public function setCode($code)
48260 {
48261 if (!is_callable($code)) {
48262 throw new InvalidArgumentException('Invalid callable provided to Command::setCode.');
48263 }
48264
48265 if (PHP_VERSION_ID >= 50400 && $code instanceof \Closure) {
48266 $r = new \ReflectionFunction($code);
48267 if (null === $r->getClosureThis()) {
48268 if (PHP_VERSION_ID < 70000) {
48269
48270  
48271  
48272  
48273  $code = @\Closure::bind($code, $this);
48274 } else {
48275 $code = \Closure::bind($code, $this);
48276 }
48277 }
48278 }
48279
48280 $this->code = $code;
48281
48282 return $this;
48283 }
48284
48285
48286
48287
48288
48289
48290
48291
48292 public function mergeApplicationDefinition($mergeArgs = true)
48293 {
48294 if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) {
48295 return;
48296 }
48297
48298 $this->definition->addOptions($this->application->getDefinition()->getOptions());
48299
48300 if ($mergeArgs) {
48301 $currentArguments = $this->definition->getArguments();
48302 $this->definition->setArguments($this->application->getDefinition()->getArguments());
48303 $this->definition->addArguments($currentArguments);
48304 }
48305
48306 $this->applicationDefinitionMerged = true;
48307 if ($mergeArgs) {
48308 $this->applicationDefinitionMergedWithArgs = true;
48309 }
48310 }
48311
48312
48313
48314
48315
48316
48317
48318
48319 public function setDefinition($definition)
48320 {
48321 if ($definition instanceof InputDefinition) {
48322 $this->definition = $definition;
48323 } else {
48324 $this->definition->setDefinition($definition);
48325 }
48326
48327 $this->applicationDefinitionMerged = false;
48328
48329 return $this;
48330 }
48331
48332
48333
48334
48335
48336
48337 public function getDefinition()
48338 {
48339 return $this->definition;
48340 }
48341
48342
48343
48344
48345
48346
48347
48348
48349
48350
48351
48352 public function getNativeDefinition()
48353 {
48354 return $this->getDefinition();
48355 }
48356
48357
48358
48359
48360
48361
48362
48363
48364
48365
48366
48367 public function addArgument($name, $mode = null, $description = '', $default = null)
48368 {
48369 $this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
48370
48371 return $this;
48372 }
48373
48374
48375
48376
48377
48378
48379
48380
48381
48382
48383
48384
48385 public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
48386 {
48387 $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
48388
48389 return $this;
48390 }
48391
48392
48393
48394
48395
48396
48397
48398
48399
48400
48401
48402
48403
48404
48405
48406 public function setName($name)
48407 {
48408 $this->validateName($name);
48409
48410 $this->name = $name;
48411
48412 return $this;
48413 }
48414
48415
48416
48417
48418
48419
48420
48421
48422
48423
48424
48425
48426
48427 public function setProcessTitle($title)
48428 {
48429 $this->processTitle = $title;
48430
48431 return $this;
48432 }
48433
48434
48435
48436
48437
48438
48439 public function getName()
48440 {
48441 return $this->name;
48442 }
48443
48444
48445
48446
48447
48448
48449
48450
48451 public function setDescription($description)
48452 {
48453 $this->description = $description;
48454
48455 return $this;
48456 }
48457
48458
48459
48460
48461
48462
48463 public function getDescription()
48464 {
48465 return $this->description;
48466 }
48467
48468
48469
48470
48471
48472
48473
48474
48475 public function setHelp($help)
48476 {
48477 $this->help = $help;
48478
48479 return $this;
48480 }
48481
48482
48483
48484
48485
48486
48487 public function getHelp()
48488 {
48489 return $this->help;
48490 }
48491
48492
48493
48494
48495
48496
48497
48498 public function getProcessedHelp()
48499 {
48500 $name = $this->name;
48501
48502 $placeholders = array(
48503 '%command.name%',
48504 '%command.full_name%',
48505 );
48506 $replacements = array(
48507 $name,
48508 $_SERVER['PHP_SELF'].' '.$name,
48509 );
48510
48511 return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription());
48512 }
48513
48514
48515
48516
48517
48518
48519
48520
48521
48522
48523 public function setAliases($aliases)
48524 {
48525 if (!is_array($aliases) && !$aliases instanceof \Traversable) {
48526 throw new InvalidArgumentException('$aliases must be an array or an instance of \Traversable');
48527 }
48528
48529 foreach ($aliases as $alias) {
48530 $this->validateName($alias);
48531 }
48532
48533 $this->aliases = $aliases;
48534
48535 return $this;
48536 }
48537
48538
48539
48540
48541
48542
48543 public function getAliases()
48544 {
48545 return $this->aliases;
48546 }
48547
48548
48549
48550
48551
48552
48553
48554
48555 public function getSynopsis($short = false)
48556 {
48557 $key = $short ? 'short' : 'long';
48558
48559 if (!isset($this->synopsis[$key])) {
48560 $this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short)));
48561 }
48562
48563 return $this->synopsis[$key];
48564 }
48565
48566
48567
48568
48569
48570
48571
48572
48573 public function addUsage($usage)
48574 {
48575 if (0 !== strpos($usage, $this->name)) {
48576 $usage = sprintf('%s %s', $this->name, $usage);
48577 }
48578
48579 $this->usages[] = $usage;
48580
48581 return $this;
48582 }
48583
48584
48585
48586
48587
48588
48589 public function getUsages()
48590 {
48591 return $this->usages;
48592 }
48593
48594
48595
48596
48597
48598
48599
48600
48601
48602
48603
48604 public function getHelper($name)
48605 {
48606 if (null === $this->helperSet) {
48607 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));
48608 }
48609
48610 return $this->helperSet->get($name);
48611 }
48612
48613
48614
48615
48616
48617
48618
48619
48620 public function asText()
48621 {
48622 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
48623
48624 $descriptor = new TextDescriptor();
48625 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
48626 $descriptor->describe($output, $this, array('raw_output' => true));
48627
48628 return $output->fetch();
48629 }
48630
48631
48632
48633
48634
48635
48636
48637
48638
48639
48640 public function asXml($asDom = false)
48641 {
48642 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
48643
48644 $descriptor = new XmlDescriptor();
48645
48646 if ($asDom) {
48647 return $descriptor->getCommandDocument($this);
48648 }
48649
48650 $output = new BufferedOutput();
48651 $descriptor->describe($output, $this);
48652
48653 return $output->fetch();
48654 }
48655
48656
48657
48658
48659
48660
48661
48662
48663
48664
48665 private function validateName($name)
48666 {
48667 if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
48668 throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
48669 }
48670 }
48671 }
48672 <?php
48673
48674
48675
48676
48677
48678
48679
48680
48681
48682
48683 namespace Symfony\Component\Console\Command;
48684
48685 use Symfony\Component\Console\Helper\DescriptorHelper;
48686 use Symfony\Component\Console\Input\InputArgument;
48687 use Symfony\Component\Console\Input\InputOption;
48688 use Symfony\Component\Console\Input\InputInterface;
48689 use Symfony\Component\Console\Output\OutputInterface;
48690
48691
48692
48693
48694
48695
48696 class HelpCommand extends Command
48697 {
48698 private $command;
48699
48700
48701
48702
48703 protected function configure()
48704 {
48705 $this->ignoreValidationErrors();
48706
48707 $this
48708 ->setName('help')
48709 ->setDefinition(array(
48710 new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
48711 new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
48712 new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
48713 new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
48714 ))
48715 ->setDescription('Displays help for a command')
48716 ->setHelp(<<<'EOF'
48717 The <info>%command.name%</info> command displays help for a given command:
48718
48719   <info>php %command.full_name% list</info>
48720
48721 You can also output the help in other formats by using the <comment>--format</comment> option:
48722
48723   <info>php %command.full_name% --format=xml list</info>
48724
48725 To display the list of available commands, please use the <info>list</info> command.
48726 EOF
48727 )
48728 ;
48729 }
48730
48731
48732
48733
48734
48735
48736 public function setCommand(Command $command)
48737 {
48738 $this->command = $command;
48739 }
48740
48741
48742
48743
48744 protected function execute(InputInterface $input, OutputInterface $output)
48745 {
48746 if (null === $this->command) {
48747 $this->command = $this->getApplication()->find($input->getArgument('command_name'));
48748 }
48749
48750 if ($input->getOption('xml')) {
48751 @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);
48752
48753 $input->setOption('format', 'xml');
48754 }
48755
48756 $helper = new DescriptorHelper();
48757 $helper->describe($output, $this->command, array(
48758 'format' => $input->getOption('format'),
48759 'raw_text' => $input->getOption('raw'),
48760 ));
48761
48762 $this->command = null;
48763 }
48764 }
48765 <?php
48766
48767
48768
48769
48770
48771
48772
48773
48774
48775
48776 namespace Symfony\Component\Console\Command;
48777
48778 use Symfony\Component\Console\Helper\DescriptorHelper;
48779 use Symfony\Component\Console\Input\InputArgument;
48780 use Symfony\Component\Console\Input\InputOption;
48781 use Symfony\Component\Console\Input\InputInterface;
48782 use Symfony\Component\Console\Output\OutputInterface;
48783 use Symfony\Component\Console\Input\InputDefinition;
48784
48785
48786
48787
48788
48789
48790 class ListCommand extends Command
48791 {
48792
48793
48794
48795 protected function configure()
48796 {
48797 $this
48798 ->setName('list')
48799 ->setDefinition($this->createDefinition())
48800 ->setDescription('Lists commands')
48801 ->setHelp(<<<'EOF'
48802 The <info>%command.name%</info> command lists all commands:
48803
48804   <info>php %command.full_name%</info>
48805
48806 You can also display the commands for a specific namespace:
48807
48808   <info>php %command.full_name% test</info>
48809
48810 You can also output the information in other formats by using the <comment>--format</comment> option:
48811
48812   <info>php %command.full_name% --format=xml</info>
48813
48814 It's also possible to get raw list of commands (useful for embedding command runner):
48815
48816   <info>php %command.full_name% --raw</info>
48817 EOF
48818 )
48819 ;
48820 }
48821
48822
48823
48824
48825 public function getNativeDefinition()
48826 {
48827 return $this->createDefinition();
48828 }
48829
48830
48831
48832
48833 protected function execute(InputInterface $input, OutputInterface $output)
48834 {
48835 if ($input->getOption('xml')) {
48836 @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);
48837
48838 $input->setOption('format', 'xml');
48839 }
48840
48841 $helper = new DescriptorHelper();
48842 $helper->describe($output, $this->getApplication(), array(
48843 'format' => $input->getOption('format'),
48844 'raw_text' => $input->getOption('raw'),
48845 'namespace' => $input->getArgument('namespace'),
48846 ));
48847 }
48848
48849
48850
48851
48852 private function createDefinition()
48853 {
48854 return new InputDefinition(array(
48855 new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
48856 new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'),
48857 new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
48858 new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
48859 ));
48860 }
48861 }
48862 <?php
48863
48864
48865
48866
48867
48868
48869
48870
48871
48872
48873 namespace Symfony\Component\Console;
48874
48875
48876
48877
48878
48879
48880 final class ConsoleEvents
48881 {
48882
48883
48884
48885
48886
48887
48888
48889
48890
48891
48892
48893
48894 const COMMAND = 'console.command';
48895
48896
48897
48898
48899
48900
48901
48902
48903
48904
48905
48906
48907 const TERMINATE = 'console.terminate';
48908
48909
48910
48911
48912
48913
48914
48915
48916
48917
48918
48919
48920
48921 const EXCEPTION = 'console.exception';
48922 }
48923 <?php
48924
48925
48926
48927
48928
48929
48930
48931
48932
48933
48934 namespace Symfony\Component\Console\Descriptor;
48935
48936 use Symfony\Component\Console\Application;
48937 use Symfony\Component\Console\Command\Command;
48938 use Symfony\Component\Console\Exception\CommandNotFoundException;
48939
48940
48941
48942
48943
48944
48945 class ApplicationDescription
48946 {
48947 const GLOBAL_NAMESPACE = '_global';
48948
48949
48950
48951
48952 private $application;
48953
48954
48955
48956
48957 private $namespace;
48958
48959
48960
48961
48962 private $namespaces;
48963
48964
48965
48966
48967 private $commands;
48968
48969
48970
48971
48972 private $aliases;
48973
48974
48975
48976
48977
48978
48979
48980 public function __construct(Application $application, $namespace = null)
48981 {
48982 $this->application = $application;
48983 $this->namespace = $namespace;
48984 }
48985
48986
48987
48988
48989 public function getNamespaces()
48990 {
48991 if (null === $this->namespaces) {
48992 $this->inspectApplication();
48993 }
48994
48995 return $this->namespaces;
48996 }
48997
48998
48999
49000
49001 public function getCommands()
49002 {
49003 if (null === $this->commands) {
49004 $this->inspectApplication();
49005 }
49006
49007 return $this->commands;
49008 }
49009
49010
49011
49012
49013
49014
49015
49016
49017 public function getCommand($name)
49018 {
49019 if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
49020 throw new CommandNotFoundException(sprintf('Command %s does not exist.', $name));
49021 }
49022
49023 return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name];
49024 }
49025
49026 private function inspectApplication()
49027 {
49028 $this->commands = array();
49029 $this->namespaces = array();
49030
49031 $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null);
49032 foreach ($this->sortCommands($all) as $namespace => $commands) {
49033 $names = array();
49034
49035
49036 foreach ($commands as $name => $command) {
49037 if (!$command->getName()) {
49038 continue;
49039 }
49040
49041 if ($command->getName() === $name) {
49042 $this->commands[$name] = $command;
49043 } else {
49044 $this->aliases[$name] = $command;
49045 }
49046
49047 $names[] = $name;
49048 }
49049
49050 $this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names);
49051 }
49052 }
49053
49054
49055
49056
49057
49058
49059 private function sortCommands(array $commands)
49060 {
49061 $namespacedCommands = array();
49062 $globalCommands = array();
49063 foreach ($commands as $name => $command) {
49064 $key = $this->application->extractNamespace($name, 1);
49065 if (!$key) {
49066 $globalCommands['_global'][$name] = $command;
49067 } else {
49068 $namespacedCommands[$key][$name] = $command;
49069 }
49070 }
49071 ksort($namespacedCommands);
49072 $namespacedCommands = array_merge($globalCommands, $namespacedCommands);
49073
49074 foreach ($namespacedCommands as &$commandsSet) {
49075 ksort($commandsSet);
49076 }
49077
49078  unset($commandsSet);
49079
49080 return $namespacedCommands;
49081 }
49082 }
49083 <?php
49084
49085
49086
49087
49088
49089
49090
49091
49092
49093
49094 namespace Symfony\Component\Console\Descriptor;
49095
49096 use Symfony\Component\Console\Application;
49097 use Symfony\Component\Console\Command\Command;
49098 use Symfony\Component\Console\Input\InputArgument;
49099 use Symfony\Component\Console\Input\InputDefinition;
49100 use Symfony\Component\Console\Input\InputOption;
49101 use Symfony\Component\Console\Output\OutputInterface;
49102 use Symfony\Component\Console\Exception\InvalidArgumentException;
49103
49104
49105
49106
49107
49108
49109 abstract class Descriptor implements DescriptorInterface
49110 {
49111
49112
49113
49114 private $output;
49115
49116
49117
49118
49119 public function describe(OutputInterface $output, $object, array $options = array())
49120 {
49121 $this->output = $output;
49122
49123 switch (true) {
49124 case $object instanceof InputArgument:
49125 $this->describeInputArgument($object, $options);
49126 break;
49127 case $object instanceof InputOption:
49128 $this->describeInputOption($object, $options);
49129 break;
49130 case $object instanceof InputDefinition:
49131 $this->describeInputDefinition($object, $options);
49132 break;
49133 case $object instanceof Command:
49134 $this->describeCommand($object, $options);
49135 break;
49136 case $object instanceof Application:
49137 $this->describeApplication($object, $options);
49138 break;
49139 default:
49140 throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object)));
49141 }
49142 }
49143
49144
49145
49146
49147
49148
49149
49150 protected function write($content, $decorated = false)
49151 {
49152 $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW);
49153 }
49154
49155
49156
49157
49158
49159
49160
49161
49162
49163 abstract protected function describeInputArgument(InputArgument $argument, array $options = array());
49164
49165
49166
49167
49168
49169
49170
49171
49172
49173 abstract protected function describeInputOption(InputOption $option, array $options = array());
49174
49175
49176
49177
49178
49179
49180
49181
49182
49183 abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array());
49184
49185
49186
49187
49188
49189
49190
49191
49192
49193 abstract protected function describeCommand(Command $command, array $options = array());
49194
49195
49196
49197
49198
49199
49200
49201
49202
49203 abstract protected function describeApplication(Application $application, array $options = array());
49204 }
49205 <?php
49206
49207
49208
49209
49210
49211
49212
49213
49214
49215
49216 namespace Symfony\Component\Console\Descriptor;
49217
49218 use Symfony\Component\Console\Output\OutputInterface;
49219
49220
49221
49222
49223
49224
49225 interface DescriptorInterface
49226 {
49227
49228
49229
49230
49231
49232
49233
49234 public function describe(OutputInterface $output, $object, array $options = array());
49235 }
49236 <?php
49237
49238
49239
49240
49241
49242
49243
49244
49245
49246
49247 namespace Symfony\Component\Console\Descriptor;
49248
49249 use Symfony\Component\Console\Application;
49250 use Symfony\Component\Console\Command\Command;
49251 use Symfony\Component\Console\Input\InputArgument;
49252 use Symfony\Component\Console\Input\InputDefinition;
49253 use Symfony\Component\Console\Input\InputOption;
49254
49255
49256
49257
49258
49259
49260
49261
49262 class JsonDescriptor extends Descriptor
49263 {
49264
49265
49266
49267 protected function describeInputArgument(InputArgument $argument, array $options = array())
49268 {
49269 $this->writeData($this->getInputArgumentData($argument), $options);
49270 }
49271
49272
49273
49274
49275 protected function describeInputOption(InputOption $option, array $options = array())
49276 {
49277 $this->writeData($this->getInputOptionData($option), $options);
49278 }
49279
49280
49281
49282
49283 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
49284 {
49285 $this->writeData($this->getInputDefinitionData($definition), $options);
49286 }
49287
49288
49289
49290
49291 protected function describeCommand(Command $command, array $options = array())
49292 {
49293 $this->writeData($this->getCommandData($command), $options);
49294 }
49295
49296
49297
49298
49299 protected function describeApplication(Application $application, array $options = array())
49300 {
49301 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
49302 $description = new ApplicationDescription($application, $describedNamespace);
49303 $commands = array();
49304
49305 foreach ($description->getCommands() as $command) {
49306 $commands[] = $this->getCommandData($command);
49307 }
49308
49309 $data = $describedNamespace
49310 ? array('commands' => $commands, 'namespace' => $describedNamespace)
49311 : array('commands' => $commands, 'namespaces' => array_values($description->getNamespaces()));
49312
49313 $this->writeData($data, $options);
49314 }
49315
49316
49317
49318
49319
49320
49321
49322
49323
49324 private function writeData(array $data, array $options)
49325 {
49326 $this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0));
49327 }
49328
49329
49330
49331
49332
49333
49334 private function getInputArgumentData(InputArgument $argument)
49335 {
49336 return array(
49337 'name' => $argument->getName(),
49338 'is_required' => $argument->isRequired(),
49339 'is_array' => $argument->isArray(),
49340 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()),
49341 'default' => INF === $argument->getDefault() ? 'INF' : $argument->getDefault(),
49342 );
49343 }
49344
49345
49346
49347
49348
49349
49350 private function getInputOptionData(InputOption $option)
49351 {
49352 return array(
49353 'name' => '--'.$option->getName(),
49354 'shortcut' => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '',
49355 'accept_value' => $option->acceptValue(),
49356 'is_value_required' => $option->isValueRequired(),
49357 'is_multiple' => $option->isArray(),
49358 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()),
49359 'default' => INF === $option->getDefault() ? 'INF' : $option->getDefault(),
49360 );
49361 }
49362
49363
49364
49365
49366
49367
49368 private function getInputDefinitionData(InputDefinition $definition)
49369 {
49370 $inputArguments = array();
49371 foreach ($definition->getArguments() as $name => $argument) {
49372 $inputArguments[$name] = $this->getInputArgumentData($argument);
49373 }
49374
49375 $inputOptions = array();
49376 foreach ($definition->getOptions() as $name => $option) {
49377 $inputOptions[$name] = $this->getInputOptionData($option);
49378 }
49379
49380 return array('arguments' => $inputArguments, 'options' => $inputOptions);
49381 }
49382
49383
49384
49385
49386
49387
49388 private function getCommandData(Command $command)
49389 {
49390 $command->getSynopsis();
49391 $command->mergeApplicationDefinition(false);
49392
49393 return array(
49394 'name' => $command->getName(),
49395 'usage' => array_merge(array($command->getSynopsis()), $command->getUsages(), $command->getAliases()),
49396 'description' => $command->getDescription(),
49397 'help' => $command->getProcessedHelp(),
49398 'definition' => $this->getInputDefinitionData($command->getNativeDefinition()),
49399 );
49400 }
49401 }
49402 <?php
49403
49404
49405
49406
49407
49408
49409
49410
49411
49412
49413 namespace Symfony\Component\Console\Descriptor;
49414
49415 use Symfony\Component\Console\Application;
49416 use Symfony\Component\Console\Command\Command;
49417 use Symfony\Component\Console\Helper\Helper;
49418 use Symfony\Component\Console\Input\InputArgument;
49419 use Symfony\Component\Console\Input\InputDefinition;
49420 use Symfony\Component\Console\Input\InputOption;
49421
49422
49423
49424
49425
49426
49427
49428
49429 class MarkdownDescriptor extends Descriptor
49430 {
49431
49432
49433
49434 protected function describeInputArgument(InputArgument $argument, array $options = array())
49435 {
49436 $this->write(
49437 '**'.$argument->getName().':**'."\n\n"
49438 .'* Name: '.($argument->getName() ?: '<none>')."\n"
49439 .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n"
49440 .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n"
49441 .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n  ", $argument->getDescription() ?: '<none>')."\n"
49442 .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`'
49443 );
49444 }
49445
49446
49447
49448
49449 protected function describeInputOption(InputOption $option, array $options = array())
49450 {
49451 $this->write(
49452 '**'.$option->getName().':**'."\n\n"
49453 .'* Name: `--'.$option->getName().'`'."\n"
49454 .'* Shortcut: '.($option->getShortcut() ? '`-'.implode('|-', explode('|', $option->getShortcut())).'`' : '<none>')."\n"
49455 .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n"
49456 .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
49457 .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n"
49458 .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n  ", $option->getDescription() ?: '<none>')."\n"
49459 .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`'
49460 );
49461 }
49462
49463
49464
49465
49466 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
49467 {
49468 if ($showArguments = count($definition->getArguments()) > 0) {
49469 $this->write('### Arguments:');
49470 foreach ($definition->getArguments() as $argument) {
49471 $this->write("\n\n");
49472 $this->write($this->describeInputArgument($argument));
49473 }
49474 }
49475
49476 if (count($definition->getOptions()) > 0) {
49477 if ($showArguments) {
49478 $this->write("\n\n");
49479 }
49480
49481 $this->write('### Options:');
49482 foreach ($definition->getOptions() as $option) {
49483 $this->write("\n\n");
49484 $this->write($this->describeInputOption($option));
49485 }
49486 }
49487 }
49488
49489
49490
49491
49492 protected function describeCommand(Command $command, array $options = array())
49493 {
49494 $command->getSynopsis();
49495 $command->mergeApplicationDefinition(false);
49496
49497 $this->write(
49498 $command->getName()."\n"
49499 .str_repeat('-', Helper::strlen($command->getName()))."\n\n"
49500 .'* Description: '.($command->getDescription() ?: '<none>')."\n"
49501 .'* Usage:'."\n\n"
49502 .array_reduce(array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()), function ($carry, $usage) {
49503 return $carry.'  * `'.$usage.'`'."\n";
49504 })
49505 );
49506
49507 if ($help = $command->getProcessedHelp()) {
49508 $this->write("\n");
49509 $this->write($help);
49510 }
49511
49512 if ($command->getNativeDefinition()) {
49513 $this->write("\n\n");
49514 $this->describeInputDefinition($command->getNativeDefinition());
49515 }
49516 }
49517
49518
49519
49520
49521 protected function describeApplication(Application $application, array $options = array())
49522 {
49523 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
49524 $description = new ApplicationDescription($application, $describedNamespace);
49525
49526 $this->write($application->getName()."\n".str_repeat('=', Helper::strlen($application->getName())));
49527
49528 foreach ($description->getNamespaces() as $namespace) {
49529 if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
49530 $this->write("\n\n");
49531 $this->write('**'.$namespace['id'].':**');
49532 }
49533
49534 $this->write("\n\n");
49535 $this->write(implode("\n", array_map(function ($commandName) {
49536 return '* '.$commandName;
49537 }, $namespace['commands'])));
49538 }
49539
49540 foreach ($description->getCommands() as $command) {
49541 $this->write("\n\n");
49542 $this->write($this->describeCommand($command));
49543 }
49544 }
49545 }
49546 <?php
49547
49548
49549
49550
49551
49552
49553
49554
49555
49556
49557 namespace Symfony\Component\Console\Descriptor;
49558
49559 use Symfony\Component\Console\Application;
49560 use Symfony\Component\Console\Command\Command;
49561 use Symfony\Component\Console\Formatter\OutputFormatter;
49562 use Symfony\Component\Console\Helper\Helper;
49563 use Symfony\Component\Console\Input\InputArgument;
49564 use Symfony\Component\Console\Input\InputDefinition;
49565 use Symfony\Component\Console\Input\InputOption;
49566
49567
49568
49569
49570
49571
49572
49573
49574 class TextDescriptor extends Descriptor
49575 {
49576
49577
49578
49579 protected function describeInputArgument(InputArgument $argument, array $options = array())
49580 {
49581 if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
49582 $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault()));
49583 } else {
49584 $default = '';
49585 }
49586
49587 $totalWidth = isset($options['total_width']) ? $options['total_width'] : Helper::strlen($argument->getName());
49588 $spacingWidth = $totalWidth - strlen($argument->getName());
49589
49590 $this->writeText(sprintf('  <info>%s</info>  %s%s%s',
49591 $argument->getName(),
49592 str_repeat(' ', $spacingWidth),
49593
49594  preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $argument->getDescription()),
49595 $default
49596 ), $options);
49597 }
49598
49599
49600
49601
49602 protected function describeInputOption(InputOption $option, array $options = array())
49603 {
49604 if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
49605 $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($option->getDefault()));
49606 } else {
49607 $default = '';
49608 }
49609
49610 $value = '';
49611 if ($option->acceptValue()) {
49612 $value = '='.strtoupper($option->getName());
49613
49614 if ($option->isValueOptional()) {
49615 $value = '['.$value.']';
49616 }
49617 }
49618
49619 $totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions(array($option));
49620 $synopsis = sprintf('%s%s',
49621 $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : '    ',
49622 sprintf('--%s%s', $option->getName(), $value)
49623 );
49624
49625 $spacingWidth = $totalWidth - Helper::strlen($synopsis);
49626
49627 $this->writeText(sprintf('  <info>%s</info>  %s%s%s%s',
49628 $synopsis,
49629 str_repeat(' ', $spacingWidth),
49630
49631  preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()),
49632 $default,
49633 $option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
49634 ), $options);
49635 }
49636
49637
49638
49639
49640 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
49641 {
49642 $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions());
49643 foreach ($definition->getArguments() as $argument) {
49644 $totalWidth = max($totalWidth, Helper::strlen($argument->getName()));
49645 }
49646
49647 if ($definition->getArguments()) {
49648 $this->writeText('<comment>Arguments:</comment>', $options);
49649 $this->writeText("\n");
49650 foreach ($definition->getArguments() as $argument) {
49651 $this->describeInputArgument($argument, array_merge($options, array('total_width' => $totalWidth)));
49652 $this->writeText("\n");
49653 }
49654 }
49655
49656 if ($definition->getArguments() && $definition->getOptions()) {
49657 $this->writeText("\n");
49658 }
49659
49660 if ($definition->getOptions()) {
49661 $laterOptions = array();
49662
49663 $this->writeText('<comment>Options:</comment>', $options);
49664 foreach ($definition->getOptions() as $option) {
49665 if (strlen($option->getShortcut()) > 1) {
49666 $laterOptions[] = $option;
49667 continue;
49668 }
49669 $this->writeText("\n");
49670 $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
49671 }
49672 foreach ($laterOptions as $option) {
49673 $this->writeText("\n");
49674 $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
49675 }
49676 }
49677 }
49678
49679
49680
49681
49682 protected function describeCommand(Command $command, array $options = array())
49683 {
49684 $command->getSynopsis(true);
49685 $command->getSynopsis(false);
49686 $command->mergeApplicationDefinition(false);
49687
49688 $this->writeText('<comment>Usage:</comment>', $options);
49689 foreach (array_merge(array($command->getSynopsis(true)), $command->getAliases(), $command->getUsages()) as $usage) {
49690 $this->writeText("\n");
49691 $this->writeText('  '.$usage, $options);
49692 }
49693 $this->writeText("\n");
49694
49695 $definition = $command->getNativeDefinition();
49696 if ($definition->getOptions() || $definition->getArguments()) {
49697 $this->writeText("\n");
49698 $this->describeInputDefinition($definition, $options);
49699 $this->writeText("\n");
49700 }
49701
49702 if ($help = $command->getProcessedHelp()) {
49703 $this->writeText("\n");
49704 $this->writeText('<comment>Help:</comment>', $options);
49705 $this->writeText("\n");
49706 $this->writeText('  '.str_replace("\n", "\n  ", $help), $options);
49707 $this->writeText("\n");
49708 }
49709 }
49710
49711
49712
49713
49714 protected function describeApplication(Application $application, array $options = array())
49715 {
49716 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
49717 $description = new ApplicationDescription($application, $describedNamespace);
49718
49719 if (isset($options['raw_text']) && $options['raw_text']) {
49720 $width = $this->getColumnWidth($description->getCommands());
49721
49722 foreach ($description->getCommands() as $command) {
49723 $this->writeText(sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options);
49724 $this->writeText("\n");
49725 }
49726 } else {
49727 if ('' != $help = $application->getHelp()) {
49728 $this->writeText("$help\n\n", $options);
49729 }
49730
49731 $this->writeText("<comment>Usage:</comment>\n", $options);
49732 $this->writeText("  command [options] [arguments]\n\n", $options);
49733
49734 $this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options);
49735
49736 $this->writeText("\n");
49737 $this->writeText("\n");
49738
49739 $width = $this->getColumnWidth($description->getCommands());
49740
49741 if ($describedNamespace) {
49742 $this->writeText(sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options);
49743 } else {
49744 $this->writeText('<comment>Available commands:</comment>', $options);
49745 }
49746
49747
49748  foreach ($description->getNamespaces() as $namespace) {
49749 if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
49750 $this->writeText("\n");
49751 $this->writeText(' <comment>'.$namespace['id'].'</comment>', $options);
49752 }
49753
49754 foreach ($namespace['commands'] as $name) {
49755 $this->writeText("\n");
49756 $spacingWidth = $width - Helper::strlen($name);
49757 $this->writeText(sprintf('  <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $description->getCommand($name)->getDescription()), $options);
49758 }
49759 }
49760
49761 $this->writeText("\n");
49762 }
49763 }
49764
49765
49766
49767
49768 private function writeText($content, array $options = array())
49769 {
49770 $this->write(
49771 isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content,
49772 isset($options['raw_output']) ? !$options['raw_output'] : true
49773 );
49774 }
49775
49776
49777
49778
49779
49780
49781
49782
49783 private function formatDefaultValue($default)
49784 {
49785 if (INF === $default) {
49786 return 'INF';
49787 }
49788
49789 if (is_string($default)) {
49790 $default = OutputFormatter::escape($default);
49791 } elseif (is_array($default)) {
49792 foreach ($default as $key => $value) {
49793 if (is_string($value)) {
49794 $default[$key] = OutputFormatter::escape($value);
49795 }
49796 }
49797 }
49798
49799 if (\PHP_VERSION_ID < 50400) {
49800 return str_replace(array('\/', '\\\\'), array('/', '\\'), json_encode($default));
49801 }
49802
49803 return str_replace('\\\\', '\\', json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
49804 }
49805
49806
49807
49808
49809
49810
49811 private function getColumnWidth(array $commands)
49812 {
49813 $widths = array();
49814
49815 foreach ($commands as $command) {
49816 $widths[] = Helper::strlen($command->getName());
49817 foreach ($command->getAliases() as $alias) {
49818 $widths[] = Helper::strlen($alias);
49819 }
49820 }
49821
49822 return max($widths) + 2;
49823 }
49824
49825
49826
49827
49828
49829
49830 private function calculateTotalWidthForOptions($options)
49831 {
49832 $totalWidth = 0;
49833 foreach ($options as $option) {
49834
49835  $nameLength = 1 + max(strlen($option->getShortcut()), 1) + 4 + Helper::strlen($option->getName());
49836
49837 if ($option->acceptValue()) {
49838 $valueLength = 1 + Helper::strlen($option->getName()); 
49839  $valueLength += $option->isValueOptional() ? 2 : 0; 
49840
49841 $nameLength += $valueLength;
49842 }
49843 $totalWidth = max($totalWidth, $nameLength);
49844 }
49845
49846 return $totalWidth;
49847 }
49848 }
49849 <?php
49850
49851
49852
49853
49854
49855
49856
49857
49858
49859
49860 namespace Symfony\Component\Console\Descriptor;
49861
49862 use Symfony\Component\Console\Application;
49863 use Symfony\Component\Console\Command\Command;
49864 use Symfony\Component\Console\Input\InputArgument;
49865 use Symfony\Component\Console\Input\InputDefinition;
49866 use Symfony\Component\Console\Input\InputOption;
49867
49868
49869
49870
49871
49872
49873
49874
49875 class XmlDescriptor extends Descriptor
49876 {
49877
49878
49879
49880
49881
49882 public function getInputDefinitionDocument(InputDefinition $definition)
49883 {
49884 $dom = new \DOMDocument('1.0', 'UTF-8');
49885 $dom->appendChild($definitionXML = $dom->createElement('definition'));
49886
49887 $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
49888 foreach ($definition->getArguments() as $argument) {
49889 $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument));
49890 }
49891
49892 $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
49893 foreach ($definition->getOptions() as $option) {
49894 $this->appendDocument($optionsXML, $this->getInputOptionDocument($option));
49895 }
49896
49897 return $dom;
49898 }
49899
49900
49901
49902
49903
49904
49905 public function getCommandDocument(Command $command)
49906 {
49907 $dom = new \DOMDocument('1.0', 'UTF-8');
49908 $dom->appendChild($commandXML = $dom->createElement('command'));
49909
49910 $command->getSynopsis();
49911 $command->mergeApplicationDefinition(false);
49912
49913 $commandXML->setAttribute('id', $command->getName());
49914 $commandXML->setAttribute('name', $command->getName());
49915
49916 $commandXML->appendChild($usagesXML = $dom->createElement('usages'));
49917
49918 foreach (array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()) as $usage) {
49919 $usagesXML->appendChild($dom->createElement('usage', $usage));
49920 }
49921
49922 $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
49923 $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription())));
49924
49925 $commandXML->appendChild($helpXML = $dom->createElement('help'));
49926 $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));
49927
49928 $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition());
49929 $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));
49930
49931 return $dom;
49932 }
49933
49934
49935
49936
49937
49938
49939
49940 public function getApplicationDocument(Application $application, $namespace = null)
49941 {
49942 $dom = new \DOMDocument('1.0', 'UTF-8');
49943 $dom->appendChild($rootXml = $dom->createElement('symfony'));
49944
49945 if ($application->getName() !== 'UNKNOWN') {
49946 $rootXml->setAttribute('name', $application->getName());
49947 if ($application->getVersion() !== 'UNKNOWN') {
49948 $rootXml->setAttribute('version', $application->getVersion());
49949 }
49950 }
49951
49952 $rootXml->appendChild($commandsXML = $dom->createElement('commands'));
49953
49954 $description = new ApplicationDescription($application, $namespace);
49955
49956 if ($namespace) {
49957 $commandsXML->setAttribute('namespace', $namespace);
49958 }
49959
49960 foreach ($description->getCommands() as $command) {
49961 $this->appendDocument($commandsXML, $this->getCommandDocument($command));
49962 }
49963
49964 if (!$namespace) {
49965 $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces'));
49966
49967 foreach ($description->getNamespaces() as $namespaceDescription) {
49968 $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
49969 $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']);
49970
49971 foreach ($namespaceDescription['commands'] as $name) {
49972 $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
49973 $commandXML->appendChild($dom->createTextNode($name));
49974 }
49975 }
49976 }
49977
49978 return $dom;
49979 }
49980
49981
49982
49983
49984 protected function describeInputArgument(InputArgument $argument, array $options = array())
49985 {
49986 $this->writeDocument($this->getInputArgumentDocument($argument));
49987 }
49988
49989
49990
49991
49992 protected function describeInputOption(InputOption $option, array $options = array())
49993 {
49994 $this->writeDocument($this->getInputOptionDocument($option));
49995 }
49996
49997
49998
49999
50000 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
50001 {
50002 $this->writeDocument($this->getInputDefinitionDocument($definition));
50003 }
50004
50005
50006
50007
50008 protected function describeCommand(Command $command, array $options = array())
50009 {
50010 $this->writeDocument($this->getCommandDocument($command));
50011 }
50012
50013
50014
50015
50016 protected function describeApplication(Application $application, array $options = array())
50017 {
50018 $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null));
50019 }
50020
50021
50022
50023
50024
50025
50026
50027 private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent)
50028 {
50029 foreach ($importedParent->childNodes as $childNode) {
50030 $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true));
50031 }
50032 }
50033
50034
50035
50036
50037
50038
50039
50040
50041 private function writeDocument(\DOMDocument $dom)
50042 {
50043 $dom->formatOutput = true;
50044 $this->write($dom->saveXML());
50045 }
50046
50047
50048
50049
50050
50051
50052 private function getInputArgumentDocument(InputArgument $argument)
50053 {
50054 $dom = new \DOMDocument('1.0', 'UTF-8');
50055
50056 $dom->appendChild($objectXML = $dom->createElement('argument'));
50057 $objectXML->setAttribute('name', $argument->getName());
50058 $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
50059 $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
50060 $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
50061 $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
50062
50063 $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
50064 $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : (is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array()));
50065 foreach ($defaults as $default) {
50066 $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
50067 $defaultXML->appendChild($dom->createTextNode($default));
50068 }
50069
50070 return $dom;
50071 }
50072
50073
50074
50075
50076
50077
50078 private function getInputOptionDocument(InputOption $option)
50079 {
50080 $dom = new \DOMDocument('1.0', 'UTF-8');
50081
50082 $dom->appendChild($objectXML = $dom->createElement('option'));
50083 $objectXML->setAttribute('name', '--'.$option->getName());
50084 $pos = strpos($option->getShortcut(), '|');
50085 if (false !== $pos) {
50086 $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos));
50087 $objectXML->setAttribute('shortcuts', '-'.implode('|-', explode('|', $option->getShortcut())));
50088 } else {
50089 $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
50090 }
50091 $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
50092 $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
50093 $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
50094 $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
50095 $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
50096
50097 if ($option->acceptValue()) {
50098 $defaults = is_array($option->getDefault()) ? $option->getDefault() : (is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array()));
50099 $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
50100
50101 if (!empty($defaults)) {
50102 foreach ($defaults as $default) {
50103 $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
50104 $defaultXML->appendChild($dom->createTextNode($default));
50105 }
50106 }
50107 }
50108
50109 return $dom;
50110 }
50111 }
50112 <?php
50113
50114
50115
50116
50117
50118
50119
50120
50121
50122
50123 namespace Symfony\Component\Console\Event;
50124
50125
50126
50127
50128
50129
50130 class ConsoleCommandEvent extends ConsoleEvent
50131 {
50132
50133
50134
50135 const RETURN_CODE_DISABLED = 113;
50136
50137
50138
50139
50140
50141
50142 private $commandShouldRun = true;
50143
50144
50145
50146
50147
50148
50149 public function disableCommand()
50150 {
50151 return $this->commandShouldRun = false;
50152 }
50153
50154
50155
50156
50157
50158
50159 public function enableCommand()
50160 {
50161 return $this->commandShouldRun = true;
50162 }
50163
50164
50165
50166
50167
50168
50169 public function commandShouldRun()
50170 {
50171 return $this->commandShouldRun;
50172 }
50173 }
50174 <?php
50175
50176
50177
50178
50179
50180
50181
50182
50183
50184
50185 namespace Symfony\Component\Console\Event;
50186
50187 use Symfony\Component\Console\Command\Command;
50188 use Symfony\Component\Console\Input\InputInterface;
50189 use Symfony\Component\Console\Output\OutputInterface;
50190 use Symfony\Component\EventDispatcher\Event;
50191
50192
50193
50194
50195
50196
50197 class ConsoleEvent extends Event
50198 {
50199 protected $command;
50200
50201 private $input;
50202 private $output;
50203
50204 public function __construct(Command $command, InputInterface $input, OutputInterface $output)
50205 {
50206 $this->command = $command;
50207 $this->input = $input;
50208 $this->output = $output;
50209 }
50210
50211
50212
50213
50214
50215
50216 public function getCommand()
50217 {
50218 return $this->command;
50219 }
50220
50221
50222
50223
50224
50225
50226 public function getInput()
50227 {
50228 return $this->input;
50229 }
50230
50231
50232
50233
50234
50235
50236 public function getOutput()
50237 {
50238 return $this->output;
50239 }
50240 }
50241 <?php
50242
50243
50244
50245
50246
50247
50248
50249
50250
50251
50252 namespace Symfony\Component\Console\Event;
50253
50254 use Symfony\Component\Console\Command\Command;
50255 use Symfony\Component\Console\Input\InputInterface;
50256 use Symfony\Component\Console\Output\OutputInterface;
50257
50258
50259
50260
50261
50262
50263 class ConsoleExceptionEvent extends ConsoleEvent
50264 {
50265 private $exception;
50266 private $exitCode;
50267
50268 public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode)
50269 {
50270 parent::__construct($command, $input, $output);
50271
50272 $this->setException($exception);
50273 $this->exitCode = (int) $exitCode;
50274 }
50275
50276
50277
50278
50279
50280
50281 public function getException()
50282 {
50283 return $this->exception;
50284 }
50285
50286
50287
50288
50289
50290
50291
50292
50293 public function setException(\Exception $exception)
50294 {
50295 $this->exception = $exception;
50296 }
50297
50298
50299
50300
50301
50302
50303 public function getExitCode()
50304 {
50305 return $this->exitCode;
50306 }
50307 }
50308 <?php
50309
50310
50311
50312
50313
50314
50315
50316
50317
50318
50319 namespace Symfony\Component\Console\Event;
50320
50321 use Symfony\Component\Console\Command\Command;
50322 use Symfony\Component\Console\Input\InputInterface;
50323 use Symfony\Component\Console\Output\OutputInterface;
50324
50325
50326
50327
50328
50329
50330 class ConsoleTerminateEvent extends ConsoleEvent
50331 {
50332
50333
50334
50335
50336
50337 private $exitCode;
50338
50339 public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode)
50340 {
50341 parent::__construct($command, $input, $output);
50342
50343 $this->setExitCode($exitCode);
50344 }
50345
50346
50347
50348
50349
50350
50351 public function setExitCode($exitCode)
50352 {
50353 $this->exitCode = (int) $exitCode;
50354 }
50355
50356
50357
50358
50359
50360
50361 public function getExitCode()
50362 {
50363 return $this->exitCode;
50364 }
50365 }
50366 <?php
50367
50368
50369
50370
50371
50372
50373
50374
50375
50376
50377 namespace Symfony\Component\Console\Exception;
50378
50379
50380
50381
50382
50383
50384 class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface
50385 {
50386 private $alternatives;
50387
50388
50389
50390
50391
50392
50393
50394 public function __construct($message, array $alternatives = array(), $code = 0, \Exception $previous = null)
50395 {
50396 parent::__construct($message, $code, $previous);
50397
50398 $this->alternatives = $alternatives;
50399 }
50400
50401
50402
50403
50404 public function getAlternatives()
50405 {
50406 return $this->alternatives;
50407 }
50408 }
50409 <?php
50410
50411
50412
50413
50414
50415
50416
50417
50418
50419
50420 namespace Symfony\Component\Console\Exception;
50421
50422
50423
50424
50425
50426
50427 interface ExceptionInterface
50428 {
50429 }
50430 <?php
50431
50432
50433
50434
50435
50436
50437
50438
50439
50440
50441 namespace Symfony\Component\Console\Exception;
50442
50443
50444
50445
50446 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
50447 {
50448 }
50449 <?php
50450
50451
50452
50453
50454
50455
50456
50457
50458
50459
50460 namespace Symfony\Component\Console\Exception;
50461
50462
50463
50464
50465
50466
50467 class InvalidOptionException extends \InvalidArgumentException implements ExceptionInterface
50468 {
50469 }
50470 <?php
50471
50472
50473
50474
50475
50476
50477
50478
50479
50480
50481 namespace Symfony\Component\Console\Exception;
50482
50483
50484
50485
50486 class LogicException extends \LogicException implements ExceptionInterface
50487 {
50488 }
50489 <?php
50490
50491
50492
50493
50494
50495
50496
50497
50498
50499
50500 namespace Symfony\Component\Console\Exception;
50501
50502
50503
50504
50505 class RuntimeException extends \RuntimeException implements ExceptionInterface
50506 {
50507 }
50508 <?php
50509
50510
50511
50512
50513
50514
50515
50516
50517
50518
50519 namespace Symfony\Component\Console\Formatter;
50520
50521 use Symfony\Component\Console\Exception\InvalidArgumentException;
50522
50523
50524
50525
50526
50527
50528 class OutputFormatter implements OutputFormatterInterface
50529 {
50530 private $decorated;
50531 private $styles = array();
50532 private $styleStack;
50533
50534
50535
50536
50537
50538
50539
50540
50541 public static function escape($text)
50542 {
50543 $text = preg_replace('/([^\\\\]?)</', '$1\\<', $text);
50544
50545 return self::escapeTrailingBackslash($text);
50546 }
50547
50548
50549
50550
50551
50552
50553
50554
50555
50556
50557 public static function escapeTrailingBackslash($text)
50558 {
50559 if ('\\' === substr($text, -1)) {
50560 $len = strlen($text);
50561 $text = rtrim($text, '\\');
50562 $text .= str_repeat('<<', $len - strlen($text));
50563 }
50564
50565 return $text;
50566 }
50567
50568
50569
50570
50571
50572
50573
50574 public function __construct($decorated = false, array $styles = array())
50575 {
50576 $this->decorated = (bool) $decorated;
50577
50578 $this->setStyle('error', new OutputFormatterStyle('white', 'red'));
50579 $this->setStyle('info', new OutputFormatterStyle('green'));
50580 $this->setStyle('comment', new OutputFormatterStyle('yellow'));
50581 $this->setStyle('question', new OutputFormatterStyle('black', 'cyan'));
50582
50583 foreach ($styles as $name => $style) {
50584 $this->setStyle($name, $style);
50585 }
50586
50587 $this->styleStack = new OutputFormatterStyleStack();
50588 }
50589
50590
50591
50592
50593 public function setDecorated($decorated)
50594 {
50595 $this->decorated = (bool) $decorated;
50596 }
50597
50598
50599
50600
50601 public function isDecorated()
50602 {
50603 return $this->decorated;
50604 }
50605
50606
50607
50608
50609 public function setStyle($name, OutputFormatterStyleInterface $style)
50610 {
50611 $this->styles[strtolower($name)] = $style;
50612 }
50613
50614
50615
50616
50617 public function hasStyle($name)
50618 {
50619 return isset($this->styles[strtolower($name)]);
50620 }
50621
50622
50623
50624
50625 public function getStyle($name)
50626 {
50627 if (!$this->hasStyle($name)) {
50628 throw new InvalidArgumentException(sprintf('Undefined style: %s', $name));
50629 }
50630
50631 return $this->styles[strtolower($name)];
50632 }
50633
50634
50635
50636
50637 public function format($message)
50638 {
50639 $message = (string) $message;
50640 $offset = 0;
50641 $output = '';
50642 $tagRegex = '[a-z][a-z0-9_=;-]*+';
50643 preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE);
50644 foreach ($matches[0] as $i => $match) {
50645 $pos = $match[1];
50646 $text = $match[0];
50647
50648 if (0 != $pos && '\\' == $message[$pos - 1]) {
50649 continue;
50650 }
50651
50652
50653  $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset));
50654 $offset = $pos + strlen($text);
50655
50656
50657  if ($open = '/' != $text[1]) {
50658 $tag = $matches[1][$i][0];
50659 } else {
50660 $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : '';
50661 }
50662
50663 if (!$open && !$tag) {
50664
50665  $this->styleStack->pop();
50666 } elseif (false === $style = $this->createStyleFromString(strtolower($tag))) {
50667 $output .= $this->applyCurrentStyle($text);
50668 } elseif ($open) {
50669 $this->styleStack->push($style);
50670 } else {
50671 $this->styleStack->pop($style);
50672 }
50673 }
50674
50675 $output .= $this->applyCurrentStyle(substr($message, $offset));
50676
50677 if (false !== strpos($output, '<<')) {
50678 return strtr($output, array('\\<' => '<', '<<' => '\\'));
50679 }
50680
50681 return str_replace('\\<', '<', $output);
50682 }
50683
50684
50685
50686
50687 public function getStyleStack()
50688 {
50689 return $this->styleStack;
50690 }
50691
50692
50693
50694
50695
50696
50697
50698
50699 private function createStyleFromString($string)
50700 {
50701 if (isset($this->styles[$string])) {
50702 return $this->styles[$string];
50703 }
50704
50705 if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) {
50706 return false;
50707 }
50708
50709 $style = new OutputFormatterStyle();
50710 foreach ($matches as $match) {
50711 array_shift($match);
50712
50713 if ('fg' == $match[0]) {
50714 $style->setForeground($match[1]);
50715 } elseif ('bg' == $match[0]) {
50716 $style->setBackground($match[1]);
50717 } else {
50718 try {
50719 $style->setOption($match[1]);
50720 } catch (\InvalidArgumentException $e) {
50721 return false;
50722 }
50723 }
50724 }
50725
50726 return $style;
50727 }
50728
50729
50730
50731
50732
50733
50734
50735
50736 private function applyCurrentStyle($text)
50737 {
50738 return $this->isDecorated() && strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text;
50739 }
50740 }
50741 <?php
50742
50743
50744
50745
50746
50747
50748
50749
50750
50751
50752 namespace Symfony\Component\Console\Formatter;
50753
50754
50755
50756
50757
50758
50759 interface OutputFormatterInterface
50760 {
50761
50762
50763
50764
50765
50766 public function setDecorated($decorated);
50767
50768
50769
50770
50771
50772
50773 public function isDecorated();
50774
50775
50776
50777
50778
50779
50780
50781 public function setStyle($name, OutputFormatterStyleInterface $style);
50782
50783
50784
50785
50786
50787
50788
50789
50790 public function hasStyle($name);
50791
50792
50793
50794
50795
50796
50797
50798
50799
50800
50801 public function getStyle($name);
50802
50803
50804
50805
50806
50807
50808
50809
50810 public function format($message);
50811 }
50812 <?php
50813
50814
50815
50816
50817
50818
50819
50820
50821
50822
50823 namespace Symfony\Component\Console\Formatter;
50824
50825 use Symfony\Component\Console\Exception\InvalidArgumentException;
50826
50827
50828
50829
50830
50831
50832 class OutputFormatterStyle implements OutputFormatterStyleInterface
50833 {
50834 private static $availableForegroundColors = array(
50835 'black' => array('set' => 30, 'unset' => 39),
50836 'red' => array('set' => 31, 'unset' => 39),
50837 'green' => array('set' => 32, 'unset' => 39),
50838 'yellow' => array('set' => 33, 'unset' => 39),
50839 'blue' => array('set' => 34, 'unset' => 39),
50840 'magenta' => array('set' => 35, 'unset' => 39),
50841 'cyan' => array('set' => 36, 'unset' => 39),
50842 'white' => array('set' => 37, 'unset' => 39),
50843 'default' => array('set' => 39, 'unset' => 39),
50844 );
50845 private static $availableBackgroundColors = array(
50846 'black' => array('set' => 40, 'unset' => 49),
50847 'red' => array('set' => 41, 'unset' => 49),
50848 'green' => array('set' => 42, 'unset' => 49),
50849 'yellow' => array('set' => 43, 'unset' => 49),
50850 'blue' => array('set' => 44, 'unset' => 49),
50851 'magenta' => array('set' => 45, 'unset' => 49),
50852 'cyan' => array('set' => 46, 'unset' => 49),
50853 'white' => array('set' => 47, 'unset' => 49),
50854 'default' => array('set' => 49, 'unset' => 49),
50855 );
50856 private static $availableOptions = array(
50857 'bold' => array('set' => 1, 'unset' => 22),
50858 'underscore' => array('set' => 4, 'unset' => 24),
50859 'blink' => array('set' => 5, 'unset' => 25),
50860 'reverse' => array('set' => 7, 'unset' => 27),
50861 'conceal' => array('set' => 8, 'unset' => 28),
50862 );
50863
50864 private $foreground;
50865 private $background;
50866 private $options = array();
50867
50868
50869
50870
50871
50872
50873
50874
50875 public function __construct($foreground = null, $background = null, array $options = array())
50876 {
50877 if (null !== $foreground) {
50878 $this->setForeground($foreground);
50879 }
50880 if (null !== $background) {
50881 $this->setBackground($background);
50882 }
50883 if (count($options)) {
50884 $this->setOptions($options);
50885 }
50886 }
50887
50888
50889
50890
50891
50892
50893
50894
50895 public function setForeground($color = null)
50896 {
50897 if (null === $color) {
50898 $this->foreground = null;
50899
50900 return;
50901 }
50902
50903 if (!isset(static::$availableForegroundColors[$color])) {
50904 throw new InvalidArgumentException(sprintf(
50905 'Invalid foreground color specified: "%s". Expected one of (%s)',
50906 $color,
50907 implode(', ', array_keys(static::$availableForegroundColors))
50908 ));
50909 }
50910
50911 $this->foreground = static::$availableForegroundColors[$color];
50912 }
50913
50914
50915
50916
50917
50918
50919
50920
50921 public function setBackground($color = null)
50922 {
50923 if (null === $color) {
50924 $this->background = null;
50925
50926 return;
50927 }
50928
50929 if (!isset(static::$availableBackgroundColors[$color])) {
50930 throw new InvalidArgumentException(sprintf(
50931 'Invalid background color specified: "%s". Expected one of (%s)',
50932 $color,
50933 implode(', ', array_keys(static::$availableBackgroundColors))
50934 ));
50935 }
50936
50937 $this->background = static::$availableBackgroundColors[$color];
50938 }
50939
50940
50941
50942
50943
50944
50945
50946
50947 public function setOption($option)
50948 {
50949 if (!isset(static::$availableOptions[$option])) {
50950 throw new InvalidArgumentException(sprintf(
50951 'Invalid option specified: "%s". Expected one of (%s)',
50952 $option,
50953 implode(', ', array_keys(static::$availableOptions))
50954 ));
50955 }
50956
50957 if (!in_array(static::$availableOptions[$option], $this->options)) {
50958 $this->options[] = static::$availableOptions[$option];
50959 }
50960 }
50961
50962
50963
50964
50965
50966
50967
50968
50969 public function unsetOption($option)
50970 {
50971 if (!isset(static::$availableOptions[$option])) {
50972 throw new InvalidArgumentException(sprintf(
50973 'Invalid option specified: "%s". Expected one of (%s)',
50974 $option,
50975 implode(', ', array_keys(static::$availableOptions))
50976 ));
50977 }
50978
50979 $pos = array_search(static::$availableOptions[$option], $this->options);
50980 if (false !== $pos) {
50981 unset($this->options[$pos]);
50982 }
50983 }
50984
50985
50986
50987
50988
50989
50990 public function setOptions(array $options)
50991 {
50992 $this->options = array();
50993
50994 foreach ($options as $option) {
50995 $this->setOption($option);
50996 }
50997 }
50998
50999
51000
51001
51002
51003
51004
51005
51006 public function apply($text)
51007 {
51008 $setCodes = array();
51009 $unsetCodes = array();
51010
51011 if (null !== $this->foreground) {
51012 $setCodes[] = $this->foreground['set'];
51013 $unsetCodes[] = $this->foreground['unset'];
51014 }
51015 if (null !== $this->background) {
51016 $setCodes[] = $this->background['set'];
51017 $unsetCodes[] = $this->background['unset'];
51018 }
51019 if (count($this->options)) {
51020 foreach ($this->options as $option) {
51021 $setCodes[] = $option['set'];
51022 $unsetCodes[] = $option['unset'];
51023 }
51024 }
51025
51026 if (0 === count($setCodes)) {
51027 return $text;
51028 }
51029
51030 return sprintf("\033[%sm%s\033[%sm", implode(';', $setCodes), $text, implode(';', $unsetCodes));
51031 }
51032 }
51033 <?php
51034
51035
51036
51037
51038
51039
51040
51041
51042
51043
51044 namespace Symfony\Component\Console\Formatter;
51045
51046
51047
51048
51049
51050
51051 interface OutputFormatterStyleInterface
51052 {
51053
51054
51055
51056
51057
51058 public function setForeground($color = null);
51059
51060
51061
51062
51063
51064
51065 public function setBackground($color = null);
51066
51067
51068
51069
51070
51071
51072 public function setOption($option);
51073
51074
51075
51076
51077
51078
51079 public function unsetOption($option);
51080
51081
51082
51083
51084
51085
51086 public function setOptions(array $options);
51087
51088
51089
51090
51091
51092
51093
51094
51095 public function apply($text);
51096 }
51097 <?php
51098
51099
51100
51101
51102
51103
51104
51105
51106
51107
51108 namespace Symfony\Component\Console\Formatter;
51109
51110 use Symfony\Component\Console\Exception\InvalidArgumentException;
51111
51112
51113
51114
51115 class OutputFormatterStyleStack
51116 {
51117
51118
51119
51120 private $styles;
51121
51122
51123
51124
51125 private $emptyStyle;
51126
51127
51128
51129
51130
51131
51132 public function __construct(OutputFormatterStyleInterface $emptyStyle = null)
51133 {
51134 $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle();
51135 $this->reset();
51136 }
51137
51138
51139
51140
51141 public function reset()
51142 {
51143 $this->styles = array();
51144 }
51145
51146
51147
51148
51149
51150
51151 public function push(OutputFormatterStyleInterface $style)
51152 {
51153 $this->styles[] = $style;
51154 }
51155
51156
51157
51158
51159
51160
51161
51162
51163
51164
51165 public function pop(OutputFormatterStyleInterface $style = null)
51166 {
51167 if (empty($this->styles)) {
51168 return $this->emptyStyle;
51169 }
51170
51171 if (null === $style) {
51172 return array_pop($this->styles);
51173 }
51174
51175 foreach (array_reverse($this->styles, true) as $index => $stackedStyle) {
51176 if ($style->apply('') === $stackedStyle->apply('')) {
51177 $this->styles = array_slice($this->styles, 0, $index);
51178
51179 return $stackedStyle;
51180 }
51181 }
51182
51183 throw new InvalidArgumentException('Incorrectly nested style tag found.');
51184 }
51185
51186
51187
51188
51189
51190
51191 public function getCurrent()
51192 {
51193 if (empty($this->styles)) {
51194 return $this->emptyStyle;
51195 }
51196
51197 return $this->styles[count($this->styles) - 1];
51198 }
51199
51200
51201
51202
51203
51204
51205 public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle)
51206 {
51207 $this->emptyStyle = $emptyStyle;
51208
51209 return $this;
51210 }
51211
51212
51213
51214
51215 public function getEmptyStyle()
51216 {
51217 return $this->emptyStyle;
51218 }
51219 }
51220 <?php
51221
51222
51223
51224
51225
51226
51227
51228
51229
51230
51231 namespace Symfony\Component\Console\Helper;
51232
51233
51234
51235
51236
51237
51238
51239
51240 class DebugFormatterHelper extends Helper
51241 {
51242 private $colors = array('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default');
51243 private $started = array();
51244 private $count = -1;
51245
51246
51247
51248
51249
51250
51251
51252
51253
51254
51255 public function start($id, $message, $prefix = 'RUN')
51256 {
51257 $this->started[$id] = array('border' => ++$this->count % count($this->colors));
51258
51259 return sprintf("%s<bg=blue;fg=white> %s </> <fg=blue>%s</>\n", $this->getBorder($id), $prefix, $message);
51260 }
51261
51262
51263
51264
51265
51266
51267
51268
51269
51270
51271
51272
51273 public function progress($id, $buffer, $error = false, $prefix = 'OUT', $errorPrefix = 'ERR')
51274 {
51275 $message = '';
51276
51277 if ($error) {
51278 if (isset($this->started[$id]['out'])) {
51279 $message .= "\n";
51280 unset($this->started[$id]['out']);
51281 }
51282 if (!isset($this->started[$id]['err'])) {
51283 $message .= sprintf('%s<bg=red;fg=white> %s </> ', $this->getBorder($id), $errorPrefix);
51284 $this->started[$id]['err'] = true;
51285 }
51286
51287 $message .= str_replace("\n", sprintf("\n%s<bg=red;fg=white> %s </> ", $this->getBorder($id), $errorPrefix), $buffer);
51288 } else {
51289 if (isset($this->started[$id]['err'])) {
51290 $message .= "\n";
51291 unset($this->started[$id]['err']);
51292 }
51293 if (!isset($this->started[$id]['out'])) {
51294 $message .= sprintf('%s<bg=green;fg=white> %s </> ', $this->getBorder($id), $prefix);
51295 $this->started[$id]['out'] = true;
51296 }
51297
51298 $message .= str_replace("\n", sprintf("\n%s<bg=green;fg=white> %s </> ", $this->getBorder($id), $prefix), $buffer);
51299 }
51300
51301 return $message;
51302 }
51303
51304
51305
51306
51307
51308
51309
51310
51311
51312
51313
51314 public function stop($id, $message, $successful, $prefix = 'RES')
51315 {
51316 $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : '';
51317
51318 if ($successful) {
51319 return sprintf("%s%s<bg=green;fg=white> %s </> <fg=green>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
51320 }
51321
51322 $message = sprintf("%s%s<bg=red;fg=white> %s </> <fg=red>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
51323
51324 unset($this->started[$id]['out'], $this->started[$id]['err']);
51325
51326 return $message;
51327 }
51328
51329
51330
51331
51332
51333
51334 private function getBorder($id)
51335 {
51336 return sprintf('<bg=%s> </>', $this->colors[$this->started[$id]['border']]);
51337 }
51338
51339
51340
51341
51342 public function getName()
51343 {
51344 return 'debug_formatter';
51345 }
51346 }
51347 <?php
51348
51349
51350
51351
51352
51353
51354
51355
51356
51357
51358 namespace Symfony\Component\Console\Helper;
51359
51360 use Symfony\Component\Console\Descriptor\DescriptorInterface;
51361 use Symfony\Component\Console\Descriptor\JsonDescriptor;
51362 use Symfony\Component\Console\Descriptor\MarkdownDescriptor;
51363 use Symfony\Component\Console\Descriptor\TextDescriptor;
51364 use Symfony\Component\Console\Descriptor\XmlDescriptor;
51365 use Symfony\Component\Console\Output\OutputInterface;
51366 use Symfony\Component\Console\Exception\InvalidArgumentException;
51367
51368
51369
51370
51371
51372
51373 class DescriptorHelper extends Helper
51374 {
51375
51376
51377
51378 private $descriptors = array();
51379
51380
51381
51382
51383 public function __construct()
51384 {
51385 $this
51386 ->register('txt', new TextDescriptor())
51387 ->register('xml', new XmlDescriptor())
51388 ->register('json', new JsonDescriptor())
51389 ->register('md', new MarkdownDescriptor())
51390 ;
51391 }
51392
51393
51394
51395
51396
51397
51398
51399
51400
51401
51402
51403
51404
51405
51406 public function describe(OutputInterface $output, $object, array $options = array())
51407 {
51408 $options = array_merge(array(
51409 'raw_text' => false,
51410 'format' => 'txt',
51411 ), $options);
51412
51413 if (!isset($this->descriptors[$options['format']])) {
51414 throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format']));
51415 }
51416
51417 $descriptor = $this->descriptors[$options['format']];
51418 $descriptor->describe($output, $object, $options);
51419 }
51420
51421
51422
51423
51424
51425
51426
51427
51428
51429 public function register($format, DescriptorInterface $descriptor)
51430 {
51431 $this->descriptors[$format] = $descriptor;
51432
51433 return $this;
51434 }
51435
51436
51437
51438
51439 public function getName()
51440 {
51441 return 'descriptor';
51442 }
51443 }
51444 <?php
51445
51446
51447
51448
51449
51450
51451
51452
51453
51454
51455 namespace Symfony\Component\Console\Helper;
51456
51457 use Symfony\Component\Console\Exception\InvalidArgumentException;
51458 use Symfony\Component\Console\Exception\RuntimeException;
51459 use Symfony\Component\Console\Output\ConsoleOutputInterface;
51460 use Symfony\Component\Console\Output\OutputInterface;
51461 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
51462
51463
51464
51465
51466
51467
51468
51469
51470
51471 class DialogHelper extends InputAwareHelper
51472 {
51473 private $inputStream;
51474 private static $shell;
51475 private static $stty;
51476
51477 public function __construct($triggerDeprecationError = true)
51478 {
51479 if ($triggerDeprecationError) {
51480 @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);
51481 }
51482 }
51483
51484
51485
51486
51487
51488
51489
51490
51491
51492
51493
51494
51495
51496
51497
51498
51499 public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
51500 {
51501 if ($output instanceof ConsoleOutputInterface) {
51502 $output = $output->getErrorOutput();
51503 }
51504
51505 $width = max(array_map('strlen', array_keys($choices)));
51506
51507 $messages = (array) $question;
51508 foreach ($choices as $key => $value) {
51509 $messages[] = sprintf("  [<info>%-{$width}s</info>] %s", $key, $value);
51510 }
51511
51512 $output->writeln($messages);
51513
51514 $result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage, $multiselect) {
51515
51516  $selectedChoices = str_replace(' ', '', $picked);
51517
51518 if ($multiselect) {
51519
51520  if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) {
51521 throw new InvalidArgumentException(sprintf($errorMessage, $picked));
51522 }
51523 $selectedChoices = explode(',', $selectedChoices);
51524 } else {
51525 $selectedChoices = array($picked);
51526 }
51527
51528 $multiselectChoices = array();
51529
51530 foreach ($selectedChoices as $value) {
51531 if (empty($choices[$value])) {
51532 throw new InvalidArgumentException(sprintf($errorMessage, $value));
51533 }
51534 $multiselectChoices[] = $value;
51535 }
51536
51537 if ($multiselect) {
51538 return $multiselectChoices;
51539 }
51540
51541 return $picked;
51542 }, $attempts, $default);
51543
51544 return $result;
51545 }
51546
51547
51548
51549
51550
51551
51552
51553
51554
51555
51556
51557
51558
51559 public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null)
51560 {
51561 if ($this->input && !$this->input->isInteractive()) {
51562 return $default;
51563 }
51564
51565 if ($output instanceof ConsoleOutputInterface) {
51566 $output = $output->getErrorOutput();
51567 }
51568
51569 $output->write($question);
51570
51571 $inputStream = $this->inputStream ?: STDIN;
51572
51573 if (null === $autocomplete || !$this->hasSttyAvailable()) {
51574 $ret = fgets($inputStream, 4096);
51575 if (false === $ret) {
51576 throw new RuntimeException('Aborted');
51577 }
51578 $ret = trim($ret);
51579 } else {
51580 $ret = '';
51581
51582 $i = 0;
51583 $ofs = -1;
51584 $matches = $autocomplete;
51585 $numMatches = count($matches);
51586
51587 $sttyMode = shell_exec('stty -g');
51588
51589
51590  shell_exec('stty -icanon -echo');
51591
51592
51593  $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
51594
51595
51596  while (!feof($inputStream)) {
51597 $c = fread($inputStream, 1);
51598
51599
51600  if ("\177" === $c) {
51601 if (0 === $numMatches && 0 !== $i) {
51602 --$i;
51603
51604  $output->write("\033[1D");
51605 }
51606
51607 if ($i === 0) {
51608 $ofs = -1;
51609 $matches = $autocomplete;
51610 $numMatches = count($matches);
51611 } else {
51612 $numMatches = 0;
51613 }
51614
51615
51616  $ret = substr($ret, 0, $i);
51617 } elseif ("\033" === $c) {
51618
51619  $c .= fread($inputStream, 2);
51620
51621
51622  if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
51623 if ('A' === $c[2] && -1 === $ofs) {
51624 $ofs = 0;
51625 }
51626
51627 if (0 === $numMatches) {
51628 continue;
51629 }
51630
51631 $ofs += ('A' === $c[2]) ? -1 : 1;
51632 $ofs = ($numMatches + $ofs) % $numMatches;
51633 }
51634 } elseif (ord($c) < 32) {
51635 if ("\t" === $c || "\n" === $c) {
51636 if ($numMatches > 0 && -1 !== $ofs) {
51637 $ret = $matches[$ofs];
51638
51639  $output->write(substr($ret, $i));
51640 $i = strlen($ret);
51641 }
51642
51643 if ("\n" === $c) {
51644 $output->write($c);
51645 break;
51646 }
51647
51648 $numMatches = 0;
51649 }
51650
51651 continue;
51652 } else {
51653 $output->write($c);
51654 $ret .= $c;
51655 ++$i;
51656
51657 $numMatches = 0;
51658 $ofs = 0;
51659
51660 foreach ($autocomplete as $value) {
51661
51662  if (0 === strpos($value, $ret) && $i !== strlen($value)) {
51663 $matches[$numMatches++] = $value;
51664 }
51665 }
51666 }
51667
51668
51669  $output->write("\033[K");
51670
51671 if ($numMatches > 0 && -1 !== $ofs) {
51672
51673  $output->write("\0337");
51674
51675  $output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
51676
51677  $output->write("\0338");
51678 }
51679 }
51680
51681
51682  shell_exec(sprintf('stty %s', $sttyMode));
51683 }
51684
51685 return strlen($ret) > 0 ? $ret : $default;
51686 }
51687
51688
51689
51690
51691
51692
51693
51694
51695
51696
51697
51698
51699 public function askConfirmation(OutputInterface $output, $question, $default = true)
51700 {
51701 $answer = 'z';
51702 while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) {
51703 $answer = $this->ask($output, $question);
51704 }
51705
51706 if (false === $default) {
51707 return $answer && 'y' == strtolower($answer[0]);
51708 }
51709
51710 return !$answer || 'y' == strtolower($answer[0]);
51711 }
51712
51713
51714
51715
51716
51717
51718
51719
51720
51721
51722
51723
51724 public function askHiddenResponse(OutputInterface $output, $question, $fallback = true)
51725 {
51726 if ($output instanceof ConsoleOutputInterface) {
51727 $output = $output->getErrorOutput();
51728 }
51729
51730 if ('\\' === DIRECTORY_SEPARATOR) {
51731 $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
51732
51733
51734  if ('phar:' === substr(__FILE__, 0, 5)) {
51735 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
51736 copy($exe, $tmpExe);
51737 $exe = $tmpExe;
51738 }
51739
51740 $output->write($question);
51741 $value = rtrim(shell_exec($exe));
51742 $output->writeln('');
51743
51744 if (isset($tmpExe)) {
51745 unlink($tmpExe);
51746 }
51747
51748 return $value;
51749 }
51750
51751 if ($this->hasSttyAvailable()) {
51752 $output->write($question);
51753
51754 $sttyMode = shell_exec('stty -g');
51755
51756 shell_exec('stty -echo');
51757 $value = fgets($this->inputStream ?: STDIN, 4096);
51758 shell_exec(sprintf('stty %s', $sttyMode));
51759
51760 if (false === $value) {
51761 throw new RuntimeException('Aborted');
51762 }
51763
51764 $value = trim($value);
51765 $output->writeln('');
51766
51767 return $value;
51768 }
51769
51770 if (false !== $shell = $this->getShell()) {
51771 $output->write($question);
51772 $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword';
51773 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
51774 $value = rtrim(shell_exec($command));
51775 $output->writeln('');
51776
51777 return $value;
51778 }
51779
51780 if ($fallback) {
51781 return $this->ask($output, $question);
51782 }
51783
51784 throw new RuntimeException('Unable to hide the response');
51785 }
51786
51787
51788
51789
51790
51791
51792
51793
51794
51795
51796
51797
51798
51799
51800
51801
51802
51803
51804
51805 public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null, array $autocomplete = null)
51806 {
51807 $that = $this;
51808
51809 $interviewer = function () use ($output, $question, $default, $autocomplete, $that) {
51810 return $that->ask($output, $question, $default, $autocomplete);
51811 };
51812
51813 return $this->validateAttempts($interviewer, $output, $validator, $attempts);
51814 }
51815
51816
51817
51818
51819
51820
51821
51822
51823
51824
51825
51826
51827
51828
51829
51830
51831
51832
51833
51834 public function askHiddenResponseAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $fallback = true)
51835 {
51836 $that = $this;
51837
51838 $interviewer = function () use ($output, $question, $fallback, $that) {
51839 return $that->askHiddenResponse($output, $question, $fallback);
51840 };
51841
51842 return $this->validateAttempts($interviewer, $output, $validator, $attempts);
51843 }
51844
51845
51846
51847
51848
51849
51850
51851
51852 public function setInputStream($stream)
51853 {
51854 $this->inputStream = $stream;
51855 }
51856
51857
51858
51859
51860
51861
51862 public function getInputStream()
51863 {
51864 return $this->inputStream;
51865 }
51866
51867
51868
51869
51870 public function getName()
51871 {
51872 return 'dialog';
51873 }
51874
51875
51876
51877
51878
51879
51880 private function getShell()
51881 {
51882 if (null !== self::$shell) {
51883 return self::$shell;
51884 }
51885
51886 self::$shell = false;
51887
51888 if (file_exists('/usr/bin/env')) {
51889
51890  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
51891 foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
51892 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
51893 self::$shell = $sh;
51894 break;
51895 }
51896 }
51897 }
51898
51899 return self::$shell;
51900 }
51901
51902 private function hasSttyAvailable()
51903 {
51904 if (null !== self::$stty) {
51905 return self::$stty;
51906 }
51907
51908 exec('stty 2>&1', $output, $exitcode);
51909
51910 return self::$stty = $exitcode === 0;
51911 }
51912
51913
51914
51915
51916
51917
51918
51919
51920
51921
51922
51923
51924
51925 private function validateAttempts($interviewer, OutputInterface $output, $validator, $attempts)
51926 {
51927 if ($output instanceof ConsoleOutputInterface) {
51928 $output = $output->getErrorOutput();
51929 }
51930
51931 $e = null;
51932 while (false === $attempts || $attempts--) {
51933 if (null !== $e) {
51934 $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($e->getMessage(), 'error'));
51935 }
51936
51937 try {
51938 return call_user_func($validator, $interviewer());
51939 } catch (\Exception $e) {
51940 }
51941 }
51942
51943 throw $e;
51944 }
51945 }
51946 <?php
51947
51948
51949
51950
51951
51952
51953
51954
51955
51956
51957 namespace Symfony\Component\Console\Helper;
51958
51959 use Symfony\Component\Console\Formatter\OutputFormatter;
51960
51961
51962
51963
51964
51965
51966 class FormatterHelper extends Helper
51967 {
51968
51969
51970
51971
51972
51973
51974
51975
51976
51977 public function formatSection($section, $message, $style = 'info')
51978 {
51979 return sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message);
51980 }
51981
51982
51983
51984
51985
51986
51987
51988
51989
51990
51991 public function formatBlock($messages, $style, $large = false)
51992 {
51993 if (!is_array($messages)) {
51994 $messages = array($messages);
51995 }
51996
51997 $len = 0;
51998 $lines = array();
51999 foreach ($messages as $message) {
52000 $message = OutputFormatter::escape($message);
52001 $lines[] = sprintf($large ? '  %s  ' : ' %s ', $message);
52002 $len = max($this->strlen($message) + ($large ? 4 : 2), $len);
52003 }
52004
52005 $messages = $large ? array(str_repeat(' ', $len)) : array();
52006 for ($i = 0; isset($lines[$i]); ++$i) {
52007 $messages[] = $lines[$i].str_repeat(' ', $len - $this->strlen($lines[$i]));
52008 }
52009 if ($large) {
52010 $messages[] = str_repeat(' ', $len);
52011 }
52012
52013 for ($i = 0; isset($messages[$i]); ++$i) {
52014 $messages[$i] = sprintf('<%s>%s</%s>', $style, $messages[$i], $style);
52015 }
52016
52017 return implode("\n", $messages);
52018 }
52019
52020
52021
52022
52023 public function getName()
52024 {
52025 return 'formatter';
52026 }
52027 }
52028 <?php
52029
52030
52031
52032
52033
52034
52035
52036
52037
52038
52039 namespace Symfony\Component\Console\Helper;
52040
52041 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
52042
52043
52044
52045
52046
52047
52048 abstract class Helper implements HelperInterface
52049 {
52050 protected $helperSet = null;
52051
52052
52053
52054
52055
52056
52057 public function setHelperSet(HelperSet $helperSet = null)
52058 {
52059 $this->helperSet = $helperSet;
52060 }
52061
52062
52063
52064
52065
52066
52067 public function getHelperSet()
52068 {
52069 return $this->helperSet;
52070 }
52071
52072
52073
52074
52075
52076
52077
52078
52079 public static function strlen($string)
52080 {
52081 if (false === $encoding = mb_detect_encoding($string, null, true)) {
52082 return strlen($string);
52083 }
52084
52085 return mb_strwidth($string, $encoding);
52086 }
52087
52088 public static function formatTime($secs)
52089 {
52090 static $timeFormats = array(
52091 array(0, '< 1 sec'),
52092 array(1, '1 sec'),
52093 array(2, 'secs', 1),
52094 array(60, '1 min'),
52095 array(120, 'mins', 60),
52096 array(3600, '1 hr'),
52097 array(7200, 'hrs', 3600),
52098 array(86400, '1 day'),
52099 array(172800, 'days', 86400),
52100 );
52101
52102 foreach ($timeFormats as $index => $format) {
52103 if ($secs >= $format[0]) {
52104 if ((isset($timeFormats[$index + 1]) && $secs < $timeFormats[$index + 1][0])
52105 || $index == count($timeFormats) - 1
52106 ) {
52107 if (2 == count($format)) {
52108 return $format[1];
52109 }
52110
52111 return floor($secs / $format[2]).' '.$format[1];
52112 }
52113 }
52114 }
52115 }
52116
52117 public static function formatMemory($memory)
52118 {
52119 if ($memory >= 1024 * 1024 * 1024) {
52120 return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024);
52121 }
52122
52123 if ($memory >= 1024 * 1024) {
52124 return sprintf('%.1f MiB', $memory / 1024 / 1024);
52125 }
52126
52127 if ($memory >= 1024) {
52128 return sprintf('%d KiB', $memory / 1024);
52129 }
52130
52131 return sprintf('%d B', $memory);
52132 }
52133
52134 public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string)
52135 {
52136 return self::strlen(self::removeDecoration($formatter, $string));
52137 }
52138
52139 public static function removeDecoration(OutputFormatterInterface $formatter, $string)
52140 {
52141 $isDecorated = $formatter->isDecorated();
52142 $formatter->setDecorated(false);
52143
52144  $string = $formatter->format($string);
52145
52146  $string = preg_replace("/\033\[[^m]*m/", '', $string);
52147 $formatter->setDecorated($isDecorated);
52148
52149 return $string;
52150 }
52151 }
52152 <?php
52153
52154
52155
52156
52157
52158
52159
52160
52161
52162
52163 namespace Symfony\Component\Console\Helper;
52164
52165
52166
52167
52168
52169
52170 interface HelperInterface
52171 {
52172
52173
52174
52175
52176
52177 public function setHelperSet(HelperSet $helperSet = null);
52178
52179
52180
52181
52182
52183
52184 public function getHelperSet();
52185
52186
52187
52188
52189
52190
52191 public function getName();
52192 }
52193 <?php
52194
52195
52196
52197
52198
52199
52200
52201
52202
52203
52204 namespace Symfony\Component\Console\Helper;
52205
52206 use Symfony\Component\Console\Command\Command;
52207 use Symfony\Component\Console\Exception\InvalidArgumentException;
52208
52209
52210
52211
52212
52213
52214 class HelperSet implements \IteratorAggregate
52215 {
52216
52217
52218
52219 private $helpers = array();
52220 private $command;
52221
52222
52223
52224
52225
52226
52227 public function __construct(array $helpers = array())
52228 {
52229 foreach ($helpers as $alias => $helper) {
52230 $this->set($helper, is_int($alias) ? null : $alias);
52231 }
52232 }
52233
52234
52235
52236
52237
52238
52239
52240 public function set(HelperInterface $helper, $alias = null)
52241 {
52242 $this->helpers[$helper->getName()] = $helper;
52243 if (null !== $alias) {
52244 $this->helpers[$alias] = $helper;
52245 }
52246
52247 $helper->setHelperSet($this);
52248 }
52249
52250
52251
52252
52253
52254
52255
52256
52257 public function has($name)
52258 {
52259 return isset($this->helpers[$name]);
52260 }
52261
52262
52263
52264
52265
52266
52267
52268
52269
52270
52271 public function get($name)
52272 {
52273 if (!$this->has($name)) {
52274 throw new InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
52275 }
52276
52277 if ('dialog' === $name && $this->helpers[$name] instanceof DialogHelper) {
52278 @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);
52279 } elseif ('progress' === $name && $this->helpers[$name] instanceof ProgressHelper) {
52280 @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);
52281 } elseif ('table' === $name && $this->helpers[$name] instanceof TableHelper) {
52282 @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);
52283 }
52284
52285 return $this->helpers[$name];
52286 }
52287
52288
52289
52290
52291
52292
52293 public function setCommand(Command $command = null)
52294 {
52295 $this->command = $command;
52296 }
52297
52298
52299
52300
52301
52302
52303 public function getCommand()
52304 {
52305 return $this->command;
52306 }
52307
52308
52309
52310
52311 public function getIterator()
52312 {
52313 return new \ArrayIterator($this->helpers);
52314 }
52315 }
52316 <?php
52317
52318
52319
52320
52321
52322
52323
52324
52325
52326
52327 namespace Symfony\Component\Console\Helper;
52328
52329 use Symfony\Component\Console\Input\InputInterface;
52330 use Symfony\Component\Console\Input\InputAwareInterface;
52331
52332
52333
52334
52335
52336
52337 abstract class InputAwareHelper extends Helper implements InputAwareInterface
52338 {
52339 protected $input;
52340
52341
52342
52343
52344 public function setInput(InputInterface $input)
52345 {
52346 $this->input = $input;
52347 }
52348 }
52349 <?php
52350
52351
52352
52353
52354
52355
52356
52357
52358
52359
52360 namespace Symfony\Component\Console\Helper;
52361
52362 use Symfony\Component\Console\Output\ConsoleOutputInterface;
52363 use Symfony\Component\Console\Output\OutputInterface;
52364 use Symfony\Component\Process\Exception\ProcessFailedException;
52365 use Symfony\Component\Process\Process;
52366 use Symfony\Component\Process\ProcessBuilder;
52367
52368
52369
52370
52371
52372
52373 class ProcessHelper extends Helper
52374 {
52375
52376
52377
52378
52379
52380
52381
52382
52383
52384
52385
52386
52387 public function run(OutputInterface $output, $cmd, $error = null, $callback = null, $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE)
52388 {
52389 if ($output instanceof ConsoleOutputInterface) {
52390 $output = $output->getErrorOutput();
52391 }
52392
52393 $formatter = $this->getHelperSet()->get('debug_formatter');
52394
52395 if (is_array($cmd)) {
52396 $process = ProcessBuilder::create($cmd)->getProcess();
52397 } elseif ($cmd instanceof Process) {
52398 $process = $cmd;
52399 } else {
52400 $process = new Process($cmd);
52401 }
52402
52403 if ($verbosity <= $output->getVerbosity()) {
52404 $output->write($formatter->start(spl_object_hash($process), $this->escapeString($process->getCommandLine())));
52405 }
52406
52407 if ($output->isDebug()) {
52408 $callback = $this->wrapCallback($output, $process, $callback);
52409 }
52410
52411 $process->run($callback);
52412
52413 if ($verbosity <= $output->getVerbosity()) {
52414 $message = $process->isSuccessful() ? 'Command ran successfully' : sprintf('%s Command did not run successfully', $process->getExitCode());
52415 $output->write($formatter->stop(spl_object_hash($process), $message, $process->isSuccessful()));
52416 }
52417
52418 if (!$process->isSuccessful() && null !== $error) {
52419 $output->writeln(sprintf('<error>%s</error>', $this->escapeString($error)));
52420 }
52421
52422 return $process;
52423 }
52424
52425
52426
52427
52428
52429
52430
52431
52432
52433
52434
52435
52436
52437
52438
52439
52440
52441
52442
52443 public function mustRun(OutputInterface $output, $cmd, $error = null, $callback = null)
52444 {
52445 $process = $this->run($output, $cmd, $error, $callback);
52446
52447 if (!$process->isSuccessful()) {
52448 throw new ProcessFailedException($process);
52449 }
52450
52451 return $process;
52452 }
52453
52454
52455
52456
52457
52458
52459
52460
52461
52462
52463 public function wrapCallback(OutputInterface $output, Process $process, $callback = null)
52464 {
52465 if ($output instanceof ConsoleOutputInterface) {
52466 $output = $output->getErrorOutput();
52467 }
52468
52469 $formatter = $this->getHelperSet()->get('debug_formatter');
52470
52471 $that = $this;
52472
52473 return function ($type, $buffer) use ($output, $process, $callback, $formatter, $that) {
52474 $output->write($formatter->progress(spl_object_hash($process), $that->escapeString($buffer), Process::ERR === $type));
52475
52476 if (null !== $callback) {
52477 call_user_func($callback, $type, $buffer);
52478 }
52479 };
52480 }
52481
52482
52483
52484
52485
52486
52487 public function escapeString($str)
52488 {
52489 return str_replace('<', '\\<', $str);
52490 }
52491
52492
52493
52494
52495 public function getName()
52496 {
52497 return 'process';
52498 }
52499 }
52500 <?php
52501
52502
52503
52504
52505
52506
52507
52508
52509
52510
52511 namespace Symfony\Component\Console\Helper;
52512
52513 use Symfony\Component\Console\Output\ConsoleOutputInterface;
52514 use Symfony\Component\Console\Output\OutputInterface;
52515 use Symfony\Component\Console\Exception\LogicException;
52516
52517
52518
52519
52520
52521
52522
52523 class ProgressBar
52524 {
52525
52526  private $barWidth = 28;
52527 private $barChar;
52528 private $emptyBarChar = '-';
52529 private $progressChar = '>';
52530 private $format;
52531 private $internalFormat;
52532 private $redrawFreq = 1;
52533
52534
52535
52536
52537 private $output;
52538 private $step = 0;
52539 private $max;
52540 private $startTime;
52541 private $stepWidth;
52542 private $percent = 0.0;
52543 private $formatLineCount;
52544 private $messages = array();
52545 private $overwrite = true;
52546 private $firstRun = true;
52547
52548 private static $formatters;
52549 private static $formats;
52550
52551
52552
52553
52554
52555
52556
52557 public function __construct(OutputInterface $output, $max = 0)
52558 {
52559 if ($output instanceof ConsoleOutputInterface) {
52560 $output = $output->getErrorOutput();
52561 }
52562
52563 $this->output = $output;
52564 $this->setMaxSteps($max);
52565
52566 if (!$this->output->isDecorated()) {
52567
52568  $this->overwrite = false;
52569
52570
52571  $this->setRedrawFrequency($max / 10);
52572 }
52573
52574 $this->startTime = time();
52575 }
52576
52577
52578
52579
52580
52581
52582
52583
52584
52585 public static function setPlaceholderFormatterDefinition($name, $callable)
52586 {
52587 if (!self::$formatters) {
52588 self::$formatters = self::initPlaceholderFormatters();
52589 }
52590
52591 self::$formatters[$name] = $callable;
52592 }
52593
52594
52595
52596
52597
52598
52599
52600
52601 public static function getPlaceholderFormatterDefinition($name)
52602 {
52603 if (!self::$formatters) {
52604 self::$formatters = self::initPlaceholderFormatters();
52605 }
52606
52607 return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
52608 }
52609
52610
52611
52612
52613
52614
52615
52616
52617
52618 public static function setFormatDefinition($name, $format)
52619 {
52620 if (!self::$formats) {
52621 self::$formats = self::initFormats();
52622 }
52623
52624 self::$formats[$name] = $format;
52625 }
52626
52627
52628
52629
52630
52631
52632
52633
52634 public static function getFormatDefinition($name)
52635 {
52636 if (!self::$formats) {
52637 self::$formats = self::initFormats();
52638 }
52639
52640 return isset(self::$formats[$name]) ? self::$formats[$name] : null;
52641 }
52642
52643
52644
52645
52646
52647
52648
52649
52650
52651
52652
52653 public function setMessage($message, $name = 'message')
52654 {
52655 $this->messages[$name] = $message;
52656 }
52657
52658 public function getMessage($name = 'message')
52659 {
52660 return $this->messages[$name];
52661 }
52662
52663
52664
52665
52666
52667
52668 public function getStartTime()
52669 {
52670 return $this->startTime;
52671 }
52672
52673
52674
52675
52676
52677
52678 public function getMaxSteps()
52679 {
52680 return $this->max;
52681 }
52682
52683
52684
52685
52686
52687
52688
52689
52690 public function getStep()
52691 {
52692 @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);
52693
52694 return $this->getProgress();
52695 }
52696
52697
52698
52699
52700
52701
52702 public function getProgress()
52703 {
52704 return $this->step;
52705 }
52706
52707
52708
52709
52710
52711
52712
52713
52714 public function getStepWidth()
52715 {
52716 return $this->stepWidth;
52717 }
52718
52719
52720
52721
52722
52723
52724 public function getProgressPercent()
52725 {
52726 return $this->percent;
52727 }
52728
52729
52730
52731
52732
52733
52734 public function setBarWidth($size)
52735 {
52736 $this->barWidth = (int) $size;
52737 }
52738
52739
52740
52741
52742
52743
52744 public function getBarWidth()
52745 {
52746 return $this->barWidth;
52747 }
52748
52749
52750
52751
52752
52753
52754 public function setBarCharacter($char)
52755 {
52756 $this->barChar = $char;
52757 }
52758
52759
52760
52761
52762
52763
52764 public function getBarCharacter()
52765 {
52766 if (null === $this->barChar) {
52767 return $this->max ? '=' : $this->emptyBarChar;
52768 }
52769
52770 return $this->barChar;
52771 }
52772
52773
52774
52775
52776
52777
52778 public function setEmptyBarCharacter($char)
52779 {
52780 $this->emptyBarChar = $char;
52781 }
52782
52783
52784
52785
52786
52787
52788 public function getEmptyBarCharacter()
52789 {
52790 return $this->emptyBarChar;
52791 }
52792
52793
52794
52795
52796
52797
52798 public function setProgressCharacter($char)
52799 {
52800 $this->progressChar = $char;
52801 }
52802
52803
52804
52805
52806
52807
52808 public function getProgressCharacter()
52809 {
52810 return $this->progressChar;
52811 }
52812
52813
52814
52815
52816
52817
52818 public function setFormat($format)
52819 {
52820 $this->format = null;
52821 $this->internalFormat = $format;
52822 }
52823
52824
52825
52826
52827
52828
52829 public function setRedrawFrequency($freq)
52830 {
52831 $this->redrawFreq = max((int) $freq, 1);
52832 }
52833
52834
52835
52836
52837
52838
52839 public function start($max = null)
52840 {
52841 $this->startTime = time();
52842 $this->step = 0;
52843 $this->percent = 0.0;
52844
52845 if (null !== $max) {
52846 $this->setMaxSteps($max);
52847 }
52848
52849 $this->display();
52850 }
52851
52852
52853
52854
52855
52856
52857
52858
52859 public function advance($step = 1)
52860 {
52861 $this->setProgress($this->step + $step);
52862 }
52863
52864
52865
52866
52867
52868
52869
52870
52871
52872
52873 public function setCurrent($step)
52874 {
52875 @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);
52876
52877 $this->setProgress($step);
52878 }
52879
52880
52881
52882
52883
52884
52885 public function setOverwrite($overwrite)
52886 {
52887 $this->overwrite = (bool) $overwrite;
52888 }
52889
52890
52891
52892
52893
52894
52895
52896
52897 public function setProgress($step)
52898 {
52899 $step = (int) $step;
52900 if ($step < $this->step) {
52901 throw new LogicException('You can\'t regress the progress bar.');
52902 }
52903
52904 if ($this->max && $step > $this->max) {
52905 $this->max = $step;
52906 }
52907
52908 $prevPeriod = (int) ($this->step / $this->redrawFreq);
52909 $currPeriod = (int) ($step / $this->redrawFreq);
52910 $this->step = $step;
52911 $this->percent = $this->max ? (float) $this->step / $this->max : 0;
52912 if ($prevPeriod !== $currPeriod || $this->max === $step) {
52913 $this->display();
52914 }
52915 }
52916
52917
52918
52919
52920 public function finish()
52921 {
52922 if (!$this->max) {
52923 $this->max = $this->step;
52924 }
52925
52926 if ($this->step === $this->max && !$this->overwrite) {
52927
52928  return;
52929 }
52930
52931 $this->setProgress($this->max);
52932 }
52933
52934
52935
52936
52937 public function display()
52938 {
52939 if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
52940 return;
52941 }
52942
52943 if (null === $this->format) {
52944 $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
52945 }
52946
52947
52948  $self = $this;
52949 $output = $this->output;
52950 $messages = $this->messages;
52951 $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self, $output, $messages) {
52952 if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
52953 $text = call_user_func($formatter, $self, $output);
52954 } elseif (isset($messages[$matches[1]])) {
52955 $text = $messages[$matches[1]];
52956 } else {
52957 return $matches[0];
52958 }
52959
52960 if (isset($matches[2])) {
52961 $text = sprintf('%'.$matches[2], $text);
52962 }
52963
52964 return $text;
52965 }, $this->format));
52966 }
52967
52968
52969
52970
52971
52972
52973
52974
52975 public function clear()
52976 {
52977 if (!$this->overwrite) {
52978 return;
52979 }
52980
52981 if (null === $this->format) {
52982 $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
52983 }
52984
52985 $this->overwrite('');
52986 }
52987
52988
52989
52990
52991
52992
52993 private function setRealFormat($format)
52994 {
52995
52996  if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) {
52997 $this->format = self::getFormatDefinition($format.'_nomax');
52998 } elseif (null !== self::getFormatDefinition($format)) {
52999 $this->format = self::getFormatDefinition($format);
53000 } else {
53001 $this->format = $format;
53002 }
53003
53004 $this->formatLineCount = substr_count($this->format, "\n");
53005 }
53006
53007
53008
53009
53010
53011
53012 private function setMaxSteps($max)
53013 {
53014 $this->max = max(0, (int) $max);
53015 $this->stepWidth = $this->max ? Helper::strlen($this->max) : 4;
53016 }
53017
53018
53019
53020
53021
53022
53023 private function overwrite($message)
53024 {
53025 if ($this->overwrite) {
53026 if (!$this->firstRun) {
53027
53028  $this->output->write("\x0D");
53029
53030
53031  $this->output->write("\x1B[2K");
53032
53033
53034  if ($this->formatLineCount > 0) {
53035 $this->output->write(str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount));
53036 }
53037 }
53038 } elseif ($this->step > 0) {
53039 $this->output->writeln('');
53040 }
53041
53042 $this->firstRun = false;
53043
53044 $this->output->write($message);
53045 }
53046
53047 private function determineBestFormat()
53048 {
53049 switch ($this->output->getVerbosity()) {
53050
53051  case OutputInterface::VERBOSITY_VERBOSE:
53052 return $this->max ? 'verbose' : 'verbose_nomax';
53053 case OutputInterface::VERBOSITY_VERY_VERBOSE:
53054 return $this->max ? 'very_verbose' : 'very_verbose_nomax';
53055 case OutputInterface::VERBOSITY_DEBUG:
53056 return $this->max ? 'debug' : 'debug_nomax';
53057 default:
53058 return $this->max ? 'normal' : 'normal_nomax';
53059 }
53060 }
53061
53062 private static function initPlaceholderFormatters()
53063 {
53064 return array(
53065 'bar' => function (ProgressBar $bar, OutputInterface $output) {
53066 $completeBars = floor($bar->getMaxSteps() > 0 ? $bar->getProgressPercent() * $bar->getBarWidth() : $bar->getProgress() % $bar->getBarWidth());
53067 $display = str_repeat($bar->getBarCharacter(), $completeBars);
53068 if ($completeBars < $bar->getBarWidth()) {
53069 $emptyBars = $bar->getBarWidth() - $completeBars - Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter());
53070 $display .= $bar->getProgressCharacter().str_repeat($bar->getEmptyBarCharacter(), $emptyBars);
53071 }
53072
53073 return $display;
53074 },
53075 'elapsed' => function (ProgressBar $bar) {
53076 return Helper::formatTime(time() - $bar->getStartTime());
53077 },
53078 'remaining' => function (ProgressBar $bar) {
53079 if (!$bar->getMaxSteps()) {
53080 throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.');
53081 }
53082
53083 if (!$bar->getProgress()) {
53084 $remaining = 0;
53085 } else {
53086 $remaining = round((time() - $bar->getStartTime()) / $bar->getProgress() * ($bar->getMaxSteps() - $bar->getProgress()));
53087 }
53088
53089 return Helper::formatTime($remaining);
53090 },
53091 'estimated' => function (ProgressBar $bar) {
53092 if (!$bar->getMaxSteps()) {
53093 throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.');
53094 }
53095
53096 if (!$bar->getProgress()) {
53097 $estimated = 0;
53098 } else {
53099 $estimated = round((time() - $bar->getStartTime()) / $bar->getProgress() * $bar->getMaxSteps());
53100 }
53101
53102 return Helper::formatTime($estimated);
53103 },
53104 'memory' => function (ProgressBar $bar) {
53105 return Helper::formatMemory(memory_get_usage(true));
53106 },
53107 'current' => function (ProgressBar $bar) {
53108 return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', STR_PAD_LEFT);
53109 },
53110 'max' => function (ProgressBar $bar) {
53111 return $bar->getMaxSteps();
53112 },
53113 'percent' => function (ProgressBar $bar) {
53114 return floor($bar->getProgressPercent() * 100);
53115 },
53116 );
53117 }
53118
53119 private static function initFormats()
53120 {
53121 return array(
53122 'normal' => ' %current%/%max% [%bar%] %percent:3s%%',
53123 'normal_nomax' => ' %current% [%bar%]',
53124
53125 'verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%',
53126 'verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
53127
53128 'very_verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%',
53129 'very_verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
53130
53131 'debug' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%',
53132 'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%',
53133 );
53134 }
53135 }
53136 <?php
53137
53138
53139
53140
53141
53142
53143
53144
53145
53146
53147 namespace Symfony\Component\Console\Helper;
53148
53149 use Symfony\Component\Console\Output\NullOutput;
53150 use Symfony\Component\Console\Output\ConsoleOutputInterface;
53151 use Symfony\Component\Console\Output\OutputInterface;
53152 use Symfony\Component\Console\Exception\LogicException;
53153
53154
53155
53156
53157
53158
53159
53160
53161
53162
53163 class ProgressHelper extends Helper
53164 {
53165 const FORMAT_QUIET = ' %percent%%';
53166 const FORMAT_NORMAL = ' %current%/%max% [%bar%] %percent%%';
53167 const FORMAT_VERBOSE = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%';
53168 const FORMAT_QUIET_NOMAX = ' %current%';
53169 const FORMAT_NORMAL_NOMAX = ' %current% [%bar%]';
53170 const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%';
53171
53172
53173  private $barWidth = 28;
53174 private $barChar = '=';
53175 private $emptyBarChar = '-';
53176 private $progressChar = '>';
53177 private $format = null;
53178 private $redrawFreq = 1;
53179
53180 private $lastMessagesLength;
53181 private $barCharOriginal;
53182
53183
53184
53185
53186 private $output;
53187
53188
53189
53190
53191
53192
53193 private $current;
53194
53195
53196
53197
53198
53199
53200 private $max;
53201
53202
53203
53204
53205
53206
53207 private $startTime;
53208
53209
53210
53211
53212
53213
53214 private $defaultFormatVars = array(
53215 'current',
53216 'max',
53217 'bar',
53218 'percent',
53219 'elapsed',
53220 );
53221
53222
53223
53224
53225
53226
53227 private $formatVars;
53228
53229
53230
53231
53232
53233
53234 private $widths = array(
53235 'current' => 4,
53236 'max' => 4,
53237 'percent' => 3,
53238 'elapsed' => 6,
53239 );
53240
53241
53242
53243
53244
53245
53246 private $timeFormats = array(
53247 array(0, '???'),
53248 array(2, '1 sec'),
53249 array(59, 'secs', 1),
53250 array(60, '1 min'),
53251 array(3600, 'mins', 60),
53252 array(5400, '1 hr'),
53253 array(86400, 'hrs', 3600),
53254 array(129600, '1 day'),
53255 array(604800, 'days', 86400),
53256 );
53257
53258 public function __construct($triggerDeprecationError = true)
53259 {
53260 if ($triggerDeprecationError) {
53261 @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);
53262 }
53263 }
53264
53265
53266
53267
53268
53269
53270 public function setBarWidth($size)
53271 {
53272 $this->barWidth = (int) $size;
53273 }
53274
53275
53276
53277
53278
53279
53280 public function setBarCharacter($char)
53281 {
53282 $this->barChar = $char;
53283 }
53284
53285
53286
53287
53288
53289
53290 public function setEmptyBarCharacter($char)
53291 {
53292 $this->emptyBarChar = $char;
53293 }
53294
53295
53296
53297
53298
53299
53300 public function setProgressCharacter($char)
53301 {
53302 $this->progressChar = $char;
53303 }
53304
53305
53306
53307
53308
53309
53310 public function setFormat($format)
53311 {
53312 $this->format = $format;
53313 }
53314
53315
53316
53317
53318
53319
53320 public function setRedrawFrequency($freq)
53321 {
53322 $this->redrawFreq = (int) $freq;
53323 }
53324
53325
53326
53327
53328
53329
53330
53331 public function start(OutputInterface $output, $max = null)
53332 {
53333 if ($output instanceof ConsoleOutputInterface) {
53334 $output = $output->getErrorOutput();
53335 }
53336
53337 $this->startTime = time();
53338 $this->current = 0;
53339 $this->max = (int) $max;
53340
53341
53342  $this->output = $output->isDecorated() ? $output : new NullOutput();
53343 $this->lastMessagesLength = 0;
53344 $this->barCharOriginal = '';
53345
53346 if (null === $this->format) {
53347 switch ($output->getVerbosity()) {
53348 case OutputInterface::VERBOSITY_QUIET:
53349 $this->format = self::FORMAT_QUIET_NOMAX;
53350 if ($this->max > 0) {
53351 $this->format = self::FORMAT_QUIET;
53352 }
53353 break;
53354 case OutputInterface::VERBOSITY_VERBOSE:
53355 case OutputInterface::VERBOSITY_VERY_VERBOSE:
53356 case OutputInterface::VERBOSITY_DEBUG:
53357 $this->format = self::FORMAT_VERBOSE_NOMAX;
53358 if ($this->max > 0) {
53359 $this->format = self::FORMAT_VERBOSE;
53360 }
53361 break;
53362 default:
53363 $this->format = self::FORMAT_NORMAL_NOMAX;
53364 if ($this->max > 0) {
53365 $this->format = self::FORMAT_NORMAL;
53366 }
53367 break;
53368 }
53369 }
53370
53371 $this->initialize();
53372 }
53373
53374
53375
53376
53377
53378
53379
53380
53381
53382 public function advance($step = 1, $redraw = false)
53383 {
53384 $this->setCurrent($this->current + $step, $redraw);
53385 }
53386
53387
53388
53389
53390
53391
53392
53393
53394
53395 public function setCurrent($current, $redraw = false)
53396 {
53397 if (null === $this->startTime) {
53398 throw new LogicException('You must start the progress bar before calling setCurrent().');
53399 }
53400
53401 $current = (int) $current;
53402
53403 if ($current < $this->current) {
53404 throw new LogicException('You can\'t regress the progress bar');
53405 }
53406
53407 if (0 === $this->current) {
53408 $redraw = true;
53409 }
53410
53411 $prevPeriod = (int) ($this->current / $this->redrawFreq);
53412
53413 $this->current = $current;
53414
53415 $currPeriod = (int) ($this->current / $this->redrawFreq);
53416 if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) {
53417 $this->display();
53418 }
53419 }
53420
53421
53422
53423
53424
53425
53426
53427
53428 public function display($finish = false)
53429 {
53430 if (null === $this->startTime) {
53431 throw new LogicException('You must start the progress bar before calling display().');
53432 }
53433
53434 $message = $this->format;
53435 foreach ($this->generate($finish) as $name => $value) {
53436 $message = str_replace("%{$name}%", $value, $message);
53437 }
53438 $this->overwrite($this->output, $message);
53439 }
53440
53441
53442
53443
53444
53445
53446
53447
53448 public function clear()
53449 {
53450 $this->overwrite($this->output, '');
53451 }
53452
53453
53454
53455
53456 public function finish()
53457 {
53458 if (null === $this->startTime) {
53459 throw new LogicException('You must start the progress bar before calling finish().');
53460 }
53461
53462 if (null !== $this->startTime) {
53463 if (!$this->max) {
53464 $this->barChar = $this->barCharOriginal;
53465 $this->display(true);
53466 }
53467 $this->startTime = null;
53468 $this->output->writeln('');
53469 $this->output = null;
53470 }
53471 }
53472
53473
53474
53475
53476 private function initialize()
53477 {
53478 $this->formatVars = array();
53479 foreach ($this->defaultFormatVars as $var) {
53480 if (false !== strpos($this->format, "%{$var}%")) {
53481 $this->formatVars[$var] = true;
53482 }
53483 }
53484
53485 if ($this->max > 0) {
53486 $this->widths['max'] = $this->strlen($this->max);
53487 $this->widths['current'] = $this->widths['max'];
53488 } else {
53489 $this->barCharOriginal = $this->barChar;
53490 $this->barChar = $this->emptyBarChar;
53491 }
53492 }
53493
53494
53495
53496
53497
53498
53499
53500
53501 private function generate($finish = false)
53502 {
53503 $vars = array();
53504 $percent = 0;
53505 if ($this->max > 0) {
53506 $percent = (float) $this->current / $this->max;
53507 }
53508
53509 if (isset($this->formatVars['bar'])) {
53510 if ($this->max > 0) {
53511 $completeBars = floor($percent * $this->barWidth);
53512 } else {
53513 if (!$finish) {
53514 $completeBars = floor($this->current % $this->barWidth);
53515 } else {
53516 $completeBars = $this->barWidth;
53517 }
53518 }
53519
53520 $emptyBars = $this->barWidth - $completeBars - $this->strlen($this->progressChar);
53521 $bar = str_repeat($this->barChar, $completeBars);
53522 if ($completeBars < $this->barWidth) {
53523 $bar .= $this->progressChar;
53524 $bar .= str_repeat($this->emptyBarChar, $emptyBars);
53525 }
53526
53527 $vars['bar'] = $bar;
53528 }
53529
53530 if (isset($this->formatVars['elapsed'])) {
53531 $elapsed = time() - $this->startTime;
53532 $vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT);
53533 }
53534
53535 if (isset($this->formatVars['current'])) {
53536 $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT);
53537 }
53538
53539 if (isset($this->formatVars['max'])) {
53540 $vars['max'] = $this->max;
53541 }
53542
53543 if (isset($this->formatVars['percent'])) {
53544 $vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT);
53545 }
53546
53547 return $vars;
53548 }
53549
53550
53551
53552
53553
53554
53555
53556
53557 private function humaneTime($secs)
53558 {
53559 $text = '';
53560 foreach ($this->timeFormats as $format) {
53561 if ($secs < $format[0]) {
53562 if (count($format) == 2) {
53563 $text = $format[1];
53564 break;
53565 } else {
53566 $text = ceil($secs / $format[2]).' '.$format[1];
53567 break;
53568 }
53569 }
53570 }
53571
53572 return $text;
53573 }
53574
53575
53576
53577
53578
53579
53580
53581 private function overwrite(OutputInterface $output, $message)
53582 {
53583 $length = $this->strlen($message);
53584
53585
53586  if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) {
53587 $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
53588 }
53589
53590
53591  $output->write("\x0D");
53592 $output->write($message);
53593
53594 $this->lastMessagesLength = $this->strlen($message);
53595 }
53596
53597
53598
53599
53600 public function getName()
53601 {
53602 return 'progress';
53603 }
53604 }
53605 <?php
53606
53607
53608
53609
53610
53611
53612
53613
53614
53615
53616 namespace Symfony\Component\Console\Helper;
53617
53618 use Symfony\Component\Console\Exception\InvalidArgumentException;
53619 use Symfony\Component\Console\Exception\LogicException;
53620 use Symfony\Component\Console\Output\OutputInterface;
53621
53622
53623
53624
53625 class ProgressIndicator
53626 {
53627 private $output;
53628 private $startTime;
53629 private $format;
53630 private $message;
53631 private $indicatorValues;
53632 private $indicatorCurrent;
53633 private $indicatorChangeInterval;
53634 private $indicatorUpdateTime;
53635 private $started = false;
53636
53637 private static $formatters;
53638 private static $formats;
53639
53640
53641
53642
53643
53644
53645
53646 public function __construct(OutputInterface $output, $format = null, $indicatorChangeInterval = 100, $indicatorValues = null)
53647 {
53648 $this->output = $output;
53649
53650 if (null === $format) {
53651 $format = $this->determineBestFormat();
53652 }
53653
53654 if (null === $indicatorValues) {
53655 $indicatorValues = array('-', '\\', '|', '/');
53656 }
53657
53658 $indicatorValues = array_values($indicatorValues);
53659
53660 if (2 > count($indicatorValues)) {
53661 throw new InvalidArgumentException('Must have at least 2 indicator value characters.');
53662 }
53663
53664 $this->format = self::getFormatDefinition($format);
53665 $this->indicatorChangeInterval = $indicatorChangeInterval;
53666 $this->indicatorValues = $indicatorValues;
53667 $this->startTime = time();
53668 }
53669
53670
53671
53672
53673
53674
53675 public function setMessage($message)
53676 {
53677 $this->message = $message;
53678
53679 $this->display();
53680 }
53681
53682
53683
53684
53685
53686
53687
53688
53689 public function getMessage()
53690 {
53691 return $this->message;
53692 }
53693
53694
53695
53696
53697
53698
53699
53700
53701 public function getStartTime()
53702 {
53703 return $this->startTime;
53704 }
53705
53706
53707
53708
53709
53710
53711
53712
53713 public function getCurrentValue()
53714 {
53715 return $this->indicatorValues[$this->indicatorCurrent % count($this->indicatorValues)];
53716 }
53717
53718
53719
53720
53721
53722
53723 public function start($message)
53724 {
53725 if ($this->started) {
53726 throw new LogicException('Progress indicator already started.');
53727 }
53728
53729 $this->message = $message;
53730 $this->started = true;
53731 $this->startTime = time();
53732 $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval;
53733 $this->indicatorCurrent = 0;
53734
53735 $this->display();
53736 }
53737
53738
53739
53740
53741 public function advance()
53742 {
53743 if (!$this->started) {
53744 throw new LogicException('Progress indicator has not yet been started.');
53745 }
53746
53747 if (!$this->output->isDecorated()) {
53748 return;
53749 }
53750
53751 $currentTime = $this->getCurrentTimeInMilliseconds();
53752
53753 if ($currentTime < $this->indicatorUpdateTime) {
53754 return;
53755 }
53756
53757 $this->indicatorUpdateTime = $currentTime + $this->indicatorChangeInterval;
53758 ++$this->indicatorCurrent;
53759
53760 $this->display();
53761 }
53762
53763
53764
53765
53766
53767
53768 public function finish($message)
53769 {
53770 if (!$this->started) {
53771 throw new LogicException('Progress indicator has not yet been started.');
53772 }
53773
53774 $this->message = $message;
53775 $this->display();
53776 $this->output->writeln('');
53777 $this->started = false;
53778 }
53779
53780
53781
53782
53783
53784
53785
53786
53787 public static function getFormatDefinition($name)
53788 {
53789 if (!self::$formats) {
53790 self::$formats = self::initFormats();
53791 }
53792
53793 return isset(self::$formats[$name]) ? self::$formats[$name] : null;
53794 }
53795
53796
53797
53798
53799
53800
53801
53802
53803
53804 public static function setPlaceholderFormatterDefinition($name, $callable)
53805 {
53806 if (!self::$formatters) {
53807 self::$formatters = self::initPlaceholderFormatters();
53808 }
53809
53810 self::$formatters[$name] = $callable;
53811 }
53812
53813
53814
53815
53816
53817
53818
53819
53820 public static function getPlaceholderFormatterDefinition($name)
53821 {
53822 if (!self::$formatters) {
53823 self::$formatters = self::initPlaceholderFormatters();
53824 }
53825
53826 return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
53827 }
53828
53829 private function display()
53830 {
53831 if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
53832 return;
53833 }
53834
53835 $self = $this;
53836
53837 $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self) {
53838 if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
53839 return call_user_func($formatter, $self);
53840 }
53841
53842 return $matches[0];
53843 }, $this->format));
53844 }
53845
53846 private function determineBestFormat()
53847 {
53848 switch ($this->output->getVerbosity()) {
53849
53850  case OutputInterface::VERBOSITY_VERBOSE:
53851 return $this->output->isDecorated() ? 'verbose' : 'verbose_no_ansi';
53852 case OutputInterface::VERBOSITY_VERY_VERBOSE:
53853 case OutputInterface::VERBOSITY_DEBUG:
53854 return $this->output->isDecorated() ? 'very_verbose' : 'very_verbose_no_ansi';
53855 default:
53856 return $this->output->isDecorated() ? 'normal' : 'normal_no_ansi';
53857 }
53858 }
53859
53860
53861
53862
53863
53864
53865 private function overwrite($message)
53866 {
53867 if ($this->output->isDecorated()) {
53868 $this->output->write("\x0D\x1B[2K");
53869 $this->output->write($message);
53870 } else {
53871 $this->output->writeln($message);
53872 }
53873 }
53874
53875 private function getCurrentTimeInMilliseconds()
53876 {
53877 return round(microtime(true) * 1000);
53878 }
53879
53880 private static function initPlaceholderFormatters()
53881 {
53882 return array(
53883 'indicator' => function (ProgressIndicator $indicator) {
53884 return $indicator->getCurrentValue();
53885 },
53886 'message' => function (ProgressIndicator $indicator) {
53887 return $indicator->getMessage();
53888 },
53889 'elapsed' => function (ProgressIndicator $indicator) {
53890 return Helper::formatTime(time() - $indicator->getStartTime());
53891 },
53892 'memory' => function () {
53893 return Helper::formatMemory(memory_get_usage(true));
53894 },
53895 );
53896 }
53897
53898 private static function initFormats()
53899 {
53900 return array(
53901 'normal' => ' %indicator% %message%',
53902 'normal_no_ansi' => ' %message%',
53903
53904 'verbose' => ' %indicator% %message% (%elapsed:6s%)',
53905 'verbose_no_ansi' => ' %message% (%elapsed:6s%)',
53906
53907 'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)',
53908 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)',
53909 );
53910 }
53911 }
53912 <?php
53913
53914
53915
53916
53917
53918
53919
53920
53921
53922
53923 namespace Symfony\Component\Console\Helper;
53924
53925 use Symfony\Component\Console\Exception\InvalidArgumentException;
53926 use Symfony\Component\Console\Exception\RuntimeException;
53927 use Symfony\Component\Console\Input\InputInterface;
53928 use Symfony\Component\Console\Output\ConsoleOutputInterface;
53929 use Symfony\Component\Console\Output\OutputInterface;
53930 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
53931 use Symfony\Component\Console\Question\Question;
53932 use Symfony\Component\Console\Question\ChoiceQuestion;
53933
53934
53935
53936
53937
53938
53939 class QuestionHelper extends Helper
53940 {
53941 private $inputStream;
53942 private static $shell;
53943 private static $stty;
53944
53945
53946
53947
53948
53949
53950
53951
53952
53953
53954
53955
53956 public function ask(InputInterface $input, OutputInterface $output, Question $question)
53957 {
53958 if ($output instanceof ConsoleOutputInterface) {
53959 $output = $output->getErrorOutput();
53960 }
53961
53962 if (!$input->isInteractive()) {
53963 return $question->getDefault();
53964 }
53965
53966 if (!$question->getValidator()) {
53967 return $this->doAsk($output, $question);
53968 }
53969
53970 $that = $this;
53971
53972 $interviewer = function () use ($output, $question, $that) {
53973 return $that->doAsk($output, $question);
53974 };
53975
53976 return $this->validateAttempts($interviewer, $output, $question);
53977 }
53978
53979
53980
53981
53982
53983
53984
53985
53986
53987
53988 public function setInputStream($stream)
53989 {
53990 if (!is_resource($stream)) {
53991 throw new InvalidArgumentException('Input stream must be a valid resource.');
53992 }
53993
53994 $this->inputStream = $stream;
53995 }
53996
53997
53998
53999
54000
54001
54002 public function getInputStream()
54003 {
54004 return $this->inputStream;
54005 }
54006
54007
54008
54009
54010 public function getName()
54011 {
54012 return 'question';
54013 }
54014
54015
54016
54017
54018
54019
54020
54021
54022
54023
54024
54025
54026
54027 public function doAsk(OutputInterface $output, Question $question)
54028 {
54029 $this->writePrompt($output, $question);
54030
54031 $inputStream = $this->inputStream ?: STDIN;
54032 $autocomplete = $question->getAutocompleterValues();
54033
54034 if (null === $autocomplete || !$this->hasSttyAvailable()) {
54035 $ret = false;
54036 if ($question->isHidden()) {
54037 try {
54038 $ret = trim($this->getHiddenResponse($output, $inputStream));
54039 } catch (RuntimeException $e) {
54040 if (!$question->isHiddenFallback()) {
54041 throw $e;
54042 }
54043 }
54044 }
54045
54046 if (false === $ret) {
54047 $ret = fgets($inputStream, 4096);
54048 if (false === $ret) {
54049 throw new RuntimeException('Aborted');
54050 }
54051 $ret = trim($ret);
54052 }
54053 } else {
54054 $ret = trim($this->autocomplete($output, $question, $inputStream));
54055 }
54056
54057 $ret = strlen($ret) > 0 ? $ret : $question->getDefault();
54058
54059 if ($normalizer = $question->getNormalizer()) {
54060 return $normalizer($ret);
54061 }
54062
54063 return $ret;
54064 }
54065
54066
54067
54068
54069
54070
54071
54072 protected function writePrompt(OutputInterface $output, Question $question)
54073 {
54074 $message = $question->getQuestion();
54075
54076 if ($question instanceof ChoiceQuestion) {
54077 $maxWidth = max(array_map(array($this, 'strlen'), array_keys($question->getChoices())));
54078
54079 $messages = (array) $question->getQuestion();
54080 foreach ($question->getChoices() as $key => $value) {
54081 $width = $maxWidth - $this->strlen($key);
54082 $messages[] = '  [<info>'.$key.str_repeat(' ', $width).'</info>] '.$value;
54083 }
54084
54085 $output->writeln($messages);
54086
54087 $message = $question->getPrompt();
54088 }
54089
54090 $output->write($message);
54091 }
54092
54093
54094
54095
54096
54097
54098
54099 protected function writeError(OutputInterface $output, \Exception $error)
54100 {
54101 if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) {
54102 $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error');
54103 } else {
54104 $message = '<error>'.$error->getMessage().'</error>';
54105 }
54106
54107 $output->writeln($message);
54108 }
54109
54110
54111
54112
54113
54114
54115
54116
54117
54118
54119 private function autocomplete(OutputInterface $output, Question $question, $inputStream)
54120 {
54121 $autocomplete = $question->getAutocompleterValues();
54122 $ret = '';
54123
54124 $i = 0;
54125 $ofs = -1;
54126 $matches = $autocomplete;
54127 $numMatches = count($matches);
54128
54129 $sttyMode = shell_exec('stty -g');
54130
54131
54132  shell_exec('stty -icanon -echo');
54133
54134
54135  $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
54136
54137
54138  while (!feof($inputStream)) {
54139 $c = fread($inputStream, 1);
54140
54141
54142  if ("\177" === $c) {
54143 if (0 === $numMatches && 0 !== $i) {
54144 --$i;
54145
54146  $output->write("\033[1D");
54147 }
54148
54149 if ($i === 0) {
54150 $ofs = -1;
54151 $matches = $autocomplete;
54152 $numMatches = count($matches);
54153 } else {
54154 $numMatches = 0;
54155 }
54156
54157
54158  $ret = substr($ret, 0, $i);
54159 } elseif ("\033" === $c) {
54160
54161  $c .= fread($inputStream, 2);
54162
54163
54164  if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
54165 if ('A' === $c[2] && -1 === $ofs) {
54166 $ofs = 0;
54167 }
54168
54169 if (0 === $numMatches) {
54170 continue;
54171 }
54172
54173 $ofs += ('A' === $c[2]) ? -1 : 1;
54174 $ofs = ($numMatches + $ofs) % $numMatches;
54175 }
54176 } elseif (ord($c) < 32) {
54177 if ("\t" === $c || "\n" === $c) {
54178 if ($numMatches > 0 && -1 !== $ofs) {
54179 $ret = $matches[$ofs];
54180
54181  $output->write(substr($ret, $i));
54182 $i = strlen($ret);
54183 }
54184
54185 if ("\n" === $c) {
54186 $output->write($c);
54187 break;
54188 }
54189
54190 $numMatches = 0;
54191 }
54192
54193 continue;
54194 } else {
54195 $output->write($c);
54196 $ret .= $c;
54197 ++$i;
54198
54199 $numMatches = 0;
54200 $ofs = 0;
54201
54202 foreach ($autocomplete as $value) {
54203
54204  if (0 === strpos($value, $ret) && $i !== strlen($value)) {
54205 $matches[$numMatches++] = $value;
54206 }
54207 }
54208 }
54209
54210
54211  $output->write("\033[K");
54212
54213 if ($numMatches > 0 && -1 !== $ofs) {
54214
54215  $output->write("\0337");
54216
54217  $output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
54218
54219  $output->write("\0338");
54220 }
54221 }
54222
54223
54224  shell_exec(sprintf('stty %s', $sttyMode));
54225
54226 return $ret;
54227 }
54228
54229
54230
54231
54232
54233
54234
54235
54236
54237
54238
54239 private function getHiddenResponse(OutputInterface $output, $inputStream)
54240 {
54241 if ('\\' === DIRECTORY_SEPARATOR) {
54242 $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
54243
54244
54245  if ('phar:' === substr(__FILE__, 0, 5)) {
54246 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
54247 copy($exe, $tmpExe);
54248 $exe = $tmpExe;
54249 }
54250
54251 $value = rtrim(shell_exec($exe));
54252 $output->writeln('');
54253
54254 if (isset($tmpExe)) {
54255 unlink($tmpExe);
54256 }
54257
54258 return $value;
54259 }
54260
54261 if ($this->hasSttyAvailable()) {
54262 $sttyMode = shell_exec('stty -g');
54263
54264 shell_exec('stty -echo');
54265 $value = fgets($inputStream, 4096);
54266 shell_exec(sprintf('stty %s', $sttyMode));
54267
54268 if (false === $value) {
54269 throw new RuntimeException('Aborted');
54270 }
54271
54272 $value = trim($value);
54273 $output->writeln('');
54274
54275 return $value;
54276 }
54277
54278 if (false !== $shell = $this->getShell()) {
54279 $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword';
54280 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
54281 $value = rtrim(shell_exec($command));
54282 $output->writeln('');
54283
54284 return $value;
54285 }
54286
54287 throw new RuntimeException('Unable to hide the response.');
54288 }
54289
54290
54291
54292
54293
54294
54295
54296
54297
54298
54299
54300
54301 private function validateAttempts($interviewer, OutputInterface $output, Question $question)
54302 {
54303 $error = null;
54304 $attempts = $question->getMaxAttempts();
54305 while (null === $attempts || $attempts--) {
54306 if (null !== $error) {
54307 $this->writeError($output, $error);
54308 }
54309
54310 try {
54311 return call_user_func($question->getValidator(), $interviewer());
54312 } catch (RuntimeException $e) {
54313 throw $e;
54314 } catch (\Exception $error) {
54315 }
54316 }
54317
54318 throw $error;
54319 }
54320
54321
54322
54323
54324
54325
54326 private function getShell()
54327 {
54328 if (null !== self::$shell) {
54329 return self::$shell;
54330 }
54331
54332 self::$shell = false;
54333
54334 if (file_exists('/usr/bin/env')) {
54335
54336  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
54337 foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
54338 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
54339 self::$shell = $sh;
54340 break;
54341 }
54342 }
54343 }
54344
54345 return self::$shell;
54346 }
54347
54348
54349
54350
54351
54352
54353 private function hasSttyAvailable()
54354 {
54355 if (null !== self::$stty) {
54356 return self::$stty;
54357 }
54358
54359 exec('stty 2>&1', $output, $exitcode);
54360
54361 return self::$stty = $exitcode === 0;
54362 }
54363 }
54364 <?php
54365
54366
54367
54368
54369
54370
54371
54372
54373
54374
54375 namespace Symfony\Component\Console\Helper;
54376
54377 use Symfony\Component\Console\Exception\LogicException;
54378 use Symfony\Component\Console\Input\InputInterface;
54379 use Symfony\Component\Console\Output\OutputInterface;
54380 use Symfony\Component\Console\Question\ChoiceQuestion;
54381 use Symfony\Component\Console\Question\ConfirmationQuestion;
54382 use Symfony\Component\Console\Question\Question;
54383 use Symfony\Component\Console\Style\SymfonyStyle;
54384 use Symfony\Component\Console\Formatter\OutputFormatter;
54385
54386
54387
54388
54389
54390
54391 class SymfonyQuestionHelper extends QuestionHelper
54392 {
54393
54394
54395
54396 public function ask(InputInterface $input, OutputInterface $output, Question $question)
54397 {
54398 $validator = $question->getValidator();
54399 $question->setValidator(function ($value) use ($validator) {
54400 if (null !== $validator) {
54401 $value = $validator($value);
54402 } else {
54403
54404  if (!is_array($value) && !is_bool($value) && 0 === strlen($value)) {
54405 throw new LogicException('A value is required.');
54406 }
54407 }
54408
54409 return $value;
54410 });
54411
54412 return parent::ask($input, $output, $question);
54413 }
54414
54415
54416
54417
54418 protected function writePrompt(OutputInterface $output, Question $question)
54419 {
54420 $text = OutputFormatter::escapeTrailingBackslash($question->getQuestion());
54421 $default = $question->getDefault();
54422
54423 switch (true) {
54424 case null === $default:
54425 $text = sprintf(' <info>%s</info>:', $text);
54426
54427 break;
54428
54429 case $question instanceof ConfirmationQuestion:
54430 $text = sprintf(' <info>%s (yes/no)</info> [<comment>%s</comment>]:', $text, $default ? 'yes' : 'no');
54431
54432 break;
54433
54434 case $question instanceof ChoiceQuestion && $question->isMultiselect():
54435 $choices = $question->getChoices();
54436 $default = explode(',', $default);
54437
54438 foreach ($default as $key => $value) {
54439 $default[$key] = $choices[trim($value)];
54440 }
54441
54442 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape(implode(', ', $default)));
54443
54444 break;
54445
54446 case $question instanceof ChoiceQuestion:
54447 $choices = $question->getChoices();
54448 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($choices[$default]));
54449
54450 break;
54451
54452 default:
54453 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($default));
54454 }
54455
54456 $output->writeln($text);
54457
54458 if ($question instanceof ChoiceQuestion) {
54459 $width = max(array_map('strlen', array_keys($question->getChoices())));
54460
54461 foreach ($question->getChoices() as $key => $value) {
54462 $output->writeln(sprintf("  [<comment>%-${width}s</comment>] %s", $key, $value));
54463 }
54464 }
54465
54466 $output->write(' > ');
54467 }
54468
54469
54470
54471
54472 protected function writeError(OutputInterface $output, \Exception $error)
54473 {
54474 if ($output instanceof SymfonyStyle) {
54475 $output->newLine();
54476 $output->error($error->getMessage());
54477
54478 return;
54479 }
54480
54481 parent::writeError($output, $error);
54482 }
54483 }
54484 <?php
54485
54486
54487
54488
54489
54490
54491
54492
54493
54494
54495 namespace Symfony\Component\Console\Helper;
54496
54497 use Symfony\Component\Console\Output\OutputInterface;
54498 use Symfony\Component\Console\Exception\InvalidArgumentException;
54499
54500
54501
54502
54503
54504
54505
54506
54507
54508 class Table
54509 {
54510
54511
54512
54513
54514
54515 private $headers = array();
54516
54517
54518
54519
54520
54521
54522 private $rows = array();
54523
54524
54525
54526
54527
54528
54529 private $columnWidths = array();
54530
54531
54532
54533
54534
54535
54536 private $numberOfColumns;
54537
54538
54539
54540
54541 private $output;
54542
54543
54544
54545
54546 private $style;
54547
54548
54549
54550
54551 private $columnStyles = array();
54552
54553 private static $styles;
54554
54555 public function __construct(OutputInterface $output)
54556 {
54557 $this->output = $output;
54558
54559 if (!self::$styles) {
54560 self::$styles = self::initStyles();
54561 }
54562
54563 $this->setStyle('default');
54564 }
54565
54566
54567
54568
54569
54570
54571
54572 public static function setStyleDefinition($name, TableStyle $style)
54573 {
54574 if (!self::$styles) {
54575 self::$styles = self::initStyles();
54576 }
54577
54578 self::$styles[$name] = $style;
54579 }
54580
54581
54582
54583
54584
54585
54586
54587
54588 public static function getStyleDefinition($name)
54589 {
54590 if (!self::$styles) {
54591 self::$styles = self::initStyles();
54592 }
54593
54594 if (isset(self::$styles[$name])) {
54595 return self::$styles[$name];
54596 }
54597
54598 throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
54599 }
54600
54601
54602
54603
54604
54605
54606
54607
54608 public function setStyle($name)
54609 {
54610 $this->style = $this->resolveStyle($name);
54611
54612 return $this;
54613 }
54614
54615
54616
54617
54618
54619
54620 public function getStyle()
54621 {
54622 return $this->style;
54623 }
54624
54625
54626
54627
54628
54629
54630
54631
54632
54633 public function setColumnStyle($columnIndex, $name)
54634 {
54635 $columnIndex = (int) $columnIndex;
54636
54637 $this->columnStyles[$columnIndex] = $this->resolveStyle($name);
54638
54639 return $this;
54640 }
54641
54642
54643
54644
54645
54646
54647
54648
54649
54650
54651 public function getColumnStyle($columnIndex)
54652 {
54653 if (isset($this->columnStyles[$columnIndex])) {
54654 return $this->columnStyles[$columnIndex];
54655 }
54656
54657 return $this->getStyle();
54658 }
54659
54660 public function setHeaders(array $headers)
54661 {
54662 $headers = array_values($headers);
54663 if (!empty($headers) && !is_array($headers[0])) {
54664 $headers = array($headers);
54665 }
54666
54667 $this->headers = $headers;
54668
54669 return $this;
54670 }
54671
54672 public function setRows(array $rows)
54673 {
54674 $this->rows = array();
54675
54676 return $this->addRows($rows);
54677 }
54678
54679 public function addRows(array $rows)
54680 {
54681 foreach ($rows as $row) {
54682 $this->addRow($row);
54683 }
54684
54685 return $this;
54686 }
54687
54688 public function addRow($row)
54689 {
54690 if ($row instanceof TableSeparator) {
54691 $this->rows[] = $row;
54692
54693 return $this;
54694 }
54695
54696 if (!is_array($row)) {
54697 throw new InvalidArgumentException('A row must be an array or a TableSeparator instance.');
54698 }
54699
54700 $this->rows[] = array_values($row);
54701
54702 return $this;
54703 }
54704
54705 public function setRow($column, array $row)
54706 {
54707 $this->rows[$column] = $row;
54708
54709 return $this;
54710 }
54711
54712
54713
54714
54715
54716
54717
54718
54719
54720
54721
54722
54723
54724 public function render()
54725 {
54726 $this->calculateNumberOfColumns();
54727 $rows = $this->buildTableRows($this->rows);
54728 $headers = $this->buildTableRows($this->headers);
54729
54730 $this->calculateColumnsWidth(array_merge($headers, $rows));
54731
54732 $this->renderRowSeparator();
54733 if (!empty($headers)) {
54734 foreach ($headers as $header) {
54735 $this->renderRow($header, $this->style->getCellHeaderFormat());
54736 $this->renderRowSeparator();
54737 }
54738 }
54739 foreach ($rows as $row) {
54740 if ($row instanceof TableSeparator) {
54741 $this->renderRowSeparator();
54742 } else {
54743 $this->renderRow($row, $this->style->getCellRowFormat());
54744 }
54745 }
54746 if (!empty($rows)) {
54747 $this->renderRowSeparator();
54748 }
54749
54750 $this->cleanup();
54751 }
54752
54753
54754
54755
54756
54757
54758 private function renderRowSeparator()
54759 {
54760 if (0 === $count = $this->numberOfColumns) {
54761 return;
54762 }
54763
54764 if (!$this->style->getHorizontalBorderChar() && !$this->style->getCrossingChar()) {
54765 return;
54766 }
54767
54768 $markup = $this->style->getCrossingChar();
54769 for ($column = 0; $column < $count; ++$column) {
54770 $markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->columnWidths[$column]).$this->style->getCrossingChar();
54771 }
54772
54773 $this->output->writeln(sprintf($this->style->getBorderFormat(), $markup));
54774 }
54775
54776
54777
54778
54779 private function renderColumnSeparator()
54780 {
54781 return sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar());
54782 }
54783
54784
54785
54786
54787
54788
54789
54790
54791
54792 private function renderRow(array $row, $cellFormat)
54793 {
54794 if (empty($row)) {
54795 return;
54796 }
54797
54798 $rowContent = $this->renderColumnSeparator();
54799 foreach ($this->getRowColumns($row) as $column) {
54800 $rowContent .= $this->renderCell($row, $column, $cellFormat);
54801 $rowContent .= $this->renderColumnSeparator();
54802 }
54803 $this->output->writeln($rowContent);
54804 }
54805
54806
54807
54808
54809
54810
54811
54812
54813 private function renderCell(array $row, $column, $cellFormat)
54814 {
54815 $cell = isset($row[$column]) ? $row[$column] : '';
54816 $width = $this->columnWidths[$column];
54817 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
54818
54819  foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) {
54820 $width += $this->getColumnSeparatorWidth() + $this->columnWidths[$nextColumn];
54821 }
54822 }
54823
54824
54825  if (false !== $encoding = mb_detect_encoding($cell, null, true)) {
54826 $width += strlen($cell) - mb_strwidth($cell, $encoding);
54827 }
54828
54829 $style = $this->getColumnStyle($column);
54830
54831 if ($cell instanceof TableSeparator) {
54832 return sprintf($style->getBorderFormat(), str_repeat($style->getHorizontalBorderChar(), $width));
54833 }
54834
54835 $width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
54836 $content = sprintf($style->getCellRowContentFormat(), $cell);
54837
54838 return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType()));
54839 }
54840
54841
54842
54843
54844 private function calculateNumberOfColumns()
54845 {
54846 if (null !== $this->numberOfColumns) {
54847 return;
54848 }
54849
54850 $columns = array(0);
54851 foreach (array_merge($this->headers, $this->rows) as $row) {
54852 if ($row instanceof TableSeparator) {
54853 continue;
54854 }
54855
54856 $columns[] = $this->getNumberOfColumns($row);
54857 }
54858
54859 $this->numberOfColumns = max($columns);
54860 }
54861
54862 private function buildTableRows($rows)
54863 {
54864 $unmergedRows = array();
54865 for ($rowKey = 0; $rowKey < count($rows); ++$rowKey) {
54866 $rows = $this->fillNextRows($rows, $rowKey);
54867
54868
54869  foreach ($rows[$rowKey] as $column => $cell) {
54870 if (!strstr($cell, "\n")) {
54871 continue;
54872 }
54873 $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
54874 foreach ($lines as $lineKey => $line) {
54875 if ($cell instanceof TableCell) {
54876 $line = new TableCell($line, array('colspan' => $cell->getColspan()));
54877 }
54878 if (0 === $lineKey) {
54879 $rows[$rowKey][$column] = $line;
54880 } else {
54881 $unmergedRows[$rowKey][$lineKey][$column] = $line;
54882 }
54883 }
54884 }
54885 }
54886
54887 $tableRows = array();
54888 foreach ($rows as $rowKey => $row) {
54889 $tableRows[] = $this->fillCells($row);
54890 if (isset($unmergedRows[$rowKey])) {
54891 $tableRows = array_merge($tableRows, $unmergedRows[$rowKey]);
54892 }
54893 }
54894
54895 return $tableRows;
54896 }
54897
54898
54899
54900
54901
54902
54903
54904
54905
54906 private function fillNextRows($rows, $line)
54907 {
54908 $unmergedRows = array();
54909 foreach ($rows[$line] as $column => $cell) {
54910 if ($cell instanceof TableCell && $cell->getRowspan() > 1) {
54911 $nbLines = $cell->getRowspan() - 1;
54912 $lines = array($cell);
54913 if (strstr($cell, "\n")) {
54914 $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
54915 $nbLines = count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines;
54916
54917 $rows[$line][$column] = new TableCell($lines[0], array('colspan' => $cell->getColspan()));
54918 unset($lines[0]);
54919 }
54920
54921
54922  $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, array()), $unmergedRows);
54923 foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
54924 $value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : '';
54925 $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, array('colspan' => $cell->getColspan()));
54926 if ($nbLines === $unmergedRowKey - $line) {
54927 break;
54928 }
54929 }
54930 }
54931 }
54932
54933 foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
54934
54935  if (isset($rows[$unmergedRowKey]) && is_array($rows[$unmergedRowKey]) && ($this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns)) {
54936 foreach ($unmergedRow as $cellKey => $cell) {
54937
54938  array_splice($rows[$unmergedRowKey], $cellKey, 0, array($cell));
54939 }
54940 } else {
54941 $row = $this->copyRow($rows, $unmergedRowKey - 1);
54942 foreach ($unmergedRow as $column => $cell) {
54943 if (!empty($cell)) {
54944 $row[$column] = $unmergedRow[$column];
54945 }
54946 }
54947 array_splice($rows, $unmergedRowKey, 0, array($row));
54948 }
54949 }
54950
54951 return $rows;
54952 }
54953
54954
54955
54956
54957
54958
54959
54960
54961 private function fillCells($row)
54962 {
54963 $newRow = array();
54964 foreach ($row as $column => $cell) {
54965 $newRow[] = $cell;
54966 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
54967 foreach (range($column + 1, $column + $cell->getColspan() - 1) as $position) {
54968
54969  $newRow[] = '';
54970 }
54971 }
54972 }
54973
54974 return $newRow ?: $row;
54975 }
54976
54977
54978
54979
54980
54981
54982
54983 private function copyRow($rows, $line)
54984 {
54985 $row = $rows[$line];
54986 foreach ($row as $cellKey => $cellValue) {
54987 $row[$cellKey] = '';
54988 if ($cellValue instanceof TableCell) {
54989 $row[$cellKey] = new TableCell('', array('colspan' => $cellValue->getColspan()));
54990 }
54991 }
54992
54993 return $row;
54994 }
54995
54996
54997
54998
54999
55000
55001
55002
55003 private function getNumberOfColumns(array $row)
55004 {
55005 $columns = count($row);
55006 foreach ($row as $column) {
55007 $columns += $column instanceof TableCell ? ($column->getColspan() - 1) : 0;
55008 }
55009
55010 return $columns;
55011 }
55012
55013
55014
55015
55016
55017
55018
55019
55020 private function getRowColumns($row)
55021 {
55022 $columns = range(0, $this->numberOfColumns - 1);
55023 foreach ($row as $cellKey => $cell) {
55024 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
55025
55026  $columns = array_diff($columns, range($cellKey + 1, $cellKey + $cell->getColspan() - 1));
55027 }
55028 }
55029
55030 return $columns;
55031 }
55032
55033
55034
55035
55036
55037
55038 private function calculateColumnsWidth($rows)
55039 {
55040 for ($column = 0; $column < $this->numberOfColumns; ++$column) {
55041 $lengths = array();
55042 foreach ($rows as $row) {
55043 if ($row instanceof TableSeparator) {
55044 continue;
55045 }
55046
55047 foreach ($row as $i => $cell) {
55048 if ($cell instanceof TableCell) {
55049 $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell);
55050 $textLength = Helper::strlen($textContent);
55051 if ($textLength > 0) {
55052 $contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan()));
55053 foreach ($contentColumns as $position => $content) {
55054 $row[$i + $position] = $content;
55055 }
55056 }
55057 }
55058 }
55059
55060 $lengths[] = $this->getCellWidth($row, $column);
55061 }
55062
55063 $this->columnWidths[$column] = max($lengths) + strlen($this->style->getCellRowContentFormat()) - 2;
55064 }
55065 }
55066
55067
55068
55069
55070
55071
55072 private function getColumnSeparatorWidth()
55073 {
55074 return strlen(sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar()));
55075 }
55076
55077
55078
55079
55080
55081
55082
55083
55084
55085 private function getCellWidth(array $row, $column)
55086 {
55087 if (isset($row[$column])) {
55088 $cell = $row[$column];
55089 $cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
55090
55091 return $cellWidth;
55092 }
55093
55094 return 0;
55095 }
55096
55097
55098
55099
55100 private function cleanup()
55101 {
55102 $this->columnWidths = array();
55103 $this->numberOfColumns = null;
55104 }
55105
55106 private static function initStyles()
55107 {
55108 $borderless = new TableStyle();
55109 $borderless
55110 ->setHorizontalBorderChar('=')
55111 ->setVerticalBorderChar(' ')
55112 ->setCrossingChar(' ')
55113 ;
55114
55115 $compact = new TableStyle();
55116 $compact
55117 ->setHorizontalBorderChar('')
55118 ->setVerticalBorderChar(' ')
55119 ->setCrossingChar('')
55120 ->setCellRowContentFormat('%s')
55121 ;
55122
55123 $styleGuide = new TableStyle();
55124 $styleGuide
55125 ->setHorizontalBorderChar('-')
55126 ->setVerticalBorderChar(' ')
55127 ->setCrossingChar(' ')
55128 ->setCellHeaderFormat('%s')
55129 ;
55130
55131 return array(
55132 'default' => new TableStyle(),
55133 'borderless' => $borderless,
55134 'compact' => $compact,
55135 'symfony-style-guide' => $styleGuide,
55136 );
55137 }
55138
55139 private function resolveStyle($name)
55140 {
55141 if ($name instanceof TableStyle) {
55142 return $name;
55143 }
55144
55145 if (isset(self::$styles[$name])) {
55146 return self::$styles[$name];
55147 }
55148
55149 throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
55150 }
55151 }
55152 <?php
55153
55154
55155
55156
55157
55158
55159
55160
55161
55162
55163 namespace Symfony\Component\Console\Helper;
55164
55165 use Symfony\Component\Console\Exception\InvalidArgumentException;
55166
55167
55168
55169
55170 class TableCell
55171 {
55172
55173
55174
55175 private $value;
55176
55177
55178
55179
55180 private $options = array(
55181 'rowspan' => 1,
55182 'colspan' => 1,
55183 );
55184
55185
55186
55187
55188
55189 public function __construct($value = '', array $options = array())
55190 {
55191 if (is_numeric($value) && !is_string($value)) {
55192 $value = (string) $value;
55193 }
55194
55195 $this->value = $value;
55196
55197
55198  if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
55199 throw new InvalidArgumentException(sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff)));
55200 }
55201
55202 $this->options = array_merge($this->options, $options);
55203 }
55204
55205
55206
55207
55208
55209
55210 public function __toString()
55211 {
55212 return $this->value;
55213 }
55214
55215
55216
55217
55218
55219
55220 public function getColspan()
55221 {
55222 return (int) $this->options['colspan'];
55223 }
55224
55225
55226
55227
55228
55229
55230 public function getRowspan()
55231 {
55232 return (int) $this->options['rowspan'];
55233 }
55234 }
55235 <?php
55236
55237
55238
55239
55240
55241
55242
55243
55244
55245
55246 namespace Symfony\Component\Console\Helper;
55247
55248 use Symfony\Component\Console\Output\OutputInterface;
55249 use Symfony\Component\Console\Output\NullOutput;
55250 use Symfony\Component\Console\Exception\InvalidArgumentException;
55251
55252
55253
55254
55255
55256
55257
55258
55259
55260
55261 class TableHelper extends Helper
55262 {
55263 const LAYOUT_DEFAULT = 0;
55264 const LAYOUT_BORDERLESS = 1;
55265 const LAYOUT_COMPACT = 2;
55266
55267
55268
55269
55270 private $table;
55271
55272 public function __construct($triggerDeprecationError = true)
55273 {
55274 if ($triggerDeprecationError) {
55275 @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);
55276 }
55277
55278 $this->table = new Table(new NullOutput());
55279 }
55280
55281
55282
55283
55284
55285
55286
55287
55288
55289
55290 public function setLayout($layout)
55291 {
55292 switch ($layout) {
55293 case self::LAYOUT_BORDERLESS:
55294 $this->table->setStyle('borderless');
55295 break;
55296
55297 case self::LAYOUT_COMPACT:
55298 $this->table->setStyle('compact');
55299 break;
55300
55301 case self::LAYOUT_DEFAULT:
55302 $this->table->setStyle('default');
55303 break;
55304
55305 default:
55306 throw new InvalidArgumentException(sprintf('Invalid table layout "%s".', $layout));
55307 }
55308
55309 return $this;
55310 }
55311
55312 public function setHeaders(array $headers)
55313 {
55314 $this->table->setHeaders($headers);
55315
55316 return $this;
55317 }
55318
55319 public function setRows(array $rows)
55320 {
55321 $this->table->setRows($rows);
55322
55323 return $this;
55324 }
55325
55326 public function addRows(array $rows)
55327 {
55328 $this->table->addRows($rows);
55329
55330 return $this;
55331 }
55332
55333 public function addRow(array $row)
55334 {
55335 $this->table->addRow($row);
55336
55337 return $this;
55338 }
55339
55340 public function setRow($column, array $row)
55341 {
55342 $this->table->setRow($column, $row);
55343
55344 return $this;
55345 }
55346
55347
55348
55349
55350
55351
55352
55353
55354 public function setPaddingChar($paddingChar)
55355 {
55356 $this->table->getStyle()->setPaddingChar($paddingChar);
55357
55358 return $this;
55359 }
55360
55361
55362
55363
55364
55365
55366
55367
55368 public function setHorizontalBorderChar($horizontalBorderChar)
55369 {
55370 $this->table->getStyle()->setHorizontalBorderChar($horizontalBorderChar);
55371
55372 return $this;
55373 }
55374
55375
55376
55377
55378
55379
55380
55381
55382 public function setVerticalBorderChar($verticalBorderChar)
55383 {
55384 $this->table->getStyle()->setVerticalBorderChar($verticalBorderChar);
55385
55386 return $this;
55387 }
55388
55389
55390
55391
55392
55393
55394
55395
55396 public function setCrossingChar($crossingChar)
55397 {
55398 $this->table->getStyle()->setCrossingChar($crossingChar);
55399
55400 return $this;
55401 }
55402
55403
55404
55405
55406
55407
55408
55409
55410 public function setCellHeaderFormat($cellHeaderFormat)
55411 {
55412 $this->table->getStyle()->setCellHeaderFormat($cellHeaderFormat);
55413
55414 return $this;
55415 }
55416
55417
55418
55419
55420
55421
55422
55423
55424 public function setCellRowFormat($cellRowFormat)
55425 {
55426 $this->table->getStyle()->setCellHeaderFormat($cellRowFormat);
55427
55428 return $this;
55429 }
55430
55431
55432
55433
55434
55435
55436
55437
55438 public function setCellRowContentFormat($cellRowContentFormat)
55439 {
55440 $this->table->getStyle()->setCellRowContentFormat($cellRowContentFormat);
55441
55442 return $this;
55443 }
55444
55445
55446
55447
55448
55449
55450
55451
55452 public function setBorderFormat($borderFormat)
55453 {
55454 $this->table->getStyle()->setBorderFormat($borderFormat);
55455
55456 return $this;
55457 }
55458
55459
55460
55461
55462
55463
55464
55465
55466 public function setPadType($padType)
55467 {
55468 $this->table->getStyle()->setPadType($padType);
55469
55470 return $this;
55471 }
55472
55473
55474
55475
55476
55477
55478
55479
55480
55481
55482
55483
55484
55485
55486
55487 public function render(OutputInterface $output)
55488 {
55489 $p = new \ReflectionProperty($this->table, 'output');
55490 $p->setAccessible(true);
55491 $p->setValue($this->table, $output);
55492
55493 $this->table->render();
55494 }
55495
55496
55497
55498
55499 public function getName()
55500 {
55501 return 'table';
55502 }
55503 }
55504 <?php
55505
55506
55507
55508
55509
55510
55511
55512
55513
55514
55515 namespace Symfony\Component\Console\Helper;
55516
55517
55518
55519
55520
55521
55522 class TableSeparator extends TableCell
55523 {
55524
55525
55526
55527 public function __construct(array $options = array())
55528 {
55529 parent::__construct('', $options);
55530 }
55531 }
55532 <?php
55533
55534
55535
55536
55537
55538
55539
55540
55541
55542
55543 namespace Symfony\Component\Console\Helper;
55544
55545 use Symfony\Component\Console\Exception\InvalidArgumentException;
55546 use Symfony\Component\Console\Exception\LogicException;
55547
55548
55549
55550
55551
55552
55553
55554 class TableStyle
55555 {
55556 private $paddingChar = ' ';
55557 private $horizontalBorderChar = '-';
55558 private $verticalBorderChar = '|';
55559 private $crossingChar = '+';
55560 private $cellHeaderFormat = '<info>%s</info>';
55561 private $cellRowFormat = '%s';
55562 private $cellRowContentFormat = ' %s ';
55563 private $borderFormat = '%s';
55564 private $padType = STR_PAD_RIGHT;
55565
55566
55567
55568
55569
55570
55571
55572
55573 public function setPaddingChar($paddingChar)
55574 {
55575 if (!$paddingChar) {
55576 throw new LogicException('The padding char must not be empty');
55577 }
55578
55579 $this->paddingChar = $paddingChar;
55580
55581 return $this;
55582 }
55583
55584
55585
55586
55587
55588
55589 public function getPaddingChar()
55590 {
55591 return $this->paddingChar;
55592 }
55593
55594
55595
55596
55597
55598
55599
55600
55601 public function setHorizontalBorderChar($horizontalBorderChar)
55602 {
55603 $this->horizontalBorderChar = $horizontalBorderChar;
55604
55605 return $this;
55606 }
55607
55608
55609
55610
55611
55612
55613 public function getHorizontalBorderChar()
55614 {
55615 return $this->horizontalBorderChar;
55616 }
55617
55618
55619
55620
55621
55622
55623
55624
55625 public function setVerticalBorderChar($verticalBorderChar)
55626 {
55627 $this->verticalBorderChar = $verticalBorderChar;
55628
55629 return $this;
55630 }
55631
55632
55633
55634
55635
55636
55637 public function getVerticalBorderChar()
55638 {
55639 return $this->verticalBorderChar;
55640 }
55641
55642
55643
55644
55645
55646
55647
55648
55649 public function setCrossingChar($crossingChar)
55650 {
55651 $this->crossingChar = $crossingChar;
55652
55653 return $this;
55654 }
55655
55656
55657
55658
55659
55660
55661 public function getCrossingChar()
55662 {
55663 return $this->crossingChar;
55664 }
55665
55666
55667
55668
55669
55670
55671
55672
55673 public function setCellHeaderFormat($cellHeaderFormat)
55674 {
55675 $this->cellHeaderFormat = $cellHeaderFormat;
55676
55677 return $this;
55678 }
55679
55680
55681
55682
55683
55684
55685 public function getCellHeaderFormat()
55686 {
55687 return $this->cellHeaderFormat;
55688 }
55689
55690
55691
55692
55693
55694
55695
55696
55697 public function setCellRowFormat($cellRowFormat)
55698 {
55699 $this->cellRowFormat = $cellRowFormat;
55700
55701 return $this;
55702 }
55703
55704
55705
55706
55707
55708
55709 public function getCellRowFormat()
55710 {
55711 return $this->cellRowFormat;
55712 }
55713
55714
55715
55716
55717
55718
55719
55720
55721 public function setCellRowContentFormat($cellRowContentFormat)
55722 {
55723 $this->cellRowContentFormat = $cellRowContentFormat;
55724
55725 return $this;
55726 }
55727
55728
55729
55730
55731
55732
55733 public function getCellRowContentFormat()
55734 {
55735 return $this->cellRowContentFormat;
55736 }
55737
55738
55739
55740
55741
55742
55743
55744
55745 public function setBorderFormat($borderFormat)
55746 {
55747 $this->borderFormat = $borderFormat;
55748
55749 return $this;
55750 }
55751
55752
55753
55754
55755
55756
55757 public function getBorderFormat()
55758 {
55759 return $this->borderFormat;
55760 }
55761
55762
55763
55764
55765
55766
55767
55768
55769 public function setPadType($padType)
55770 {
55771 if (!in_array($padType, array(STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH), true)) {
55772 throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).');
55773 }
55774
55775 $this->padType = $padType;
55776
55777 return $this;
55778 }
55779
55780
55781
55782
55783
55784
55785 public function getPadType()
55786 {
55787 return $this->padType;
55788 }
55789 }
55790 <?php
55791
55792
55793
55794
55795
55796
55797
55798
55799
55800
55801 namespace Symfony\Component\Console\Input;
55802
55803 use Symfony\Component\Console\Exception\RuntimeException;
55804
55805
55806
55807
55808
55809
55810
55811
55812
55813
55814
55815
55816
55817
55818
55819
55820
55821
55822
55823
55824
55825
55826
55827
55828
55829
55830 class ArgvInput extends Input
55831 {
55832 private $tokens;
55833 private $parsed;
55834
55835
55836
55837
55838
55839
55840
55841 public function __construct(array $argv = null, InputDefinition $definition = null)
55842 {
55843 if (null === $argv) {
55844 $argv = $_SERVER['argv'];
55845 }
55846
55847
55848  array_shift($argv);
55849
55850 $this->tokens = $argv;
55851
55852 parent::__construct($definition);
55853 }
55854
55855 protected function setTokens(array $tokens)
55856 {
55857 $this->tokens = $tokens;
55858 }
55859
55860
55861
55862
55863 protected function parse()
55864 {
55865 $parseOptions = true;
55866 $this->parsed = $this->tokens;
55867 while (null !== $token = array_shift($this->parsed)) {
55868 if ($parseOptions && '' == $token) {
55869 $this->parseArgument($token);
55870 } elseif ($parseOptions && '--' == $token) {
55871 $parseOptions = false;
55872 } elseif ($parseOptions && 0 === strpos($token, '--')) {
55873 $this->parseLongOption($token);
55874 } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
55875 $this->parseShortOption($token);
55876 } else {
55877 $this->parseArgument($token);
55878 }
55879 }
55880 }
55881
55882
55883
55884
55885
55886
55887 private function parseShortOption($token)
55888 {
55889 $name = substr($token, 1);
55890
55891 if (strlen($name) > 1) {
55892 if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) {
55893
55894  $this->addShortOption($name[0], substr($name, 1));
55895 } else {
55896 $this->parseShortOptionSet($name);
55897 }
55898 } else {
55899 $this->addShortOption($name, null);
55900 }
55901 }
55902
55903
55904
55905
55906
55907
55908
55909
55910 private function parseShortOptionSet($name)
55911 {
55912 $len = strlen($name);
55913 for ($i = 0; $i < $len; ++$i) {
55914 if (!$this->definition->hasShortcut($name[$i])) {
55915 throw new RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i]));
55916 }
55917
55918 $option = $this->definition->getOptionForShortcut($name[$i]);
55919 if ($option->acceptValue()) {
55920 $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));
55921
55922 break;
55923 } else {
55924 $this->addLongOption($option->getName(), null);
55925 }
55926 }
55927 }
55928
55929
55930
55931
55932
55933
55934 private function parseLongOption($token)
55935 {
55936 $name = substr($token, 2);
55937
55938 if (false !== $pos = strpos($name, '=')) {
55939 if (0 === strlen($value = substr($name, $pos + 1))) {
55940 array_unshift($this->parsed, null);
55941 }
55942 $this->addLongOption(substr($name, 0, $pos), $value);
55943 } else {
55944 $this->addLongOption($name, null);
55945 }
55946 }
55947
55948
55949
55950
55951
55952
55953
55954
55955 private function parseArgument($token)
55956 {
55957 $c = count($this->arguments);
55958
55959
55960  if ($this->definition->hasArgument($c)) {
55961 $arg = $this->definition->getArgument($c);
55962 $this->arguments[$arg->getName()] = $arg->isArray() ? array($token) : $token;
55963
55964
55965  } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
55966 $arg = $this->definition->getArgument($c - 1);
55967 $this->arguments[$arg->getName()][] = $token;
55968
55969
55970  } else {
55971 $all = $this->definition->getArguments();
55972 if (count($all)) {
55973 throw new RuntimeException(sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all))));
55974 }
55975
55976 throw new RuntimeException(sprintf('No arguments expected, got "%s".', $token));
55977 }
55978 }
55979
55980
55981
55982
55983
55984
55985
55986
55987
55988 private function addShortOption($shortcut, $value)
55989 {
55990 if (!$this->definition->hasShortcut($shortcut)) {
55991 throw new RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
55992 }
55993
55994 $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
55995 }
55996
55997
55998
55999
56000
56001
56002
56003
56004
56005 private function addLongOption($name, $value)
56006 {
56007 if (!$this->definition->hasOption($name)) {
56008 throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name));
56009 }
56010
56011 $option = $this->definition->getOption($name);
56012
56013
56014  if (!isset($value[0])) {
56015 $value = null;
56016 }
56017
56018 if (null !== $value && !$option->acceptValue()) {
56019 throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name));
56020 }
56021
56022 if (null === $value && $option->acceptValue() && count($this->parsed)) {
56023
56024  
56025  $next = array_shift($this->parsed);
56026 if (isset($next[0]) && '-' !== $next[0]) {
56027 $value = $next;
56028 } elseif (empty($next)) {
56029 $value = null;
56030 } else {
56031 array_unshift($this->parsed, $next);
56032 }
56033 }
56034
56035 if (null === $value) {
56036 if ($option->isValueRequired()) {
56037 throw new RuntimeException(sprintf('The "--%s" option requires a value.', $name));
56038 }
56039
56040 if (!$option->isArray()) {
56041 $value = $option->isValueOptional() ? $option->getDefault() : true;
56042 }
56043 }
56044
56045 if ($option->isArray()) {
56046 $this->options[$name][] = $value;
56047 } else {
56048 $this->options[$name] = $value;
56049 }
56050 }
56051
56052
56053
56054
56055 public function getFirstArgument()
56056 {
56057 foreach ($this->tokens as $token) {
56058 if ($token && '-' === $token[0]) {
56059 continue;
56060 }
56061
56062 return $token;
56063 }
56064 }
56065
56066
56067
56068
56069 public function hasParameterOption($values)
56070 {
56071 $values = (array) $values;
56072
56073 foreach ($this->tokens as $token) {
56074 foreach ($values as $value) {
56075 if ($token === $value || 0 === strpos($token, $value.'=')) {
56076 return true;
56077 }
56078 }
56079 }
56080
56081 return false;
56082 }
56083
56084
56085
56086
56087 public function getParameterOption($values, $default = false)
56088 {
56089 $values = (array) $values;
56090 $tokens = $this->tokens;
56091
56092 while (0 < count($tokens)) {
56093 $token = array_shift($tokens);
56094
56095 foreach ($values as $value) {
56096 if ($token === $value || 0 === strpos($token, $value.'=')) {
56097 if (false !== $pos = strpos($token, '=')) {
56098 return substr($token, $pos + 1);
56099 }
56100
56101 return array_shift($tokens);
56102 }
56103 }
56104 }
56105
56106 return $default;
56107 }
56108
56109
56110
56111
56112
56113
56114 public function __toString()
56115 {
56116 $self = $this;
56117 $tokens = array_map(function ($token) use ($self) {
56118 if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) {
56119 return $match[1].$self->escapeToken($match[2]);
56120 }
56121
56122 if ($token && $token[0] !== '-') {
56123 return $self->escapeToken($token);
56124 }
56125
56126 return $token;
56127 }, $this->tokens);
56128
56129 return implode(' ', $tokens);
56130 }
56131 }
56132 <?php
56133
56134
56135
56136
56137
56138
56139
56140
56141
56142
56143 namespace Symfony\Component\Console\Input;
56144
56145 use Symfony\Component\Console\Exception\InvalidArgumentException;
56146 use Symfony\Component\Console\Exception\InvalidOptionException;
56147
56148
56149
56150
56151
56152
56153
56154
56155
56156
56157 class ArrayInput extends Input
56158 {
56159 private $parameters;
56160
56161
56162
56163
56164
56165
56166
56167 public function __construct(array $parameters, InputDefinition $definition = null)
56168 {
56169 $this->parameters = $parameters;
56170
56171 parent::__construct($definition);
56172 }
56173
56174
56175
56176
56177 public function getFirstArgument()
56178 {
56179 foreach ($this->parameters as $key => $value) {
56180 if ($key && '-' === $key[0]) {
56181 continue;
56182 }
56183
56184 return $value;
56185 }
56186 }
56187
56188
56189
56190
56191 public function hasParameterOption($values)
56192 {
56193 $values = (array) $values;
56194
56195 foreach ($this->parameters as $k => $v) {
56196 if (!is_int($k)) {
56197 $v = $k;
56198 }
56199
56200 if (in_array($v, $values)) {
56201 return true;
56202 }
56203 }
56204
56205 return false;
56206 }
56207
56208
56209
56210
56211 public function getParameterOption($values, $default = false)
56212 {
56213 $values = (array) $values;
56214
56215 foreach ($this->parameters as $k => $v) {
56216 if (is_int($k)) {
56217 if (in_array($v, $values)) {
56218 return true;
56219 }
56220 } elseif (in_array($k, $values)) {
56221 return $v;
56222 }
56223 }
56224
56225 return $default;
56226 }
56227
56228
56229
56230
56231
56232
56233 public function __toString()
56234 {
56235 $params = array();
56236 foreach ($this->parameters as $param => $val) {
56237 if ($param && '-' === $param[0]) {
56238 $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : '');
56239 } else {
56240 $params[] = $this->escapeToken($val);
56241 }
56242 }
56243
56244 return implode(' ', $params);
56245 }
56246
56247
56248
56249
56250 protected function parse()
56251 {
56252 foreach ($this->parameters as $key => $value) {
56253 if (0 === strpos($key, '--')) {
56254 $this->addLongOption(substr($key, 2), $value);
56255 } elseif ('-' === $key[0]) {
56256 $this->addShortOption(substr($key, 1), $value);
56257 } else {
56258 $this->addArgument($key, $value);
56259 }
56260 }
56261 }
56262
56263
56264
56265
56266
56267
56268
56269
56270
56271 private function addShortOption($shortcut, $value)
56272 {
56273 if (!$this->definition->hasShortcut($shortcut)) {
56274 throw new InvalidOptionException(sprintf('The "-%s" option does not exist.', $shortcut));
56275 }
56276
56277 $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
56278 }
56279
56280
56281
56282
56283
56284
56285
56286
56287
56288
56289 private function addLongOption($name, $value)
56290 {
56291 if (!$this->definition->hasOption($name)) {
56292 throw new InvalidOptionException(sprintf('The "--%s" option does not exist.', $name));
56293 }
56294
56295 $option = $this->definition->getOption($name);
56296
56297 if (null === $value) {
56298 if ($option->isValueRequired()) {
56299 throw new InvalidOptionException(sprintf('The "--%s" option requires a value.', $name));
56300 }
56301
56302 $value = $option->isValueOptional() ? $option->getDefault() : true;
56303 }
56304
56305 $this->options[$name] = $value;
56306 }
56307
56308
56309
56310
56311
56312
56313
56314
56315
56316 private function addArgument($name, $value)
56317 {
56318 if (!$this->definition->hasArgument($name)) {
56319 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
56320 }
56321
56322 $this->arguments[$name] = $value;
56323 }
56324 }
56325 <?php
56326
56327
56328
56329
56330
56331
56332
56333
56334
56335
56336 namespace Symfony\Component\Console\Input;
56337
56338 use Symfony\Component\Console\Exception\InvalidArgumentException;
56339 use Symfony\Component\Console\Exception\RuntimeException;
56340
56341
56342
56343
56344
56345
56346
56347
56348
56349
56350
56351
56352 abstract class Input implements InputInterface
56353 {
56354
56355
56356
56357 protected $definition;
56358 protected $options = array();
56359 protected $arguments = array();
56360 protected $interactive = true;
56361
56362
56363
56364
56365
56366
56367 public function __construct(InputDefinition $definition = null)
56368 {
56369 if (null === $definition) {
56370 $this->definition = new InputDefinition();
56371 } else {
56372 $this->bind($definition);
56373 $this->validate();
56374 }
56375 }
56376
56377
56378
56379
56380 public function bind(InputDefinition $definition)
56381 {
56382 $this->arguments = array();
56383 $this->options = array();
56384 $this->definition = $definition;
56385
56386 $this->parse();
56387 }
56388
56389
56390
56391
56392 abstract protected function parse();
56393
56394
56395
56396
56397 public function validate()
56398 {
56399 $definition = $this->definition;
56400 $givenArguments = $this->arguments;
56401
56402 $missingArguments = array_filter(array_keys($definition->getArguments()), function ($argument) use ($definition, $givenArguments) {
56403 return !array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired();
56404 });
56405
56406 if (count($missingArguments) > 0) {
56407 throw new RuntimeException(sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments)));
56408 }
56409 }
56410
56411
56412
56413
56414 public function isInteractive()
56415 {
56416 return $this->interactive;
56417 }
56418
56419
56420
56421
56422 public function setInteractive($interactive)
56423 {
56424 $this->interactive = (bool) $interactive;
56425 }
56426
56427
56428
56429
56430 public function getArguments()
56431 {
56432 return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
56433 }
56434
56435
56436
56437
56438 public function getArgument($name)
56439 {
56440 if (!$this->definition->hasArgument($name)) {
56441 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
56442 }
56443
56444 return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault();
56445 }
56446
56447
56448
56449
56450 public function setArgument($name, $value)
56451 {
56452 if (!$this->definition->hasArgument($name)) {
56453 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
56454 }
56455
56456 $this->arguments[$name] = $value;
56457 }
56458
56459
56460
56461
56462 public function hasArgument($name)
56463 {
56464 return $this->definition->hasArgument($name);
56465 }
56466
56467
56468
56469
56470 public function getOptions()
56471 {
56472 return array_merge($this->definition->getOptionDefaults(), $this->options);
56473 }
56474
56475
56476
56477
56478 public function getOption($name)
56479 {
56480 if (!$this->definition->hasOption($name)) {
56481 throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
56482 }
56483
56484 return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
56485 }
56486
56487
56488
56489
56490 public function setOption($name, $value)
56491 {
56492 if (!$this->definition->hasOption($name)) {
56493 throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
56494 }
56495
56496 $this->options[$name] = $value;
56497 }
56498
56499
56500
56501
56502 public function hasOption($name)
56503 {
56504 return $this->definition->hasOption($name);
56505 }
56506
56507
56508
56509
56510
56511
56512
56513
56514 public function escapeToken($token)
56515 {
56516 return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token);
56517 }
56518 }
56519 <?php
56520
56521
56522
56523
56524
56525
56526
56527
56528
56529
56530 namespace Symfony\Component\Console\Input;
56531
56532 use Symfony\Component\Console\Exception\InvalidArgumentException;
56533 use Symfony\Component\Console\Exception\LogicException;
56534
56535
56536
56537
56538
56539
56540 class InputArgument
56541 {
56542 const REQUIRED = 1;
56543 const OPTIONAL = 2;
56544 const IS_ARRAY = 4;
56545
56546 private $name;
56547 private $mode;
56548 private $default;
56549 private $description;
56550
56551
56552
56553
56554
56555
56556
56557
56558
56559
56560
56561 public function __construct($name, $mode = null, $description = '', $default = null)
56562 {
56563 if (null === $mode) {
56564 $mode = self::OPTIONAL;
56565 } elseif (!is_int($mode) || $mode > 7 || $mode < 1) {
56566 throw new InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode));
56567 }
56568
56569 $this->name = $name;
56570 $this->mode = $mode;
56571 $this->description = $description;
56572
56573 $this->setDefault($default);
56574 }
56575
56576
56577
56578
56579
56580
56581 public function getName()
56582 {
56583 return $this->name;
56584 }
56585
56586
56587
56588
56589
56590
56591 public function isRequired()
56592 {
56593 return self::REQUIRED === (self::REQUIRED & $this->mode);
56594 }
56595
56596
56597
56598
56599
56600
56601 public function isArray()
56602 {
56603 return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
56604 }
56605
56606
56607
56608
56609
56610
56611
56612
56613 public function setDefault($default = null)
56614 {
56615 if (self::REQUIRED === $this->mode && null !== $default) {
56616 throw new LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.');
56617 }
56618
56619 if ($this->isArray()) {
56620 if (null === $default) {
56621 $default = array();
56622 } elseif (!is_array($default)) {
56623 throw new LogicException('A default value for an array argument must be an array.');
56624 }
56625 }
56626
56627 $this->default = $default;
56628 }
56629
56630
56631
56632
56633
56634
56635 public function getDefault()
56636 {
56637 return $this->default;
56638 }
56639
56640
56641
56642
56643
56644
56645 public function getDescription()
56646 {
56647 return $this->description;
56648 }
56649 }
56650 <?php
56651
56652
56653
56654
56655
56656
56657
56658
56659
56660
56661 namespace Symfony\Component\Console\Input;
56662
56663
56664
56665
56666
56667
56668
56669 interface InputAwareInterface
56670 {
56671
56672
56673
56674
56675
56676 public function setInput(InputInterface $input);
56677 }
56678 <?php
56679
56680
56681
56682
56683
56684
56685
56686
56687
56688
56689 namespace Symfony\Component\Console\Input;
56690
56691 use Symfony\Component\Console\Descriptor\TextDescriptor;
56692 use Symfony\Component\Console\Descriptor\XmlDescriptor;
56693 use Symfony\Component\Console\Output\BufferedOutput;
56694 use Symfony\Component\Console\Exception\InvalidArgumentException;
56695 use Symfony\Component\Console\Exception\LogicException;
56696
56697
56698
56699
56700
56701
56702
56703
56704
56705
56706
56707
56708
56709 class InputDefinition
56710 {
56711 private $arguments;
56712 private $requiredCount;
56713 private $hasAnArrayArgument = false;
56714 private $hasOptional;
56715 private $options;
56716 private $shortcuts;
56717
56718
56719
56720
56721
56722
56723 public function __construct(array $definition = array())
56724 {
56725 $this->setDefinition($definition);
56726 }
56727
56728
56729
56730
56731
56732
56733 public function setDefinition(array $definition)
56734 {
56735 $arguments = array();
56736 $options = array();
56737 foreach ($definition as $item) {
56738 if ($item instanceof InputOption) {
56739 $options[] = $item;
56740 } else {
56741 $arguments[] = $item;
56742 }
56743 }
56744
56745 $this->setArguments($arguments);
56746 $this->setOptions($options);
56747 }
56748
56749
56750
56751
56752
56753
56754 public function setArguments($arguments = array())
56755 {
56756 $this->arguments = array();
56757 $this->requiredCount = 0;
56758 $this->hasOptional = false;
56759 $this->hasAnArrayArgument = false;
56760 $this->addArguments($arguments);
56761 }
56762
56763
56764
56765
56766
56767
56768 public function addArguments($arguments = array())
56769 {
56770 if (null !== $arguments) {
56771 foreach ($arguments as $argument) {
56772 $this->addArgument($argument);
56773 }
56774 }
56775 }
56776
56777
56778
56779
56780
56781
56782
56783
56784 public function addArgument(InputArgument $argument)
56785 {
56786 if (isset($this->arguments[$argument->getName()])) {
56787 throw new LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName()));
56788 }
56789
56790 if ($this->hasAnArrayArgument) {
56791 throw new LogicException('Cannot add an argument after an array argument.');
56792 }
56793
56794 if ($argument->isRequired() && $this->hasOptional) {
56795 throw new LogicException('Cannot add a required argument after an optional one.');
56796 }
56797
56798 if ($argument->isArray()) {
56799 $this->hasAnArrayArgument = true;
56800 }
56801
56802 if ($argument->isRequired()) {
56803 ++$this->requiredCount;
56804 } else {
56805 $this->hasOptional = true;
56806 }
56807
56808 $this->arguments[$argument->getName()] = $argument;
56809 }
56810
56811
56812
56813
56814
56815
56816
56817
56818
56819
56820 public function getArgument($name)
56821 {
56822 if (!$this->hasArgument($name)) {
56823 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
56824 }
56825
56826 $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
56827
56828 return $arguments[$name];
56829 }
56830
56831
56832
56833
56834
56835
56836
56837
56838 public function hasArgument($name)
56839 {
56840 $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
56841
56842 return isset($arguments[$name]);
56843 }
56844
56845
56846
56847
56848
56849
56850 public function getArguments()
56851 {
56852 return $this->arguments;
56853 }
56854
56855
56856
56857
56858
56859
56860 public function getArgumentCount()
56861 {
56862 return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments);
56863 }
56864
56865
56866
56867
56868
56869
56870 public function getArgumentRequiredCount()
56871 {
56872 return $this->requiredCount;
56873 }
56874
56875
56876
56877
56878
56879
56880 public function getArgumentDefaults()
56881 {
56882 $values = array();
56883 foreach ($this->arguments as $argument) {
56884 $values[$argument->getName()] = $argument->getDefault();
56885 }
56886
56887 return $values;
56888 }
56889
56890
56891
56892
56893
56894
56895 public function setOptions($options = array())
56896 {
56897 $this->options = array();
56898 $this->shortcuts = array();
56899 $this->addOptions($options);
56900 }
56901
56902
56903
56904
56905
56906
56907 public function addOptions($options = array())
56908 {
56909 foreach ($options as $option) {
56910 $this->addOption($option);
56911 }
56912 }
56913
56914
56915
56916
56917
56918
56919
56920
56921 public function addOption(InputOption $option)
56922 {
56923 if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
56924 throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName()));
56925 }
56926
56927 if ($option->getShortcut()) {
56928 foreach (explode('|', $option->getShortcut()) as $shortcut) {
56929 if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) {
56930 throw new LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut));
56931 }
56932 }
56933 }
56934
56935 $this->options[$option->getName()] = $option;
56936 if ($option->getShortcut()) {
56937 foreach (explode('|', $option->getShortcut()) as $shortcut) {
56938 $this->shortcuts[$shortcut] = $option->getName();
56939 }
56940 }
56941 }
56942
56943
56944
56945
56946
56947
56948
56949
56950
56951
56952 public function getOption($name)
56953 {
56954 if (!$this->hasOption($name)) {
56955 throw new InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
56956 }
56957
56958 return $this->options[$name];
56959 }
56960
56961
56962
56963
56964
56965
56966
56967
56968
56969
56970
56971 public function hasOption($name)
56972 {
56973 return isset($this->options[$name]);
56974 }
56975
56976
56977
56978
56979
56980
56981 public function getOptions()
56982 {
56983 return $this->options;
56984 }
56985
56986
56987
56988
56989
56990
56991
56992
56993 public function hasShortcut($name)
56994 {
56995 return isset($this->shortcuts[$name]);
56996 }
56997
56998
56999
57000
57001
57002
57003
57004
57005 public function getOptionForShortcut($shortcut)
57006 {
57007 return $this->getOption($this->shortcutToName($shortcut));
57008 }
57009
57010
57011
57012
57013
57014
57015 public function getOptionDefaults()
57016 {
57017 $values = array();
57018 foreach ($this->options as $option) {
57019 $values[$option->getName()] = $option->getDefault();
57020 }
57021
57022 return $values;
57023 }
57024
57025
57026
57027
57028
57029
57030
57031
57032
57033
57034 private function shortcutToName($shortcut)
57035 {
57036 if (!isset($this->shortcuts[$shortcut])) {
57037 throw new InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
57038 }
57039
57040 return $this->shortcuts[$shortcut];
57041 }
57042
57043
57044
57045
57046
57047
57048
57049
57050 public function getSynopsis($short = false)
57051 {
57052 $elements = array();
57053
57054 if ($short && $this->getOptions()) {
57055 $elements[] = '[options]';
57056 } elseif (!$short) {
57057 foreach ($this->getOptions() as $option) {
57058 $value = '';
57059 if ($option->acceptValue()) {
57060 $value = sprintf(
57061 ' %s%s%s',
57062 $option->isValueOptional() ? '[' : '',
57063 strtoupper($option->getName()),
57064 $option->isValueOptional() ? ']' : ''
57065 );
57066 }
57067
57068 $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
57069 $elements[] = sprintf('[%s--%s%s]', $shortcut, $option->getName(), $value);
57070 }
57071 }
57072
57073 if (count($elements) && $this->getArguments()) {
57074 $elements[] = '[--]';
57075 }
57076
57077 foreach ($this->getArguments() as $argument) {
57078 $element = '<'.$argument->getName().'>';
57079 if (!$argument->isRequired()) {
57080 $element = '['.$element.']';
57081 } elseif ($argument->isArray()) {
57082 $element = $element.' ('.$element.')';
57083 }
57084
57085 if ($argument->isArray()) {
57086 $element .= '...';
57087 }
57088
57089 $elements[] = $element;
57090 }
57091
57092 return implode(' ', $elements);
57093 }
57094
57095
57096
57097
57098
57099
57100
57101
57102 public function asText()
57103 {
57104 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
57105
57106 $descriptor = new TextDescriptor();
57107 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
57108 $descriptor->describe($output, $this, array('raw_output' => true));
57109
57110 return $output->fetch();
57111 }
57112
57113
57114
57115
57116
57117
57118
57119
57120
57121
57122 public function asXml($asDom = false)
57123 {
57124 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
57125
57126 $descriptor = new XmlDescriptor();
57127
57128 if ($asDom) {
57129 return $descriptor->getInputDefinitionDocument($this);
57130 }
57131
57132 $output = new BufferedOutput();
57133 $descriptor->describe($output, $this);
57134
57135 return $output->fetch();
57136 }
57137 }
57138 <?php
57139
57140
57141
57142
57143
57144
57145
57146
57147
57148
57149 namespace Symfony\Component\Console\Input;
57150
57151 use Symfony\Component\Console\Exception\InvalidArgumentException;
57152 use Symfony\Component\Console\Exception\RuntimeException;
57153
57154
57155
57156
57157
57158
57159 interface InputInterface
57160 {
57161
57162
57163
57164
57165
57166 public function getFirstArgument();
57167
57168
57169
57170
57171
57172
57173
57174
57175
57176
57177
57178 public function hasParameterOption($values);
57179
57180
57181
57182
57183
57184
57185
57186
57187
57188
57189
57190
57191 public function getParameterOption($values, $default = false);
57192
57193
57194
57195
57196
57197
57198 public function bind(InputDefinition $definition);
57199
57200
57201
57202
57203
57204
57205 public function validate();
57206
57207
57208
57209
57210
57211
57212 public function getArguments();
57213
57214
57215
57216
57217
57218
57219
57220
57221
57222
57223 public function getArgument($name);
57224
57225
57226
57227
57228
57229
57230
57231
57232
57233 public function setArgument($name, $value);
57234
57235
57236
57237
57238
57239
57240
57241
57242 public function hasArgument($name);
57243
57244
57245
57246
57247
57248
57249 public function getOptions();
57250
57251
57252
57253
57254
57255
57256
57257
57258
57259
57260 public function getOption($name);
57261
57262
57263
57264
57265
57266
57267
57268
57269
57270 public function setOption($name, $value);
57271
57272
57273
57274
57275
57276
57277
57278
57279 public function hasOption($name);
57280
57281
57282
57283
57284
57285
57286 public function isInteractive();
57287
57288
57289
57290
57291
57292
57293 public function setInteractive($interactive);
57294 }
57295 <?php
57296
57297
57298
57299
57300
57301
57302
57303
57304
57305
57306 namespace Symfony\Component\Console\Input;
57307
57308 use Symfony\Component\Console\Exception\InvalidArgumentException;
57309 use Symfony\Component\Console\Exception\LogicException;
57310
57311
57312
57313
57314
57315
57316 class InputOption
57317 {
57318 const VALUE_NONE = 1;
57319 const VALUE_REQUIRED = 2;
57320 const VALUE_OPTIONAL = 4;
57321 const VALUE_IS_ARRAY = 8;
57322
57323 private $name;
57324 private $shortcut;
57325 private $mode;
57326 private $default;
57327 private $description;
57328
57329
57330
57331
57332
57333
57334
57335
57336
57337
57338
57339
57340 public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null)
57341 {
57342 if (0 === strpos($name, '--')) {
57343 $name = substr($name, 2);
57344 }
57345
57346 if (empty($name)) {
57347 throw new InvalidArgumentException('An option name cannot be empty.');
57348 }
57349
57350 if (empty($shortcut)) {
57351 $shortcut = null;
57352 }
57353
57354 if (null !== $shortcut) {
57355 if (is_array($shortcut)) {
57356 $shortcut = implode('|', $shortcut);
57357 }
57358 $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-'));
57359 $shortcuts = array_filter($shortcuts);
57360 $shortcut = implode('|', $shortcuts);
57361
57362 if (empty($shortcut)) {
57363 throw new InvalidArgumentException('An option shortcut cannot be empty.');
57364 }
57365 }
57366
57367 if (null === $mode) {
57368 $mode = self::VALUE_NONE;
57369 } elseif (!is_int($mode) || $mode > 15 || $mode < 1) {
57370 throw new InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
57371 }
57372
57373 $this->name = $name;
57374 $this->shortcut = $shortcut;
57375 $this->mode = $mode;
57376 $this->description = $description;
57377
57378 if ($this->isArray() && !$this->acceptValue()) {
57379 throw new InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.');
57380 }
57381
57382 $this->setDefault($default);
57383 }
57384
57385
57386
57387
57388
57389
57390 public function getShortcut()
57391 {
57392 return $this->shortcut;
57393 }
57394
57395
57396
57397
57398
57399
57400 public function getName()
57401 {
57402 return $this->name;
57403 }
57404
57405
57406
57407
57408
57409
57410 public function acceptValue()
57411 {
57412 return $this->isValueRequired() || $this->isValueOptional();
57413 }
57414
57415
57416
57417
57418
57419
57420 public function isValueRequired()
57421 {
57422 return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode);
57423 }
57424
57425
57426
57427
57428
57429
57430 public function isValueOptional()
57431 {
57432 return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode);
57433 }
57434
57435
57436
57437
57438
57439
57440 public function isArray()
57441 {
57442 return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
57443 }
57444
57445
57446
57447
57448
57449
57450
57451
57452 public function setDefault($default = null)
57453 {
57454 if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
57455 throw new LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
57456 }
57457
57458 if ($this->isArray()) {
57459 if (null === $default) {
57460 $default = array();
57461 } elseif (!is_array($default)) {
57462 throw new LogicException('A default value for an array option must be an array.');
57463 }
57464 }
57465
57466 $this->default = $this->acceptValue() ? $default : false;
57467 }
57468
57469
57470
57471
57472
57473
57474 public function getDefault()
57475 {
57476 return $this->default;
57477 }
57478
57479
57480
57481
57482
57483
57484 public function getDescription()
57485 {
57486 return $this->description;
57487 }
57488
57489
57490
57491
57492
57493
57494
57495
57496 public function equals(InputOption $option)
57497 {
57498 return $option->getName() === $this->getName()
57499 && $option->getShortcut() === $this->getShortcut()
57500 && $option->getDefault() === $this->getDefault()
57501 && $option->isArray() === $this->isArray()
57502 && $option->isValueRequired() === $this->isValueRequired()
57503 && $option->isValueOptional() === $this->isValueOptional()
57504 ;
57505 }
57506 }
57507 <?php
57508
57509
57510
57511
57512
57513
57514
57515
57516
57517
57518 namespace Symfony\Component\Console\Input;
57519
57520 use Symfony\Component\Console\Exception\InvalidArgumentException;
57521
57522
57523
57524
57525
57526
57527
57528
57529
57530
57531 class StringInput extends ArgvInput
57532 {
57533 const REGEX_STRING = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)';
57534 const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
57535
57536
57537
57538
57539
57540
57541
57542
57543
57544 public function __construct($input, InputDefinition $definition = null)
57545 {
57546 if ($definition) {
57547 @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);
57548 }
57549
57550 parent::__construct(array(), null);
57551
57552 $this->setTokens($this->tokenize($input));
57553
57554 if (null !== $definition) {
57555 $this->bind($definition);
57556 }
57557 }
57558
57559
57560
57561
57562
57563
57564
57565
57566
57567
57568 private function tokenize($input)
57569 {
57570 $tokens = array();
57571 $length = strlen($input);
57572 $cursor = 0;
57573 while ($cursor < $length) {
57574 if (preg_match('/\s+/A', $input, $match, null, $cursor)) {
57575 } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) {
57576 $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2)));
57577 } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) {
57578 $tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2));
57579 } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) {
57580 $tokens[] = stripcslashes($match[1]);
57581 } else {
57582
57583  throw new InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10)));
57584 }
57585
57586 $cursor += strlen($match[0]);
57587 }
57588
57589 return $tokens;
57590 }
57591 }
57592 Copyright (c) 2004-2017 Fabien Potencier
57593
57594 Permission is hereby granted, free of charge, to any person obtaining a copy
57595 of this software and associated documentation files (the "Software"), to deal
57596 in the Software without restriction, including without limitation the rights
57597 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
57598 copies of the Software, and to permit persons to whom the Software is furnished
57599 to do so, subject to the following conditions:
57600
57601 The above copyright notice and this permission notice shall be included in all
57602 copies or substantial portions of the Software.
57603
57604 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
57605 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
57606 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
57607 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
57608 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
57609 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
57610 THE SOFTWARE.
57611 <?php
57612
57613
57614
57615
57616
57617
57618
57619
57620
57621
57622 namespace Symfony\Component\Console\Logger;
57623
57624 use Psr\Log\AbstractLogger;
57625 use Psr\Log\InvalidArgumentException;
57626 use Psr\Log\LogLevel;
57627 use Symfony\Component\Console\Output\OutputInterface;
57628 use Symfony\Component\Console\Output\ConsoleOutputInterface;
57629
57630
57631
57632
57633
57634
57635
57636
57637 class ConsoleLogger extends AbstractLogger
57638 {
57639 const INFO = 'info';
57640 const ERROR = 'error';
57641
57642
57643
57644
57645 private $output;
57646
57647
57648
57649 private $verbosityLevelMap = array(
57650 LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL,
57651 LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL,
57652 LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL,
57653 LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL,
57654 LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL,
57655 LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE,
57656 LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE,
57657 LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG,
57658 );
57659
57660
57661
57662 private $formatLevelMap = array(
57663 LogLevel::EMERGENCY => self::ERROR,
57664 LogLevel::ALERT => self::ERROR,
57665 LogLevel::CRITICAL => self::ERROR,
57666 LogLevel::ERROR => self::ERROR,
57667 LogLevel::WARNING => self::INFO,
57668 LogLevel::NOTICE => self::INFO,
57669 LogLevel::INFO => self::INFO,
57670 LogLevel::DEBUG => self::INFO,
57671 );
57672
57673
57674
57675
57676
57677
57678 public function __construct(OutputInterface $output, array $verbosityLevelMap = array(), array $formatLevelMap = array())
57679 {
57680 $this->output = $output;
57681 $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
57682 $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap;
57683 }
57684
57685
57686
57687
57688 public function log($level, $message, array $context = array())
57689 {
57690 if (!isset($this->verbosityLevelMap[$level])) {
57691 throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level));
57692 }
57693
57694
57695  if ($this->formatLevelMap[$level] === self::ERROR && $this->output instanceof ConsoleOutputInterface) {
57696 $output = $this->output->getErrorOutput();
57697 } else {
57698 $output = $this->output;
57699 }
57700
57701 if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) {
57702 $output->writeln(sprintf('<%1$s>[%2$s] %3$s</%1$s>', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)));
57703 }
57704 }
57705
57706
57707
57708
57709
57710
57711
57712
57713
57714
57715
57716 private function interpolate($message, array $context)
57717 {
57718
57719  $replace = array();
57720 foreach ($context as $key => $val) {
57721 if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) {
57722 $replace[sprintf('{%s}', $key)] = $val;
57723 }
57724 }
57725
57726
57727  return strtr($message, $replace);
57728 }
57729 }
57730 <?php
57731
57732
57733
57734
57735
57736
57737
57738
57739
57740
57741 namespace Symfony\Component\Console\Output;
57742
57743
57744
57745
57746 class BufferedOutput extends Output
57747 {
57748
57749
57750
57751 private $buffer = '';
57752
57753
57754
57755
57756
57757
57758 public function fetch()
57759 {
57760 $content = $this->buffer;
57761 $this->buffer = '';
57762
57763 return $content;
57764 }
57765
57766
57767
57768
57769 protected function doWrite($message, $newline)
57770 {
57771 $this->buffer .= $message;
57772
57773 if ($newline) {
57774 $this->buffer .= PHP_EOL;
57775 }
57776 }
57777 }
57778 <?php
57779
57780
57781
57782
57783
57784
57785
57786
57787
57788
57789 namespace Symfony\Component\Console\Output;
57790
57791 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
57792
57793
57794
57795
57796
57797
57798
57799
57800
57801
57802
57803
57804
57805
57806 class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
57807 {
57808
57809
57810
57811 private $stderr;
57812
57813
57814
57815
57816
57817
57818
57819
57820 public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
57821 {
57822 parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter);
57823
57824 $actualDecorated = $this->isDecorated();
57825 $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter());
57826
57827 if (null === $decorated) {
57828 $this->setDecorated($actualDecorated && $this->stderr->isDecorated());
57829 }
57830 }
57831
57832
57833
57834
57835 public function setDecorated($decorated)
57836 {
57837 parent::setDecorated($decorated);
57838 $this->stderr->setDecorated($decorated);
57839 }
57840
57841
57842
57843
57844 public function setFormatter(OutputFormatterInterface $formatter)
57845 {
57846 parent::setFormatter($formatter);
57847 $this->stderr->setFormatter($formatter);
57848 }
57849
57850
57851
57852
57853 public function setVerbosity($level)
57854 {
57855 parent::setVerbosity($level);
57856 $this->stderr->setVerbosity($level);
57857 }
57858
57859
57860
57861
57862 public function getErrorOutput()
57863 {
57864 return $this->stderr;
57865 }
57866
57867
57868
57869
57870 public function setErrorOutput(OutputInterface $error)
57871 {
57872 $this->stderr = $error;
57873 }
57874
57875
57876
57877
57878
57879
57880
57881 protected function hasStdoutSupport()
57882 {
57883 return false === $this->isRunningOS400();
57884 }
57885
57886
57887
57888
57889
57890
57891
57892 protected function hasStderrSupport()
57893 {
57894 return false === $this->isRunningOS400();
57895 }
57896
57897
57898
57899
57900
57901
57902
57903 private function isRunningOS400()
57904 {
57905 $checks = array(
57906 function_exists('php_uname') ? php_uname('s') : '',
57907 getenv('OSTYPE'),
57908 PHP_OS,
57909 );
57910
57911 return false !== stripos(implode(';', $checks), 'OS400');
57912 }
57913
57914
57915
57916
57917 private function openOutputStream()
57918 {
57919 $outputStream = $this->hasStdoutSupport() ? 'php://stdout' : 'php://output';
57920
57921 return @fopen($outputStream, 'w') ?: fopen('php://output', 'w');
57922 }
57923
57924
57925
57926
57927 private function openErrorStream()
57928 {
57929 $errorStream = $this->hasStderrSupport() ? 'php://stderr' : 'php://output';
57930
57931 return fopen($errorStream, 'w');
57932 }
57933 }
57934 <?php
57935
57936
57937
57938
57939
57940
57941
57942
57943
57944
57945 namespace Symfony\Component\Console\Output;
57946
57947
57948
57949
57950
57951
57952
57953 interface ConsoleOutputInterface extends OutputInterface
57954 {
57955
57956
57957
57958
57959
57960 public function getErrorOutput();
57961
57962
57963
57964
57965
57966
57967 public function setErrorOutput(OutputInterface $error);
57968 }
57969 <?php
57970
57971
57972
57973
57974
57975
57976
57977
57978
57979
57980 namespace Symfony\Component\Console\Output;
57981
57982 use Symfony\Component\Console\Formatter\OutputFormatter;
57983 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
57984
57985
57986
57987
57988
57989
57990
57991
57992
57993 class NullOutput implements OutputInterface
57994 {
57995
57996
57997
57998 public function setFormatter(OutputFormatterInterface $formatter)
57999 {
58000
58001  }
58002
58003
58004
58005
58006 public function getFormatter()
58007 {
58008
58009  return new OutputFormatter();
58010 }
58011
58012
58013
58014
58015 public function setDecorated($decorated)
58016 {
58017
58018  }
58019
58020
58021
58022
58023 public function isDecorated()
58024 {
58025 return false;
58026 }
58027
58028
58029
58030
58031 public function setVerbosity($level)
58032 {
58033
58034  }
58035
58036
58037
58038
58039 public function getVerbosity()
58040 {
58041 return self::VERBOSITY_QUIET;
58042 }
58043
58044
58045
58046
58047 public function isQuiet()
58048 {
58049 return true;
58050 }
58051
58052
58053
58054
58055 public function isVerbose()
58056 {
58057 return false;
58058 }
58059
58060
58061
58062
58063 public function isVeryVerbose()
58064 {
58065 return false;
58066 }
58067
58068
58069
58070
58071 public function isDebug()
58072 {
58073 return false;
58074 }
58075
58076
58077
58078
58079 public function writeln($messages, $options = self::OUTPUT_NORMAL)
58080 {
58081
58082  }
58083
58084
58085
58086
58087 public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
58088 {
58089
58090  }
58091 }
58092 <?php
58093
58094
58095
58096
58097
58098
58099
58100
58101
58102
58103 namespace Symfony\Component\Console\Output;
58104
58105 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
58106 use Symfony\Component\Console\Formatter\OutputFormatter;
58107
58108
58109
58110
58111
58112
58113
58114
58115
58116
58117
58118
58119
58120
58121 abstract class Output implements OutputInterface
58122 {
58123 private $verbosity;
58124 private $formatter;
58125
58126
58127
58128
58129
58130
58131
58132
58133 public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null)
58134 {
58135 $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity;
58136 $this->formatter = $formatter ?: new OutputFormatter();
58137 $this->formatter->setDecorated($decorated);
58138 }
58139
58140
58141
58142
58143 public function setFormatter(OutputFormatterInterface $formatter)
58144 {
58145 $this->formatter = $formatter;
58146 }
58147
58148
58149
58150
58151 public function getFormatter()
58152 {
58153 return $this->formatter;
58154 }
58155
58156
58157
58158
58159 public function setDecorated($decorated)
58160 {
58161 $this->formatter->setDecorated($decorated);
58162 }
58163
58164
58165
58166
58167 public function isDecorated()
58168 {
58169 return $this->formatter->isDecorated();
58170 }
58171
58172
58173
58174
58175 public function setVerbosity($level)
58176 {
58177 $this->verbosity = (int) $level;
58178 }
58179
58180
58181
58182
58183 public function getVerbosity()
58184 {
58185 return $this->verbosity;
58186 }
58187
58188
58189
58190
58191 public function isQuiet()
58192 {
58193 return self::VERBOSITY_QUIET === $this->verbosity;
58194 }
58195
58196
58197
58198
58199 public function isVerbose()
58200 {
58201 return self::VERBOSITY_VERBOSE <= $this->verbosity;
58202 }
58203
58204
58205
58206
58207 public function isVeryVerbose()
58208 {
58209 return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
58210 }
58211
58212
58213
58214
58215 public function isDebug()
58216 {
58217 return self::VERBOSITY_DEBUG <= $this->verbosity;
58218 }
58219
58220
58221
58222
58223 public function writeln($messages, $options = self::OUTPUT_NORMAL)
58224 {
58225 $this->write($messages, true, $options);
58226 }
58227
58228
58229
58230
58231 public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
58232 {
58233 $messages = (array) $messages;
58234
58235 $types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN;
58236 $type = $types & $options ?: self::OUTPUT_NORMAL;
58237
58238 $verbosities = self::VERBOSITY_QUIET | self::VERBOSITY_NORMAL | self::VERBOSITY_VERBOSE | self::VERBOSITY_VERY_VERBOSE | self::VERBOSITY_DEBUG;
58239 $verbosity = $verbosities & $options ?: self::VERBOSITY_NORMAL;
58240
58241 if ($verbosity > $this->getVerbosity()) {
58242 return;
58243 }
58244
58245 foreach ($messages as $message) {
58246 switch ($type) {
58247 case OutputInterface::OUTPUT_NORMAL:
58248 $message = $this->formatter->format($message);
58249 break;
58250 case OutputInterface::OUTPUT_RAW:
58251 break;
58252 case OutputInterface::OUTPUT_PLAIN:
58253 $message = strip_tags($this->formatter->format($message));
58254 break;
58255 }
58256
58257 $this->doWrite($message, $newline);
58258 }
58259 }
58260
58261
58262
58263
58264
58265
58266
58267 abstract protected function doWrite($message, $newline);
58268 }
58269 <?php
58270
58271
58272
58273
58274
58275
58276
58277
58278
58279
58280 namespace Symfony\Component\Console\Output;
58281
58282 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
58283
58284
58285
58286
58287
58288
58289 interface OutputInterface
58290 {
58291 const VERBOSITY_QUIET = 16;
58292 const VERBOSITY_NORMAL = 32;
58293 const VERBOSITY_VERBOSE = 64;
58294 const VERBOSITY_VERY_VERBOSE = 128;
58295 const VERBOSITY_DEBUG = 256;
58296
58297 const OUTPUT_NORMAL = 1;
58298 const OUTPUT_RAW = 2;
58299 const OUTPUT_PLAIN = 4;
58300
58301
58302
58303
58304
58305
58306
58307
58308 public function write($messages, $newline = false, $options = 0);
58309
58310
58311
58312
58313
58314
58315
58316 public function writeln($messages, $options = 0);
58317
58318
58319
58320
58321
58322
58323 public function setVerbosity($level);
58324
58325
58326
58327
58328
58329
58330 public function getVerbosity();
58331
58332
58333
58334
58335
58336
58337 public function setDecorated($decorated);
58338
58339
58340
58341
58342
58343
58344 public function isDecorated();
58345
58346
58347
58348
58349
58350
58351 public function setFormatter(OutputFormatterInterface $formatter);
58352
58353
58354
58355
58356
58357
58358 public function getFormatter();
58359 }
58360 <?php
58361
58362
58363
58364
58365
58366
58367
58368
58369
58370
58371 namespace Symfony\Component\Console\Output;
58372
58373 use Symfony\Component\Console\Exception\InvalidArgumentException;
58374 use Symfony\Component\Console\Exception\RuntimeException;
58375 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
58376
58377
58378
58379
58380
58381
58382
58383
58384
58385
58386
58387
58388
58389
58390 class StreamOutput extends Output
58391 {
58392 private $stream;
58393
58394
58395
58396
58397
58398
58399
58400
58401
58402
58403
58404 public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
58405 {
58406 if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) {
58407 throw new InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
58408 }
58409
58410 $this->stream = $stream;
58411
58412 if (null === $decorated) {
58413 $decorated = $this->hasColorSupport();
58414 }
58415
58416 parent::__construct($verbosity, $decorated, $formatter);
58417 }
58418
58419
58420
58421
58422
58423
58424 public function getStream()
58425 {
58426 return $this->stream;
58427 }
58428
58429
58430
58431
58432 protected function doWrite($message, $newline)
58433 {
58434 if (false === @fwrite($this->stream, $message) || ($newline && (false === @fwrite($this->stream, PHP_EOL)))) {
58435
58436  throw new RuntimeException('Unable to write output.');
58437 }
58438
58439 fflush($this->stream);
58440 }
58441
58442
58443
58444
58445
58446
58447
58448
58449
58450
58451
58452 protected function hasColorSupport()
58453 {
58454 if (DIRECTORY_SEPARATOR === '\\') {
58455 return
58456 '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD
58457 || false !== getenv('ANSICON')
58458 || 'ON' === getenv('ConEmuANSI')
58459 || 'xterm' === getenv('TERM');
58460 }
58461
58462 return function_exists('posix_isatty') && @posix_isatty($this->stream);
58463 }
58464 }
58465 <?php
58466
58467
58468
58469
58470
58471
58472
58473
58474
58475
58476 namespace Symfony\Component\Console\Question;
58477
58478 use Symfony\Component\Console\Exception\InvalidArgumentException;
58479
58480
58481
58482
58483
58484
58485 class ChoiceQuestion extends Question
58486 {
58487 private $choices;
58488 private $multiselect = false;
58489 private $prompt = ' > ';
58490 private $errorMessage = 'Value "%s" is invalid';
58491
58492
58493
58494
58495
58496
58497
58498
58499 public function __construct($question, array $choices, $default = null)
58500 {
58501 if (!$choices) {
58502 throw new \LogicException('Choice question must have at least 1 choice available.');
58503 }
58504
58505 parent::__construct($question, $default);
58506
58507 $this->choices = $choices;
58508 $this->setValidator($this->getDefaultValidator());
58509 $this->setAutocompleterValues($choices);
58510 }
58511
58512
58513
58514
58515
58516
58517 public function getChoices()
58518 {
58519 return $this->choices;
58520 }
58521
58522
58523
58524
58525
58526
58527
58528
58529
58530
58531 public function setMultiselect($multiselect)
58532 {
58533 $this->multiselect = $multiselect;
58534 $this->setValidator($this->getDefaultValidator());
58535
58536 return $this;
58537 }
58538
58539
58540
58541
58542
58543
58544 public function isMultiselect()
58545 {
58546 return $this->multiselect;
58547 }
58548
58549
58550
58551
58552
58553
58554 public function getPrompt()
58555 {
58556 return $this->prompt;
58557 }
58558
58559
58560
58561
58562
58563
58564
58565
58566 public function setPrompt($prompt)
58567 {
58568 $this->prompt = $prompt;
58569
58570 return $this;
58571 }
58572
58573
58574
58575
58576
58577
58578
58579
58580
58581
58582 public function setErrorMessage($errorMessage)
58583 {
58584 $this->errorMessage = $errorMessage;
58585 $this->setValidator($this->getDefaultValidator());
58586
58587 return $this;
58588 }
58589
58590
58591
58592
58593
58594
58595 private function getDefaultValidator()
58596 {
58597 $choices = $this->choices;
58598 $errorMessage = $this->errorMessage;
58599 $multiselect = $this->multiselect;
58600 $isAssoc = $this->isAssoc($choices);
58601
58602 return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) {
58603
58604  $selectedChoices = str_replace(' ', '', $selected);
58605
58606 if ($multiselect) {
58607
58608  if (!preg_match('/^[^,]+(?:,[^,]+)*$/', $selectedChoices, $matches)) {
58609 throw new InvalidArgumentException(sprintf($errorMessage, $selected));
58610 }
58611 $selectedChoices = explode(',', $selectedChoices);
58612 } else {
58613 $selectedChoices = array($selected);
58614 }
58615
58616 $multiselectChoices = array();
58617 foreach ($selectedChoices as $value) {
58618 $results = array();
58619 foreach ($choices as $key => $choice) {
58620 if ($choice === $value) {
58621 $results[] = $key;
58622 }
58623 }
58624
58625 if (count($results) > 1) {
58626 throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of %s.', implode(' or ', $results)));
58627 }
58628
58629 $result = array_search($value, $choices);
58630
58631 if (!$isAssoc) {
58632 if (false !== $result) {
58633 $result = $choices[$result];
58634 } elseif (isset($choices[$value])) {
58635 $result = $choices[$value];
58636 }
58637 } elseif (false === $result && isset($choices[$value])) {
58638 $result = $value;
58639 }
58640
58641 if (false === $result) {
58642 throw new InvalidArgumentException(sprintf($errorMessage, $value));
58643 }
58644
58645 $multiselectChoices[] = (string) $result;
58646 }
58647
58648 if ($multiselect) {
58649 return $multiselectChoices;
58650 }
58651
58652 return current($multiselectChoices);
58653 };
58654 }
58655 }
58656 <?php
58657
58658
58659
58660
58661
58662
58663
58664
58665
58666
58667 namespace Symfony\Component\Console\Question;
58668
58669
58670
58671
58672
58673
58674 class ConfirmationQuestion extends Question
58675 {
58676 private $trueAnswerRegex;
58677
58678
58679
58680
58681
58682
58683
58684
58685 public function __construct($question, $default = true, $trueAnswerRegex = '/^y/i')
58686 {
58687 parent::__construct($question, (bool) $default);
58688
58689 $this->trueAnswerRegex = $trueAnswerRegex;
58690 $this->setNormalizer($this->getDefaultNormalizer());
58691 }
58692
58693
58694
58695
58696
58697
58698 private function getDefaultNormalizer()
58699 {
58700 $default = $this->getDefault();
58701 $regex = $this->trueAnswerRegex;
58702
58703 return function ($answer) use ($default, $regex) {
58704 if (is_bool($answer)) {
58705 return $answer;
58706 }
58707
58708 $answerIsTrue = (bool) preg_match($regex, $answer);
58709 if (false === $default) {
58710 return $answer && $answerIsTrue;
58711 }
58712
58713 return !$answer || $answerIsTrue;
58714 };
58715 }
58716 }
58717 <?php
58718
58719
58720
58721
58722
58723
58724
58725
58726
58727
58728 namespace Symfony\Component\Console\Question;
58729
58730 use Symfony\Component\Console\Exception\InvalidArgumentException;
58731 use Symfony\Component\Console\Exception\LogicException;
58732
58733
58734
58735
58736
58737
58738 class Question
58739 {
58740 private $question;
58741 private $attempts;
58742 private $hidden = false;
58743 private $hiddenFallback = true;
58744 private $autocompleterValues;
58745 private $validator;
58746 private $default;
58747 private $normalizer;
58748
58749
58750
58751
58752
58753
58754
58755 public function __construct($question, $default = null)
58756 {
58757 $this->question = $question;
58758 $this->default = $default;
58759 }
58760
58761
58762
58763
58764
58765
58766 public function getQuestion()
58767 {
58768 return $this->question;
58769 }
58770
58771
58772
58773
58774
58775
58776 public function getDefault()
58777 {
58778 return $this->default;
58779 }
58780
58781
58782
58783
58784
58785
58786 public function isHidden()
58787 {
58788 return $this->hidden;
58789 }
58790
58791
58792
58793
58794
58795
58796
58797
58798
58799
58800 public function setHidden($hidden)
58801 {
58802 if ($this->autocompleterValues) {
58803 throw new LogicException('A hidden question cannot use the autocompleter.');
58804 }
58805
58806 $this->hidden = (bool) $hidden;
58807
58808 return $this;
58809 }
58810
58811
58812
58813
58814
58815
58816 public function isHiddenFallback()
58817 {
58818 return $this->hiddenFallback;
58819 }
58820
58821
58822
58823
58824
58825
58826
58827
58828 public function setHiddenFallback($fallback)
58829 {
58830 $this->hiddenFallback = (bool) $fallback;
58831
58832 return $this;
58833 }
58834
58835
58836
58837
58838
58839
58840 public function getAutocompleterValues()
58841 {
58842 return $this->autocompleterValues;
58843 }
58844
58845
58846
58847
58848
58849
58850
58851
58852
58853
58854
58855 public function setAutocompleterValues($values)
58856 {
58857 if (is_array($values)) {
58858 $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values);
58859 }
58860
58861 if (null !== $values && !is_array($values)) {
58862 if (!$values instanceof \Traversable || !$values instanceof \Countable) {
58863 throw new InvalidArgumentException('Autocompleter values can be either an array, `null` or an object implementing both `Countable` and `Traversable` interfaces.');
58864 }
58865 }
58866
58867 if ($this->hidden) {
58868 throw new LogicException('A hidden question cannot use the autocompleter.');
58869 }
58870
58871 $this->autocompleterValues = $values;
58872
58873 return $this;
58874 }
58875
58876
58877
58878
58879
58880
58881
58882
58883 public function setValidator($validator)
58884 {
58885 $this->validator = $validator;
58886
58887 return $this;
58888 }
58889
58890
58891
58892
58893
58894
58895 public function getValidator()
58896 {
58897 return $this->validator;
58898 }
58899
58900
58901
58902
58903
58904
58905
58906
58907
58908
58909
58910
58911 public function setMaxAttempts($attempts)
58912 {
58913 if (null !== $attempts && $attempts < 1) {
58914 throw new InvalidArgumentException('Maximum number of attempts must be a positive value.');
58915 }
58916
58917 $this->attempts = $attempts;
58918
58919 return $this;
58920 }
58921
58922
58923
58924
58925
58926
58927
58928
58929 public function getMaxAttempts()
58930 {
58931 return $this->attempts;
58932 }
58933
58934
58935
58936
58937
58938
58939
58940
58941
58942
58943 public function setNormalizer($normalizer)
58944 {
58945 $this->normalizer = $normalizer;
58946
58947 return $this;
58948 }
58949
58950
58951
58952
58953
58954
58955
58956
58957 public function getNormalizer()
58958 {
58959 return $this->normalizer;
58960 }
58961
58962 protected function isAssoc($array)
58963 {
58964 return (bool) count(array_filter(array_keys($array), 'is_string'));
58965 }
58966 }
58967 <?php
58968
58969
58970
58971
58972
58973
58974
58975
58976
58977
58978 namespace Symfony\Component\Console;
58979
58980 use Symfony\Component\Console\Exception\RuntimeException;
58981 use Symfony\Component\Console\Input\StringInput;
58982 use Symfony\Component\Console\Output\ConsoleOutput;
58983 use Symfony\Component\Process\ProcessBuilder;
58984 use Symfony\Component\Process\PhpExecutableFinder;
58985
58986
58987
58988
58989
58990
58991
58992
58993
58994
58995
58996
58997 class Shell
58998 {
58999 private $application;
59000 private $history;
59001 private $output;
59002 private $hasReadline;
59003 private $processIsolation = false;
59004
59005
59006
59007
59008
59009
59010
59011
59012
59013 public function __construct(Application $application)
59014 {
59015 @trigger_error('The '.__CLASS__.' class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
59016
59017 $this->hasReadline = function_exists('readline');
59018 $this->application = $application;
59019 $this->history = getenv('HOME').'/.history_'.$application->getName();
59020 $this->output = new ConsoleOutput();
59021 }
59022
59023
59024
59025
59026 public function run()
59027 {
59028 $this->application->setAutoExit(false);
59029 $this->application->setCatchExceptions(true);
59030
59031 if ($this->hasReadline) {
59032 readline_read_history($this->history);
59033 readline_completion_function(array($this, 'autocompleter'));
59034 }
59035
59036 $this->output->writeln($this->getHeader());
59037 $php = null;
59038 if ($this->processIsolation) {
59039 $finder = new PhpExecutableFinder();
59040 $php = $finder->find();
59041 $this->output->writeln(<<<'EOF'
59042 <info>Running with process isolation, you should consider this:</info>
59043   * each command is executed as separate process,
59044   * commands don't support interactivity, all params must be passed explicitly,
59045   * commands output is not colorized.
59046
59047 EOF
59048 );
59049 }
59050
59051 while (true) {
59052 $command = $this->readline();
59053
59054 if (false === $command) {
59055 $this->output->writeln("\n");
59056
59057 break;
59058 }
59059
59060 if ($this->hasReadline) {
59061 readline_add_history($command);
59062 readline_write_history($this->history);
59063 }
59064
59065 if ($this->processIsolation) {
59066 $pb = new ProcessBuilder();
59067
59068 $process = $pb
59069 ->add($php)
59070 ->add($_SERVER['argv'][0])
59071 ->add($command)
59072 ->inheritEnvironmentVariables(true)
59073 ->getProcess()
59074 ;
59075
59076 $output = $this->output;
59077 $process->run(function ($type, $data) use ($output) {
59078 $output->writeln($data);
59079 });
59080
59081 $ret = $process->getExitCode();
59082 } else {
59083 $ret = $this->application->run(new StringInput($command), $this->output);
59084 }
59085
59086 if (0 !== $ret) {
59087 $this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
59088 }
59089 }
59090 }
59091
59092
59093
59094
59095
59096
59097 protected function getHeader()
59098 {
59099 return <<<EOF
59100
59101 Welcome to the <info>{$this->application->getName()}</info> shell (<comment>{$this->application->getVersion()}</comment>).
59102
59103 At the prompt, type <comment>help</comment> for some help,
59104 or <comment>list</comment> to get a list of available commands.
59105
59106 To exit the shell, type <comment>^D</comment>.
59107
59108 EOF;
59109 }
59110
59111
59112
59113
59114
59115
59116 protected function getPrompt()
59117 {
59118
59119  return $this->output->getFormatter()->format($this->application->getName().' > ');
59120 }
59121
59122 protected function getOutput()
59123 {
59124 return $this->output;
59125 }
59126
59127 protected function getApplication()
59128 {
59129 return $this->application;
59130 }
59131
59132
59133
59134
59135
59136
59137
59138
59139 private function autocompleter($text)
59140 {
59141 $info = readline_info();
59142 $text = substr($info['line_buffer'], 0, $info['end']);
59143
59144 if ($info['point'] !== $info['end']) {
59145 return true;
59146 }
59147
59148
59149  if (false === strpos($text, ' ') || !$text) {
59150 return array_keys($this->application->all());
59151 }
59152
59153
59154  try {
59155 $command = $this->application->find(substr($text, 0, strpos($text, ' ')));
59156 } catch (\Exception $e) {
59157 return true;
59158 }
59159
59160 $list = array('--help');
59161 foreach ($command->getDefinition()->getOptions() as $option) {
59162 $list[] = '--'.$option->getName();
59163 }
59164
59165 return $list;
59166 }
59167
59168
59169
59170
59171
59172
59173 private function readline()
59174 {
59175 if ($this->hasReadline) {
59176 $line = readline($this->getPrompt());
59177 } else {
59178 $this->output->write($this->getPrompt());
59179 $line = fgets(STDIN, 1024);
59180 $line = (false === $line || '' === $line) ? false : rtrim($line);
59181 }
59182
59183 return $line;
59184 }
59185
59186 public function getProcessIsolation()
59187 {
59188 return $this->processIsolation;
59189 }
59190
59191 public function setProcessIsolation($processIsolation)
59192 {
59193 $this->processIsolation = (bool) $processIsolation;
59194
59195 if ($this->processIsolation && !class_exists('Symfony\\Component\\Process\\Process')) {
59196 throw new RuntimeException('Unable to isolate processes as the Symfony Process Component is not installed.');
59197 }
59198 }
59199 }
59200 <?php
59201
59202
59203
59204
59205
59206
59207
59208
59209
59210
59211 namespace Symfony\Component\Console\Style;
59212
59213 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
59214 use Symfony\Component\Console\Helper\ProgressBar;
59215 use Symfony\Component\Console\Output\OutputInterface;
59216
59217
59218
59219
59220
59221
59222 abstract class OutputStyle implements OutputInterface, StyleInterface
59223 {
59224 private $output;
59225
59226
59227
59228
59229 public function __construct(OutputInterface $output)
59230 {
59231 $this->output = $output;
59232 }
59233
59234
59235
59236
59237 public function newLine($count = 1)
59238 {
59239 $this->output->write(str_repeat(PHP_EOL, $count));
59240 }
59241
59242
59243
59244
59245
59246
59247 public function createProgressBar($max = 0)
59248 {
59249 return new ProgressBar($this->output, $max);
59250 }
59251
59252
59253
59254
59255 public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
59256 {
59257 $this->output->write($messages, $newline, $type);
59258 }
59259
59260
59261
59262
59263 public function writeln($messages, $type = self::OUTPUT_NORMAL)
59264 {
59265 $this->output->writeln($messages, $type);
59266 }
59267
59268
59269
59270
59271 public function setVerbosity($level)
59272 {
59273 $this->output->setVerbosity($level);
59274 }
59275
59276
59277
59278
59279 public function getVerbosity()
59280 {
59281 return $this->output->getVerbosity();
59282 }
59283
59284
59285
59286
59287 public function setDecorated($decorated)
59288 {
59289 $this->output->setDecorated($decorated);
59290 }
59291
59292
59293
59294
59295 public function isDecorated()
59296 {
59297 return $this->output->isDecorated();
59298 }
59299
59300
59301
59302
59303 public function setFormatter(OutputFormatterInterface $formatter)
59304 {
59305 $this->output->setFormatter($formatter);
59306 }
59307
59308
59309
59310
59311 public function getFormatter()
59312 {
59313 return $this->output->getFormatter();
59314 }
59315 }
59316 <?php
59317
59318
59319
59320
59321
59322
59323
59324
59325
59326
59327 namespace Symfony\Component\Console\Style;
59328
59329
59330
59331
59332
59333
59334 interface StyleInterface
59335 {
59336
59337
59338
59339
59340
59341 public function title($message);
59342
59343
59344
59345
59346
59347
59348 public function section($message);
59349
59350
59351
59352
59353
59354
59355 public function listing(array $elements);
59356
59357
59358
59359
59360
59361
59362 public function text($message);
59363
59364
59365
59366
59367
59368
59369 public function success($message);
59370
59371
59372
59373
59374
59375
59376 public function error($message);
59377
59378
59379
59380
59381
59382
59383 public function warning($message);
59384
59385
59386
59387
59388
59389
59390 public function note($message);
59391
59392
59393
59394
59395
59396
59397 public function caution($message);
59398
59399
59400
59401
59402
59403
59404
59405 public function table(array $headers, array $rows);
59406
59407
59408
59409
59410
59411
59412
59413
59414
59415
59416 public function ask($question, $default = null, $validator = null);
59417
59418
59419
59420
59421
59422
59423
59424
59425
59426 public function askHidden($question, $validator = null);
59427
59428
59429
59430
59431
59432
59433
59434
59435
59436 public function confirm($question, $default = true);
59437
59438
59439
59440
59441
59442
59443
59444
59445
59446
59447 public function choice($question, array $choices, $default = null);
59448
59449
59450
59451
59452
59453
59454 public function newLine($count = 1);
59455
59456
59457
59458
59459
59460
59461 public function progressStart($max = 0);
59462
59463
59464
59465
59466
59467
59468 public function progressAdvance($step = 1);
59469
59470
59471
59472
59473 public function progressFinish();
59474 }
59475 <?php
59476
59477
59478
59479
59480
59481
59482
59483
59484
59485
59486 namespace Symfony\Component\Console\Style;
59487
59488 use Symfony\Component\Console\Application;
59489 use Symfony\Component\Console\Exception\RuntimeException;
59490 use Symfony\Component\Console\Formatter\OutputFormatter;
59491 use Symfony\Component\Console\Helper\Helper;
59492 use Symfony\Component\Console\Helper\ProgressBar;
59493 use Symfony\Component\Console\Helper\SymfonyQuestionHelper;
59494 use Symfony\Component\Console\Helper\Table;
59495 use Symfony\Component\Console\Input\InputInterface;
59496 use Symfony\Component\Console\Output\BufferedOutput;
59497 use Symfony\Component\Console\Output\OutputInterface;
59498 use Symfony\Component\Console\Question\ChoiceQuestion;
59499 use Symfony\Component\Console\Question\ConfirmationQuestion;
59500 use Symfony\Component\Console\Question\Question;
59501
59502
59503
59504
59505
59506
59507 class SymfonyStyle extends OutputStyle
59508 {
59509 const MAX_LINE_LENGTH = 120;
59510
59511 private $input;
59512 private $questionHelper;
59513 private $progressBar;
59514 private $lineLength;
59515 private $bufferedOutput;
59516
59517
59518
59519
59520
59521 public function __construct(InputInterface $input, OutputInterface $output)
59522 {
59523 $this->input = $input;
59524 $this->bufferedOutput = new BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter());
59525
59526  $this->lineLength = min($this->getTerminalWidth() - (int) (DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);
59527
59528 parent::__construct($output);
59529 }
59530
59531
59532
59533
59534
59535
59536
59537
59538
59539
59540 public function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false)
59541 {
59542 $messages = is_array($messages) ? array_values($messages) : array($messages);
59543
59544 $this->autoPrependBlock();
59545 $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, true));
59546 $this->newLine();
59547 }
59548
59549
59550
59551
59552 public function title($message)
59553 {
59554 $this->autoPrependBlock();
59555 $this->writeln(array(
59556 sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
59557 sprintf('<comment>%s</>', str_repeat('=', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
59558 ));
59559 $this->newLine();
59560 }
59561
59562
59563
59564
59565 public function section($message)
59566 {
59567 $this->autoPrependBlock();
59568 $this->writeln(array(
59569 sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
59570 sprintf('<comment>%s</>', str_repeat('-', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
59571 ));
59572 $this->newLine();
59573 }
59574
59575
59576
59577
59578 public function listing(array $elements)
59579 {
59580 $this->autoPrependText();
59581 $elements = array_map(function ($element) {
59582 return sprintf(' * %s', $element);
59583 }, $elements);
59584
59585 $this->writeln($elements);
59586 $this->newLine();
59587 }
59588
59589
59590
59591
59592 public function text($message)
59593 {
59594 $this->autoPrependText();
59595
59596 $messages = is_array($message) ? array_values($message) : array($message);
59597 foreach ($messages as $message) {
59598 $this->writeln(sprintf(' %s', $message));
59599 }
59600 }
59601
59602
59603
59604
59605
59606
59607 public function comment($message)
59608 {
59609 $messages = is_array($message) ? array_values($message) : array($message);
59610
59611 $this->autoPrependBlock();
59612 $this->writeln($this->createBlock($messages, null, null, '<fg=default;bg=default> // </>'));
59613 $this->newLine();
59614 }
59615
59616
59617
59618
59619 public function success($message)
59620 {
59621 $this->block($message, 'OK', 'fg=black;bg=green', ' ', true);
59622 }
59623
59624
59625
59626
59627 public function error($message)
59628 {
59629 $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', true);
59630 }
59631
59632
59633
59634
59635 public function warning($message)
59636 {
59637 $this->block($message, 'WARNING', 'fg=white;bg=red', ' ', true);
59638 }
59639
59640
59641
59642
59643 public function note($message)
59644 {
59645 $this->block($message, 'NOTE', 'fg=yellow', ' ! ');
59646 }
59647
59648
59649
59650
59651 public function caution($message)
59652 {
59653 $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', true);
59654 }
59655
59656
59657
59658
59659 public function table(array $headers, array $rows)
59660 {
59661 $style = clone Table::getStyleDefinition('symfony-style-guide');
59662 $style->setCellHeaderFormat('<info>%s</info>');
59663
59664 $table = new Table($this);
59665 $table->setHeaders($headers);
59666 $table->setRows($rows);
59667 $table->setStyle($style);
59668
59669 $table->render();
59670 $this->newLine();
59671 }
59672
59673
59674
59675
59676 public function ask($question, $default = null, $validator = null)
59677 {
59678 $question = new Question($question, $default);
59679 $question->setValidator($validator);
59680
59681 return $this->askQuestion($question);
59682 }
59683
59684
59685
59686
59687 public function askHidden($question, $validator = null)
59688 {
59689 $question = new Question($question);
59690
59691 $question->setHidden(true);
59692 $question->setValidator($validator);
59693
59694 return $this->askQuestion($question);
59695 }
59696
59697
59698
59699
59700 public function confirm($question, $default = true)
59701 {
59702 return $this->askQuestion(new ConfirmationQuestion($question, $default));
59703 }
59704
59705
59706
59707
59708 public function choice($question, array $choices, $default = null)
59709 {
59710 if (null !== $default) {
59711 $values = array_flip($choices);
59712 $default = $values[$default];
59713 }
59714
59715 return $this->askQuestion(new ChoiceQuestion($question, $choices, $default));
59716 }
59717
59718
59719
59720
59721 public function progressStart($max = 0)
59722 {
59723 $this->progressBar = $this->createProgressBar($max);
59724 $this->progressBar->start();
59725 }
59726
59727
59728
59729
59730 public function progressAdvance($step = 1)
59731 {
59732 $this->getProgressBar()->advance($step);
59733 }
59734
59735
59736
59737
59738 public function progressFinish()
59739 {
59740 $this->getProgressBar()->finish();
59741 $this->newLine(2);
59742 $this->progressBar = null;
59743 }
59744
59745
59746
59747
59748 public function createProgressBar($max = 0)
59749 {
59750 $progressBar = parent::createProgressBar($max);
59751
59752 if ('\\' !== DIRECTORY_SEPARATOR) {
59753 $progressBar->setEmptyBarCharacter('░'); 
59754  $progressBar->setProgressCharacter('');
59755 $progressBar->setBarCharacter('▓'); 
59756  }
59757
59758 return $progressBar;
59759 }
59760
59761
59762
59763
59764
59765
59766 public function askQuestion(Question $question)
59767 {
59768 if ($this->input->isInteractive()) {
59769 $this->autoPrependBlock();
59770 }
59771
59772 if (!$this->questionHelper) {
59773 $this->questionHelper = new SymfonyQuestionHelper();
59774 }
59775
59776 $answer = $this->questionHelper->ask($this->input, $this, $question);
59777
59778 if ($this->input->isInteractive()) {
59779 $this->newLine();
59780 $this->bufferedOutput->write("\n");
59781 }
59782
59783 return $answer;
59784 }
59785
59786
59787
59788
59789 public function writeln($messages, $type = self::OUTPUT_NORMAL)
59790 {
59791 parent::writeln($messages, $type);
59792 $this->bufferedOutput->writeln($this->reduceBuffer($messages), $type);
59793 }
59794
59795
59796
59797
59798 public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
59799 {
59800 parent::write($messages, $newline, $type);
59801 $this->bufferedOutput->write($this->reduceBuffer($messages), $newline, $type);
59802 }
59803
59804
59805
59806
59807 public function newLine($count = 1)
59808 {
59809 parent::newLine($count);
59810 $this->bufferedOutput->write(str_repeat("\n", $count));
59811 }
59812
59813
59814
59815
59816 private function getProgressBar()
59817 {
59818 if (!$this->progressBar) {
59819 throw new RuntimeException('The ProgressBar is not started.');
59820 }
59821
59822 return $this->progressBar;
59823 }
59824
59825 private function getTerminalWidth()
59826 {
59827 $application = new Application();
59828 $dimensions = $application->getTerminalDimensions();
59829
59830 return $dimensions[0] ?: self::MAX_LINE_LENGTH;
59831 }
59832
59833 private function autoPrependBlock()
59834 {
59835 $chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);
59836
59837 if (!isset($chars[0])) {
59838 return $this->newLine(); 
59839  }
59840
59841  $this->newLine(2 - substr_count($chars, "\n"));
59842 }
59843
59844 private function autoPrependText()
59845 {
59846 $fetched = $this->bufferedOutput->fetch();
59847
59848  if ("\n" !== substr($fetched, -1)) {
59849 $this->newLine();
59850 }
59851 }
59852
59853 private function reduceBuffer($messages)
59854 {
59855
59856  
59857  return array_map(function ($value) {
59858 return substr($value, -4);
59859 }, array_merge(array($this->bufferedOutput->fetch()), (array) $messages));
59860 }
59861
59862 private function createBlock($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = false)
59863 {
59864 $indentLength = 0;
59865 $prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(), $prefix);
59866 $lines = array();
59867
59868 if (null !== $type) {
59869 $type = sprintf('[%s] ', $type);
59870 $indentLength = strlen($type);
59871 $lineIndentation = str_repeat(' ', $indentLength);
59872 }
59873
59874
59875  foreach ($messages as $key => $message) {
59876 if ($escape) {
59877 $message = OutputFormatter::escape($message);
59878 }
59879
59880 $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL, true)));
59881
59882 if (count($messages) > 1 && $key < count($messages) - 1) {
59883 $lines[] = '';
59884 }
59885 }
59886
59887 $firstLineIndex = 0;
59888 if ($padding && $this->isDecorated()) {
59889 $firstLineIndex = 1;
59890 array_unshift($lines, '');
59891 $lines[] = '';
59892 }
59893
59894 foreach ($lines as $i => &$line) {
59895 if (null !== $type) {
59896 $line = $firstLineIndex === $i ? $type.$line : $lineIndentation.$line;
59897 }
59898
59899 $line = $prefix.$line;
59900 $line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line));
59901
59902 if ($style) {
59903 $line = sprintf('<%s>%s</>', $style, $line);
59904 }
59905 }
59906
59907 return $lines;
59908 }
59909 }
59910 <?php
59911
59912
59913
59914
59915
59916
59917
59918
59919
59920
59921 namespace Symfony\Component\Console\Tester;
59922
59923 use Symfony\Component\Console\Application;
59924 use Symfony\Component\Console\Input\ArrayInput;
59925 use Symfony\Component\Console\Input\InputInterface;
59926 use Symfony\Component\Console\Output\OutputInterface;
59927 use Symfony\Component\Console\Output\StreamOutput;
59928
59929
59930
59931
59932
59933
59934
59935
59936
59937
59938
59939 class ApplicationTester
59940 {
59941 private $application;
59942 private $input;
59943 private $output;
59944 private $statusCode;
59945
59946
59947
59948
59949
59950
59951 public function __construct(Application $application)
59952 {
59953 $this->application = $application;
59954 }
59955
59956
59957
59958
59959
59960
59961
59962
59963
59964
59965
59966
59967
59968
59969
59970 public function run(array $input, $options = array())
59971 {
59972 $this->input = new ArrayInput($input);
59973 if (isset($options['interactive'])) {
59974 $this->input->setInteractive($options['interactive']);
59975 }
59976
59977 $this->output = new StreamOutput(fopen('php://memory', 'w', false));
59978 if (isset($options['decorated'])) {
59979 $this->output->setDecorated($options['decorated']);
59980 }
59981 if (isset($options['verbosity'])) {
59982 $this->output->setVerbosity($options['verbosity']);
59983 }
59984
59985 return $this->statusCode = $this->application->run($this->input, $this->output);
59986 }
59987
59988
59989
59990
59991
59992
59993
59994
59995 public function getDisplay($normalize = false)
59996 {
59997 rewind($this->output->getStream());
59998
59999 $display = stream_get_contents($this->output->getStream());
60000
60001 if ($normalize) {
60002 $display = str_replace(PHP_EOL, "\n", $display);
60003 }
60004
60005 return $display;
60006 }
60007
60008
60009
60010
60011
60012
60013 public function getInput()
60014 {
60015 return $this->input;
60016 }
60017
60018
60019
60020
60021
60022
60023 public function getOutput()
60024 {
60025 return $this->output;
60026 }
60027
60028
60029
60030
60031
60032
60033 public function getStatusCode()
60034 {
60035 return $this->statusCode;
60036 }
60037 }
60038 <?php
60039
60040
60041
60042
60043
60044
60045
60046
60047
60048
60049 namespace Symfony\Component\Console\Tester;
60050
60051 use Symfony\Component\Console\Command\Command;
60052 use Symfony\Component\Console\Input\ArrayInput;
60053 use Symfony\Component\Console\Output\StreamOutput;
60054 use Symfony\Component\Console\Input\InputInterface;
60055 use Symfony\Component\Console\Output\OutputInterface;
60056
60057
60058
60059
60060
60061
60062 class CommandTester
60063 {
60064 private $command;
60065 private $input;
60066 private $output;
60067 private $statusCode;
60068
60069
60070
60071
60072
60073
60074 public function __construct(Command $command)
60075 {
60076 $this->command = $command;
60077 }
60078
60079
60080
60081
60082
60083
60084
60085
60086
60087
60088
60089
60090
60091
60092
60093 public function execute(array $input, array $options = array())
60094 {
60095
60096  
60097  if (!isset($input['command'])
60098 && (null !== $application = $this->command->getApplication())
60099 && $application->getDefinition()->hasArgument('command')
60100 ) {
60101 $input = array_merge(array('command' => $this->command->getName()), $input);
60102 }
60103
60104 $this->input = new ArrayInput($input);
60105 if (isset($options['interactive'])) {
60106 $this->input->setInteractive($options['interactive']);
60107 }
60108
60109 $this->output = new StreamOutput(fopen('php://memory', 'w', false));
60110 $this->output->setDecorated(isset($options['decorated']) ? $options['decorated'] : false);
60111 if (isset($options['verbosity'])) {
60112 $this->output->setVerbosity($options['verbosity']);
60113 }
60114
60115 return $this->statusCode = $this->command->run($this->input, $this->output);
60116 }
60117
60118
60119
60120
60121
60122
60123
60124
60125 public function getDisplay($normalize = false)
60126 {
60127 rewind($this->output->getStream());
60128
60129 $display = stream_get_contents($this->output->getStream());
60130
60131 if ($normalize) {
60132 $display = str_replace(PHP_EOL, "\n", $display);
60133 }
60134
60135 return $display;
60136 }
60137
60138
60139
60140
60141
60142
60143 public function getInput()
60144 {
60145 return $this->input;
60146 }
60147
60148
60149
60150
60151
60152
60153 public function getOutput()
60154 {
60155 return $this->output;
60156 }
60157
60158
60159
60160
60161
60162
60163 public function getStatusCode()
60164 {
60165 return $this->statusCode;
60166 }
60167 }
60168 <?php
60169
60170
60171
60172
60173
60174
60175
60176
60177
60178
60179 namespace Symfony\Component\Debug;
60180
60181 use Psr\Log\AbstractLogger;
60182
60183
60184
60185
60186
60187
60188 class BufferingLogger extends AbstractLogger
60189 {
60190 private $logs = array();
60191
60192 public function log($level, $message, array $context = array())
60193 {
60194 $this->logs[] = array($level, $message, $context);
60195 }
60196
60197 public function cleanLogs()
60198 {
60199 $logs = $this->logs;
60200 $this->logs = array();
60201
60202 return $logs;
60203 }
60204 }
60205 <?php
60206
60207
60208
60209
60210
60211
60212
60213
60214
60215
60216 namespace Symfony\Component\Debug;
60217
60218
60219
60220
60221
60222
60223 class Debug
60224 {
60225 private static $enabled = false;
60226
60227
60228
60229
60230
60231
60232
60233
60234
60235
60236
60237
60238 public static function enable($errorReportingLevel = null, $displayErrors = true)
60239 {
60240 if (static::$enabled) {
60241 return;
60242 }
60243
60244 static::$enabled = true;
60245
60246 if (null !== $errorReportingLevel) {
60247 error_reporting($errorReportingLevel);
60248 } else {
60249 error_reporting(-1);
60250 }
60251
60252 if ('cli' !== PHP_SAPI) {
60253 ini_set('display_errors', 0);
60254 ExceptionHandler::register();
60255 } elseif ($displayErrors && (!ini_get('log_errors') || ini_get('error_log'))) {
60256
60257  ini_set('display_errors', 1);
60258 }
60259 if ($displayErrors) {
60260 ErrorHandler::register(new ErrorHandler(new BufferingLogger()));
60261 } else {
60262 ErrorHandler::register()->throwAt(0, true);
60263 }
60264
60265 DebugClassLoader::enable();
60266 }
60267 }
60268 <?php
60269
60270
60271
60272
60273
60274
60275
60276
60277
60278
60279 namespace Symfony\Component\Debug;
60280
60281
60282
60283
60284
60285
60286
60287
60288
60289
60290
60291
60292 class DebugClassLoader
60293 {
60294 private $classLoader;
60295 private $isFinder;
60296 private $wasFinder;
60297 private static $caseCheck;
60298 private static $deprecated = array();
60299 private static $php7Reserved = array('int', 'float', 'bool', 'string', 'true', 'false', 'null');
60300 private static $darwinCache = array('/' => array('/', array()));
60301
60302
60303
60304
60305
60306
60307 public function __construct($classLoader)
60308 {
60309 $this->wasFinder = is_object($classLoader) && method_exists($classLoader, 'findFile');
60310
60311 if ($this->wasFinder) {
60312 @trigger_error('The '.__METHOD__.' method will no longer support receiving an object into its $classLoader argument in 3.0.', E_USER_DEPRECATED);
60313 $this->classLoader = array($classLoader, 'loadClass');
60314 $this->isFinder = true;
60315 } else {
60316 $this->classLoader = $classLoader;
60317 $this->isFinder = is_array($classLoader) && method_exists($classLoader[0], 'findFile');
60318 }
60319
60320 if (!isset(self::$caseCheck)) {
60321 $file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), DIRECTORY_SEPARATOR);
60322 $i = strrpos($file, DIRECTORY_SEPARATOR);
60323 $dir = substr($file, 0, 1 + $i);
60324 $file = substr($file, 1 + $i);
60325 $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file);
60326 $test = realpath($dir.$test);
60327
60328 if (false === $test || false === $i) {
60329
60330  self::$caseCheck = 0;
60331 } elseif (substr($test, -strlen($file)) === $file) {
60332
60333  self::$caseCheck = 1;
60334 } elseif (false !== stripos(PHP_OS, 'darwin')) {
60335
60336  self::$caseCheck = 2;
60337 } else {
60338
60339  self::$caseCheck = 0;
60340 }
60341 }
60342 }
60343
60344
60345
60346
60347
60348
60349 public function getClassLoader()
60350 {
60351 return $this->wasFinder ? $this->classLoader[0] : $this->classLoader;
60352 }
60353
60354
60355
60356
60357 public static function enable()
60358 {
60359
60360  class_exists('Symfony\Component\Debug\ErrorHandler');
60361 class_exists('Psr\Log\LogLevel');
60362
60363 if (!is_array($functions = spl_autoload_functions())) {
60364 return;
60365 }
60366
60367 foreach ($functions as $function) {
60368 spl_autoload_unregister($function);
60369 }
60370
60371 foreach ($functions as $function) {
60372 if (!is_array($function) || !$function[0] instanceof self) {
60373 $function = array(new static($function), 'loadClass');
60374 }
60375
60376 spl_autoload_register($function);
60377 }
60378 }
60379
60380
60381
60382
60383 public static function disable()
60384 {
60385 if (!is_array($functions = spl_autoload_functions())) {
60386 return;
60387 }
60388
60389 foreach ($functions as $function) {
60390 spl_autoload_unregister($function);
60391 }
60392
60393 foreach ($functions as $function) {
60394 if (is_array($function) && $function[0] instanceof self) {
60395 $function = $function[0]->getClassLoader();
60396 }
60397
60398 spl_autoload_register($function);
60399 }
60400 }
60401
60402
60403
60404
60405
60406
60407
60408
60409
60410
60411 public function findFile($class)
60412 {
60413 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
60414
60415 if ($this->wasFinder) {
60416 return $this->classLoader[0]->findFile($class);
60417 }
60418 }
60419
60420
60421
60422
60423
60424
60425
60426
60427
60428
60429 public function loadClass($class)
60430 {
60431 ErrorHandler::stackErrors();
60432
60433 try {
60434 if ($this->isFinder) {
60435 if ($file = $this->classLoader[0]->findFile($class)) {
60436 require_once $file;
60437 }
60438 } else {
60439 call_user_func($this->classLoader, $class);
60440 $file = false;
60441 }
60442 } catch (\Exception $e) {
60443 ErrorHandler::unstackErrors();
60444
60445 throw $e;
60446 } catch (\Throwable $e) {
60447 ErrorHandler::unstackErrors();
60448
60449 throw $e;
60450 }
60451
60452 ErrorHandler::unstackErrors();
60453
60454 $exists = class_exists($class, false) || interface_exists($class, false) || (function_exists('trait_exists') && trait_exists($class, false));
60455
60456 if ($class && '\\' === $class[0]) {
60457 $class = substr($class, 1);
60458 }
60459
60460 if ($exists) {
60461 $refl = new \ReflectionClass($class);
60462 $name = $refl->getName();
60463
60464 if ($name !== $class && 0 === strcasecmp($name, $class)) {
60465 throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: %s vs %s', $class, $name));
60466 }
60467
60468 if (in_array(strtolower($refl->getShortName()), self::$php7Reserved)) {
60469 @trigger_error(sprintf('%s uses a reserved class name (%s) that will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED);
60470 } elseif (preg_match('#\n \* @deprecated (.*?)\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) {
60471 self::$deprecated[$name] = preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]);
60472 } else {
60473 if (2 > $len = 1 + (strpos($name, '\\', 1 + strpos($name, '\\')) ?: strpos($name, '_'))) {
60474 $len = 0;
60475 $ns = '';
60476 } else {
60477 switch ($ns = substr($name, 0, $len)) {
60478 case 'Symfony\Bridge\\':
60479 case 'Symfony\Bundle\\':
60480 case 'Symfony\Component\\':
60481 $ns = 'Symfony\\';
60482 $len = strlen($ns);
60483 break;
60484 }
60485 }
60486 $parent = get_parent_class($class);
60487
60488 if (!$parent || strncmp($ns, $parent, $len)) {
60489 if ($parent && isset(self::$deprecated[$parent]) && strncmp($ns, $parent, $len)) {
60490 @trigger_error(sprintf('The %s class extends %s that is deprecated %s', $name, $parent, self::$deprecated[$parent]), E_USER_DEPRECATED);
60491 }
60492
60493 $parentInterfaces = array();
60494 $deprecatedInterfaces = array();
60495 if ($parent) {
60496 foreach (class_implements($parent) as $interface) {
60497 $parentInterfaces[$interface] = 1;
60498 }
60499 }
60500
60501 foreach ($refl->getInterfaceNames() as $interface) {
60502 if (isset(self::$deprecated[$interface]) && strncmp($ns, $interface, $len)) {
60503 $deprecatedInterfaces[] = $interface;
60504 }
60505 foreach (class_implements($interface) as $interface) {
60506 $parentInterfaces[$interface] = 1;
60507 }
60508 }
60509
60510 foreach ($deprecatedInterfaces as $interface) {
60511 if (!isset($parentInterfaces[$interface])) {
60512 @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);
60513 }
60514 }
60515 }
60516 }
60517 }
60518
60519 if ($file) {
60520 if (!$exists) {
60521 if (false !== strpos($class, '/')) {
60522 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));
60523 }
60524
60525 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));
60526 }
60527 if (self::$caseCheck) {
60528 $real = explode('\\', $class.strrchr($file, '.'));
60529 $tail = explode(DIRECTORY_SEPARATOR, str_replace('/', DIRECTORY_SEPARATOR, $file));
60530
60531 $i = count($tail) - 1;
60532 $j = count($real) - 1;
60533
60534 while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) {
60535 --$i;
60536 --$j;
60537 }
60538
60539 array_splice($tail, 0, $i + 1);
60540 }
60541 if (self::$caseCheck && $tail) {
60542 $tail = DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $tail);
60543 $tailLen = strlen($tail);
60544 $real = $refl->getFileName();
60545
60546 if (2 === self::$caseCheck) {
60547
60548
60549 $i = 1 + strrpos($real, '/');
60550 $file = substr($real, $i);
60551 $real = substr($real, 0, $i);
60552
60553 if (isset(self::$darwinCache[$real])) {
60554 $kDir = $real;
60555 } else {
60556 $kDir = strtolower($real);
60557
60558 if (isset(self::$darwinCache[$kDir])) {
60559 $real = self::$darwinCache[$kDir][0];
60560 } else {
60561 $dir = getcwd();
60562 chdir($real);
60563 $real = getcwd().'/';
60564 chdir($dir);
60565
60566 $dir = $real;
60567 $k = $kDir;
60568 $i = strlen($dir) - 1;
60569 while (!isset(self::$darwinCache[$k])) {
60570 self::$darwinCache[$k] = array($dir, array());
60571 self::$darwinCache[$dir] = &self::$darwinCache[$k];
60572
60573 while ('/' !== $dir[--$i]) {
60574 }
60575 $k = substr($k, 0, ++$i);
60576 $dir = substr($dir, 0, $i--);
60577 }
60578 }
60579 }
60580
60581 $dirFiles = self::$darwinCache[$kDir][1];
60582
60583 if (isset($dirFiles[$file])) {
60584 $kFile = $file;
60585 } else {
60586 $kFile = strtolower($file);
60587
60588 if (!isset($dirFiles[$kFile])) {
60589 foreach (scandir($real, 2) as $f) {
60590 if ('.' !== $f[0]) {
60591 $dirFiles[$f] = $f;
60592 if ($f === $file) {
60593 $kFile = $k = $file;
60594 } elseif ($f !== $k = strtolower($f)) {
60595 $dirFiles[$k] = $f;
60596 }
60597 }
60598 }
60599 self::$darwinCache[$kDir][1] = $dirFiles;
60600 }
60601 }
60602
60603 $real .= $dirFiles[$kFile];
60604 }
60605
60606 if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true)
60607 && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false)
60608 ) {
60609 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)));
60610 }
60611 }
60612
60613 return true;
60614 }
60615 }
60616 }
60617 <?php
60618
60619
60620
60621
60622
60623
60624
60625
60626
60627
60628 namespace Symfony\Component\Debug;
60629
60630 use Psr\Log\LogLevel;
60631 use Psr\Log\LoggerInterface;
60632 use Symfony\Component\Debug\Exception\ContextErrorException;
60633 use Symfony\Component\Debug\Exception\FatalErrorException;
60634 use Symfony\Component\Debug\Exception\FatalThrowableError;
60635 use Symfony\Component\Debug\Exception\OutOfMemoryException;
60636 use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler;
60637 use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler;
60638 use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler;
60639 use Symfony\Component\Debug\FatalErrorHandler\FatalErrorHandlerInterface;
60640
60641
60642
60643
60644
60645
60646
60647
60648
60649
60650
60651
60652
60653
60654
60655
60656
60657
60658
60659
60660
60661
60662
60663 class ErrorHandler
60664 {
60665
60666
60667
60668 const TYPE_DEPRECATION = -100;
60669
60670 private $levels = array(
60671 E_DEPRECATED => 'Deprecated',
60672 E_USER_DEPRECATED => 'User Deprecated',
60673 E_NOTICE => 'Notice',
60674 E_USER_NOTICE => 'User Notice',
60675 E_STRICT => 'Runtime Notice',
60676 E_WARNING => 'Warning',
60677 E_USER_WARNING => 'User Warning',
60678 E_COMPILE_WARNING => 'Compile Warning',
60679 E_CORE_WARNING => 'Core Warning',
60680 E_USER_ERROR => 'User Error',
60681 E_RECOVERABLE_ERROR => 'Catchable Fatal Error',
60682 E_COMPILE_ERROR => 'Compile Error',
60683 E_PARSE => 'Parse Error',
60684 E_ERROR => 'Error',
60685 E_CORE_ERROR => 'Core Error',
60686 );
60687
60688 private $loggers = array(
60689 E_DEPRECATED => array(null, LogLevel::INFO),
60690 E_USER_DEPRECATED => array(null, LogLevel::INFO),
60691 E_NOTICE => array(null, LogLevel::WARNING),
60692 E_USER_NOTICE => array(null, LogLevel::WARNING),
60693 E_STRICT => array(null, LogLevel::WARNING),
60694 E_WARNING => array(null, LogLevel::WARNING),
60695 E_USER_WARNING => array(null, LogLevel::WARNING),
60696 E_COMPILE_WARNING => array(null, LogLevel::WARNING),
60697 E_CORE_WARNING => array(null, LogLevel::WARNING),
60698 E_USER_ERROR => array(null, LogLevel::CRITICAL),
60699 E_RECOVERABLE_ERROR => array(null, LogLevel::CRITICAL),
60700 E_COMPILE_ERROR => array(null, LogLevel::CRITICAL),
60701 E_PARSE => array(null, LogLevel::CRITICAL),
60702 E_ERROR => array(null, LogLevel::CRITICAL),
60703 E_CORE_ERROR => array(null, LogLevel::CRITICAL),
60704 );
60705
60706 private $thrownErrors = 0x1FFF; 
60707  private $scopedErrors = 0x1FFF; 
60708  private $tracedErrors = 0x77FB; 
60709  private $screamedErrors = 0x55; 
60710  private $loggedErrors = 0;
60711
60712 private $loggedTraces = array();
60713 private $isRecursive = 0;
60714 private $isRoot = false;
60715 private $exceptionHandler;
60716 private $bootstrappingLogger;
60717
60718 private static $reservedMemory;
60719 private static $stackedErrors = array();
60720 private static $stackedErrorLevels = array();
60721 private static $toStringException = null;
60722 private static $exitCode = 0;
60723
60724
60725
60726
60727
60728
60729 private $displayErrors = 0x1FFF;
60730
60731
60732
60733
60734
60735
60736
60737
60738
60739 public static function register($handler = null, $replace = true)
60740 {
60741 if (null === self::$reservedMemory) {
60742 self::$reservedMemory = str_repeat('x', 10240);
60743 register_shutdown_function(__CLASS__.'::handleFatalError');
60744 }
60745
60746 $levels = -1;
60747
60748 if ($handlerIsNew = !$handler instanceof self) {
60749
60750  if (null !== $handler) {
60751 $levels = $replace ? $handler : 0;
60752 $replace = true;
60753 }
60754 $handler = new static();
60755 }
60756
60757 if (null === $prev = set_error_handler(array($handler, 'handleError'))) {
60758 restore_error_handler();
60759
60760  set_error_handler(array($handler, 'handleError'), $handler->thrownErrors | $handler->loggedErrors);
60761 $handler->isRoot = true;
60762 }
60763
60764 if ($handlerIsNew && is_array($prev) && $prev[0] instanceof self) {
60765 $handler = $prev[0];
60766 $replace = false;
60767 }
60768 if ($replace || !$prev) {
60769 $handler->setExceptionHandler(set_exception_handler(array($handler, 'handleException')));
60770 } else {
60771 restore_error_handler();
60772 }
60773
60774 $handler->throwAt($levels & $handler->thrownErrors, true);
60775
60776 return $handler;
60777 }
60778
60779 public function __construct(BufferingLogger $bootstrappingLogger = null)
60780 {
60781 if ($bootstrappingLogger) {
60782 $this->bootstrappingLogger = $bootstrappingLogger;
60783 $this->setDefaultLogger($bootstrappingLogger);
60784 }
60785 }
60786
60787
60788
60789
60790
60791
60792
60793
60794 public function setDefaultLogger(LoggerInterface $logger, $levels = null, $replace = false)
60795 {
60796 $loggers = array();
60797
60798 if (is_array($levels)) {
60799 foreach ($levels as $type => $logLevel) {
60800 if (empty($this->loggers[$type][0]) || $replace || $this->loggers[$type][0] === $this->bootstrappingLogger) {
60801 $loggers[$type] = array($logger, $logLevel);
60802 }
60803 }
60804 } else {
60805 if (null === $levels) {
60806 $levels = E_ALL | E_STRICT;
60807 }
60808 foreach ($this->loggers as $type => $log) {
60809 if (($type & $levels) && (empty($log[0]) || $replace || $log[0] === $this->bootstrappingLogger)) {
60810 $log[0] = $logger;
60811 $loggers[$type] = $log;
60812 }
60813 }
60814 }
60815
60816 $this->setLoggers($loggers);
60817 }
60818
60819
60820
60821
60822
60823
60824
60825
60826
60827
60828 public function setLoggers(array $loggers)
60829 {
60830 $prevLogged = $this->loggedErrors;
60831 $prev = $this->loggers;
60832 $flush = array();
60833
60834 foreach ($loggers as $type => $log) {
60835 if (!isset($prev[$type])) {
60836 throw new \InvalidArgumentException('Unknown error type: '.$type);
60837 }
60838 if (!is_array($log)) {
60839 $log = array($log);
60840 } elseif (!array_key_exists(0, $log)) {
60841 throw new \InvalidArgumentException('No logger provided');
60842 }
60843 if (null === $log[0]) {
60844 $this->loggedErrors &= ~$type;
60845 } elseif ($log[0] instanceof LoggerInterface) {
60846 $this->loggedErrors |= $type;
60847 } else {
60848 throw new \InvalidArgumentException('Invalid logger provided');
60849 }
60850 $this->loggers[$type] = $log + $prev[$type];
60851
60852 if ($this->bootstrappingLogger && $prev[$type][0] === $this->bootstrappingLogger) {
60853 $flush[$type] = $type;
60854 }
60855 }
60856 $this->reRegister($prevLogged | $this->thrownErrors);
60857
60858 if ($flush) {
60859 foreach ($this->bootstrappingLogger->cleanLogs() as $log) {
60860 $type = $log[2]['type'];
60861 if (!isset($flush[$type])) {
60862 $this->bootstrappingLogger->log($log[0], $log[1], $log[2]);
60863 } elseif ($this->loggers[$type][0]) {
60864 $this->loggers[$type][0]->log($this->loggers[$type][1], $log[1], $log[2]);
60865 }
60866 }
60867 }
60868
60869 return $prev;
60870 }
60871
60872
60873
60874
60875
60876
60877
60878
60879
60880
60881 public function setExceptionHandler($handler)
60882 {
60883 if (null !== $handler && !is_callable($handler)) {
60884 throw new \LogicException('The exception handler must be a valid PHP callable.');
60885 }
60886 $prev = $this->exceptionHandler;
60887 $this->exceptionHandler = $handler;
60888
60889 return $prev;
60890 }
60891
60892
60893
60894
60895
60896
60897
60898
60899
60900 public function throwAt($levels, $replace = false)
60901 {
60902 $prev = $this->thrownErrors;
60903 $this->thrownErrors = ($levels | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED;
60904 if (!$replace) {
60905 $this->thrownErrors |= $prev;
60906 }
60907 $this->reRegister($prev | $this->loggedErrors);
60908
60909
60910  $this->displayErrors = $this->thrownErrors;
60911
60912 return $prev;
60913 }
60914
60915
60916
60917
60918
60919
60920
60921
60922
60923 public function scopeAt($levels, $replace = false)
60924 {
60925 $prev = $this->scopedErrors;
60926 $this->scopedErrors = (int) $levels;
60927 if (!$replace) {
60928 $this->scopedErrors |= $prev;
60929 }
60930
60931 return $prev;
60932 }
60933
60934
60935
60936
60937
60938
60939
60940
60941
60942 public function traceAt($levels, $replace = false)
60943 {
60944 $prev = $this->tracedErrors;
60945 $this->tracedErrors = (int) $levels;
60946 if (!$replace) {
60947 $this->tracedErrors |= $prev;
60948 }
60949
60950 return $prev;
60951 }
60952
60953
60954
60955
60956
60957
60958
60959
60960
60961 public function screamAt($levels, $replace = false)
60962 {
60963 $prev = $this->screamedErrors;
60964 $this->screamedErrors = (int) $levels;
60965 if (!$replace) {
60966 $this->screamedErrors |= $prev;
60967 }
60968
60969 return $prev;
60970 }
60971
60972
60973
60974
60975 private function reRegister($prev)
60976 {
60977 if ($prev !== $this->thrownErrors | $this->loggedErrors) {
60978 $handler = set_error_handler('var_dump');
60979 $handler = is_array($handler) ? $handler[0] : null;
60980 restore_error_handler();
60981 if ($handler === $this) {
60982 restore_error_handler();
60983 if ($this->isRoot) {
60984 set_error_handler(array($this, 'handleError'), $this->thrownErrors | $this->loggedErrors);
60985 } else {
60986 set_error_handler(array($this, 'handleError'));
60987 }
60988 }
60989 }
60990 }
60991
60992
60993
60994
60995
60996
60997
60998
60999
61000
61001
61002
61003
61004
61005
61006 public function handleError($type, $message, $file, $line)
61007 {
61008 $level = error_reporting() | E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED;
61009 $log = $this->loggedErrors & $type;
61010 $throw = $this->thrownErrors & $type & $level;
61011 $type &= $level | $this->screamedErrors;
61012
61013 if (!$type || (!$log && !$throw)) {
61014 return $type && $log;
61015 }
61016 $scope = $this->scopedErrors & $type;
61017
61018 if (4 < $numArgs = func_num_args()) {
61019 $context = $scope ? (func_get_arg(4) ?: array()) : array();
61020 $backtrace = 5 < $numArgs ? func_get_arg(5) : null; 
61021  } else {
61022 $context = array();
61023 $backtrace = null;
61024 }
61025
61026 if (isset($context['GLOBALS']) && $scope) {
61027 $e = $context; 
61028  unset($e['GLOBALS'], $context); 
61029  $context = $e;
61030 }
61031
61032 if (null !== $backtrace && $type & E_ERROR) {
61033
61034  
61035  
61036  $this->handleFatalError(compact('type', 'message', 'file', 'line', 'backtrace'));
61037
61038 return true;
61039 }
61040
61041 if ($throw) {
61042 if (null !== self::$toStringException) {
61043 $throw = self::$toStringException;
61044 self::$toStringException = null;
61045 } elseif ($scope && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) {
61046
61047  $throw = new ContextErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line, $context);
61048 } else {
61049 $throw = new \ErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line);
61050 }
61051
61052 if (\PHP_VERSION_ID <= 50407 && (\PHP_VERSION_ID >= 50400 || \PHP_VERSION_ID <= 50317)) {
61053
61054  
61055  
61056
61057 $throw->errorHandlerCanary = new ErrorHandlerCanary();
61058 }
61059
61060 if (E_USER_ERROR & $type) {
61061 $backtrace = $backtrace ?: $throw->getTrace();
61062
61063 for ($i = 1; isset($backtrace[$i]); ++$i) {
61064 if (isset($backtrace[$i]['function'], $backtrace[$i]['type'], $backtrace[$i - 1]['function'])
61065 && '__toString' === $backtrace[$i]['function']
61066 && '->' === $backtrace[$i]['type']
61067 && !isset($backtrace[$i - 1]['class'])
61068 && ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function'])
61069 ) {
61070
61071  
61072  
61073  
61074  
61075  
61076
61077 foreach ($context as $e) {
61078 if (($e instanceof \Exception || $e instanceof \Throwable) && $e->__toString() === $message) {
61079 if (1 === $i) {
61080
61081  $throw = $e;
61082 break;
61083 }
61084 self::$toStringException = $e;
61085
61086 return true;
61087 }
61088 }
61089
61090 if (1 < $i) {
61091
61092  $this->handleException($throw);
61093
61094
61095  return false;
61096 }
61097 }
61098 }
61099 }
61100
61101 throw $throw;
61102 }
61103
61104
61105  $e = md5("{$type}/{$line}/{$file}\x00{$message}", true);
61106 $trace = true;
61107
61108 if (!($this->tracedErrors & $type) || isset($this->loggedTraces[$e])) {
61109 $trace = false;
61110 } else {
61111 $this->loggedTraces[$e] = 1;
61112 }
61113
61114 $e = compact('type', 'file', 'line', 'level');
61115
61116 if ($type & $level) {
61117 if ($scope) {
61118 $e['scope_vars'] = $context;
61119 if ($trace) {
61120 $e['stack'] = $backtrace ?: debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT);
61121 }
61122 } elseif ($trace) {
61123 if (null === $backtrace) {
61124 $e['stack'] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
61125 } else {
61126 foreach ($backtrace as &$frame) {
61127 unset($frame['args'], $frame);
61128 }
61129 $e['stack'] = $backtrace;
61130 }
61131 }
61132 }
61133
61134 if ($this->isRecursive) {
61135 $log = 0;
61136 } elseif (self::$stackedErrorLevels) {
61137 self::$stackedErrors[] = array($this->loggers[$type][0], ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, $message, $e);
61138 } else {
61139 try {
61140 $this->isRecursive = true;
61141 $this->loggers[$type][0]->log(($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, $message, $e);
61142 $this->isRecursive = false;
61143 } catch (\Exception $e) {
61144 $this->isRecursive = false;
61145
61146 throw $e;
61147 } catch (\Throwable $e) {
61148 $this->isRecursive = false;
61149
61150 throw $e;
61151 }
61152 }
61153
61154 return $type && $log;
61155 }
61156
61157
61158
61159
61160
61161
61162
61163
61164
61165 public function handleException($exception, array $error = null)
61166 {
61167 if (null === $error) {
61168 self::$exitCode = 255;
61169 }
61170 if (!$exception instanceof \Exception) {
61171 $exception = new FatalThrowableError($exception);
61172 }
61173 $type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR;
61174
61175 if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) {
61176 $e = array(
61177 'type' => $type,
61178 'file' => $exception->getFile(),
61179 'line' => $exception->getLine(),
61180 'level' => error_reporting(),
61181 'stack' => $exception->getTrace(),
61182 );
61183 if ($exception instanceof FatalErrorException) {
61184 if ($exception instanceof FatalThrowableError) {
61185 $error = array(
61186 'type' => $type,
61187 'message' => $message = $exception->getMessage(),
61188 'file' => $e['file'],
61189 'line' => $e['line'],
61190 );
61191 } else {
61192 $message = 'Fatal '.$exception->getMessage();
61193 }
61194 } elseif ($exception instanceof \ErrorException) {
61195 $message = 'Uncaught '.$exception->getMessage();
61196 if ($exception instanceof ContextErrorException) {
61197 $e['context'] = $exception->getContext();
61198 }
61199 } else {
61200 $message = 'Uncaught Exception: '.$exception->getMessage();
61201 }
61202 }
61203 if ($this->loggedErrors & $type) {
61204 try {
61205 $this->loggers[$type][0]->log($this->loggers[$type][1], $message, $e);
61206 } catch (\Exception $handlerException) {
61207 } catch (\Throwable $handlerException) {
61208 }
61209 }
61210 if ($exception instanceof FatalErrorException && !$exception instanceof OutOfMemoryException && $error) {
61211 foreach ($this->getFatalErrorHandlers() as $handler) {
61212 if ($e = $handler->handleError($error, $exception)) {
61213 $exception = $e;
61214 break;
61215 }
61216 }
61217 }
61218 if (empty($this->exceptionHandler)) {
61219 throw $exception; 
61220  }
61221 try {
61222 call_user_func($this->exceptionHandler, $exception);
61223 } catch (\Exception $handlerException) {
61224 } catch (\Throwable $handlerException) {
61225 }
61226 if (isset($handlerException)) {
61227 $this->exceptionHandler = null;
61228 $this->handleException($handlerException);
61229 }
61230 }
61231
61232
61233
61234
61235
61236
61237
61238
61239 public static function handleFatalError(array $error = null)
61240 {
61241 if (null === self::$reservedMemory) {
61242 return;
61243 }
61244
61245 self::$reservedMemory = null;
61246
61247 $handler = set_error_handler('var_dump');
61248 $handler = is_array($handler) ? $handler[0] : null;
61249 restore_error_handler();
61250
61251 if (!$handler instanceof self) {
61252 return;
61253 }
61254
61255 if ($exit = null === $error) {
61256 $error = error_get_last();
61257 }
61258
61259 try {
61260 while (self::$stackedErrorLevels) {
61261 static::unstackErrors();
61262 }
61263 } catch (\Exception $exception) {
61264
61265  } catch (\Throwable $exception) {
61266
61267  }
61268
61269 if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) {
61270
61271  $handler->throwAt(0, true);
61272 $trace = isset($error['backtrace']) ? $error['backtrace'] : null;
61273
61274 if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) {
61275 $exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false, $trace);
61276 } else {
61277 $exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true, $trace);
61278 }
61279 }
61280
61281 try {
61282 if (isset($exception)) {
61283 self::$exitCode = 255;
61284 $handler->handleException($exception, $error);
61285 }
61286 } catch (FatalErrorException $e) {
61287
61288  }
61289
61290 if ($exit && self::$exitCode) {
61291 $exitCode = self::$exitCode;
61292 register_shutdown_function('register_shutdown_function', function () use ($exitCode) { exit($exitCode); });
61293 }
61294 }
61295
61296
61297
61298
61299
61300
61301
61302
61303
61304
61305
61306
61307 public static function stackErrors()
61308 {
61309 self::$stackedErrorLevels[] = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
61310 }
61311
61312
61313
61314
61315 public static function unstackErrors()
61316 {
61317 $level = array_pop(self::$stackedErrorLevels);
61318
61319 if (null !== $level) {
61320 $e = error_reporting($level);
61321 if ($e !== ($level | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR)) {
61322
61323  error_reporting($e);
61324 }
61325 }
61326
61327 if (empty(self::$stackedErrorLevels)) {
61328 $errors = self::$stackedErrors;
61329 self::$stackedErrors = array();
61330
61331 foreach ($errors as $e) {
61332 $e[0]->log($e[1], $e[2], $e[3]);
61333 }
61334 }
61335 }
61336
61337
61338
61339
61340
61341
61342
61343
61344 protected function getFatalErrorHandlers()
61345 {
61346 return array(
61347 new UndefinedFunctionFatalErrorHandler(),
61348 new UndefinedMethodFatalErrorHandler(),
61349 new ClassNotFoundFatalErrorHandler(),
61350 );
61351 }
61352
61353
61354
61355
61356
61357
61358
61359
61360 public function setLevel($level)
61361 {
61362 @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);
61363
61364 $level = null === $level ? error_reporting() : $level;
61365 $this->throwAt($level, true);
61366 }
61367
61368
61369
61370
61371
61372
61373
61374
61375 public function setDisplayErrors($displayErrors)
61376 {
61377 @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);
61378
61379 if ($displayErrors) {
61380 $this->throwAt($this->displayErrors, true);
61381 } else {
61382 $displayErrors = $this->displayErrors;
61383 $this->throwAt(0, true);
61384 $this->displayErrors = $displayErrors;
61385 }
61386 }
61387
61388
61389
61390
61391
61392
61393
61394
61395
61396 public static function setLogger(LoggerInterface $logger, $channel = 'deprecation')
61397 {
61398 @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);
61399
61400 $handler = set_error_handler('var_dump');
61401 $handler = is_array($handler) ? $handler[0] : null;
61402 restore_error_handler();
61403 if (!$handler instanceof self) {
61404 return;
61405 }
61406 if ('deprecation' === $channel) {
61407 $handler->setDefaultLogger($logger, E_DEPRECATED | E_USER_DEPRECATED, true);
61408 $handler->screamAt(E_DEPRECATED | E_USER_DEPRECATED);
61409 } elseif ('scream' === $channel) {
61410 $handler->setDefaultLogger($logger, E_ALL | E_STRICT, false);
61411 $handler->screamAt(E_ALL | E_STRICT);
61412 } elseif ('emergency' === $channel) {
61413 $handler->setDefaultLogger($logger, E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR, true);
61414 $handler->screamAt(E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
61415 }
61416 }
61417
61418
61419
61420
61421 public function handle($level, $message, $file = 'unknown', $line = 0, $context = array())
61422 {
61423 $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());
61424
61425 return $this->handleError($level, $message, $file, $line, (array) $context);
61426 }
61427
61428
61429
61430
61431
61432
61433 public function handleFatal()
61434 {
61435 @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);
61436
61437 static::handleFatalError();
61438 }
61439 }
61440
61441
61442
61443
61444
61445
61446
61447
61448 class ErrorHandlerCanary
61449 {
61450 private static $displayErrors = null;
61451
61452 public function __construct()
61453 {
61454 if (null === self::$displayErrors) {
61455 self::$displayErrors = ini_set('display_errors', 1);
61456 }
61457 }
61458
61459 public function __destruct()
61460 {
61461 if (null !== self::$displayErrors) {
61462 ini_set('display_errors', self::$displayErrors);
61463 self::$displayErrors = null;
61464 }
61465 }
61466 }
61467 <?php
61468
61469
61470
61471
61472
61473
61474
61475
61476
61477
61478 namespace Symfony\Component\Debug\Exception;
61479
61480
61481
61482
61483
61484
61485 class ClassNotFoundException extends FatalErrorException
61486 {
61487 public function __construct($message, \ErrorException $previous)
61488 {
61489 parent::__construct(
61490 $message,
61491 $previous->getCode(),
61492 $previous->getSeverity(),
61493 $previous->getFile(),
61494 $previous->getLine(),
61495 $previous->getPrevious()
61496 );
61497 $this->setTrace($previous->getTrace());
61498 }
61499 }
61500 <?php
61501
61502
61503
61504
61505
61506
61507
61508
61509
61510
61511 namespace Symfony\Component\Debug\Exception;
61512
61513
61514
61515
61516
61517
61518 class ContextErrorException extends \ErrorException
61519 {
61520 private $context = array();
61521
61522 public function __construct($message, $code, $severity, $filename, $lineno, $context = array())
61523 {
61524 parent::__construct($message, $code, $severity, $filename, $lineno);
61525 $this->context = $context;
61526 }
61527
61528
61529
61530
61531 public function getContext()
61532 {
61533 return $this->context;
61534 }
61535 }
61536 <?php
61537
61538
61539
61540
61541
61542
61543
61544
61545
61546
61547 namespace Symfony\Component\Debug\Exception;
61548
61549 @trigger_error('The '.__NAMESPACE__.'\DummyException class is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
61550
61551
61552
61553
61554
61555
61556 class DummyException extends \ErrorException
61557 {
61558 }
61559 <?php
61560
61561
61562
61563
61564
61565
61566
61567
61568
61569
61570 namespace Symfony\Component\HttpKernel\Exception;
61571
61572
61573
61574
61575
61576
61577
61578
61579
61580
61581 class FatalErrorException extends \ErrorException
61582 {
61583 }
61584
61585 namespace Symfony\Component\Debug\Exception;
61586
61587 use Symfony\Component\HttpKernel\Exception\FatalErrorException as LegacyFatalErrorException;
61588
61589
61590
61591
61592
61593
61594 class FatalErrorException extends LegacyFatalErrorException
61595 {
61596 public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true, array $trace = null)
61597 {
61598 parent::__construct($message, $code, $severity, $filename, $lineno);
61599
61600 if (null !== $trace) {
61601 if (!$traceArgs) {
61602 foreach ($trace as &$frame) {
61603 unset($frame['args'], $frame['this'], $frame);
61604 }
61605 }
61606
61607 $this->setTrace($trace);
61608 } elseif (null !== $traceOffset) {
61609 if (function_exists('xdebug_get_function_stack')) {
61610 $trace = xdebug_get_function_stack();
61611 if (0 < $traceOffset) {
61612 array_splice($trace, -$traceOffset);
61613 }
61614
61615 foreach ($trace as &$frame) {
61616 if (!isset($frame['type'])) {
61617
61618  if (isset($frame['class'])) {
61619 $frame['type'] = '::';
61620 }
61621 } elseif ('dynamic' === $frame['type']) {
61622 $frame['type'] = '->';
61623 } elseif ('static' === $frame['type']) {
61624 $frame['type'] = '::';
61625 }
61626
61627
61628  if (!$traceArgs) {
61629 unset($frame['params'], $frame['args']);
61630 } elseif (isset($frame['params']) && !isset($frame['args'])) {
61631 $frame['args'] = $frame['params'];
61632 unset($frame['params']);
61633 }
61634 }
61635
61636 unset($frame);
61637 $trace = array_reverse($trace);
61638 } elseif (function_exists('symfony_debug_backtrace')) {
61639 $trace = symfony_debug_backtrace();
61640 if (0 < $traceOffset) {
61641 array_splice($trace, 0, $traceOffset);
61642 }
61643 } else {
61644 $trace = array();
61645 }
61646
61647 $this->setTrace($trace);
61648 }
61649 }
61650
61651 protected function setTrace($trace)
61652 {
61653 $traceReflector = new \ReflectionProperty('Exception', 'trace');
61654 $traceReflector->setAccessible(true);
61655 $traceReflector->setValue($this, $trace);
61656 }
61657 }
61658 <?php
61659
61660
61661
61662
61663
61664
61665
61666
61667
61668
61669 namespace Symfony\Component\Debug\Exception;
61670
61671
61672
61673
61674
61675
61676 class FatalThrowableError extends FatalErrorException
61677 {
61678 public function __construct(\Throwable $e)
61679 {
61680 if ($e instanceof \ParseError) {
61681 $message = 'Parse error: '.$e->getMessage();
61682 $severity = E_PARSE;
61683 } elseif ($e instanceof \TypeError) {
61684 $message = 'Type error: '.$e->getMessage();
61685 $severity = E_RECOVERABLE_ERROR;
61686 } else {
61687 $message = $e->getMessage();
61688 $severity = E_ERROR;
61689 }
61690
61691 \ErrorException::__construct(
61692 $message,
61693 $e->getCode(),
61694 $severity,
61695 $e->getFile(),
61696 $e->getLine()
61697 );
61698
61699 $this->setTrace($e->getTrace());
61700 }
61701 }
61702 <?php
61703
61704
61705
61706
61707
61708
61709
61710
61711
61712
61713 namespace Symfony\Component\HttpKernel\Exception;
61714
61715 use Symfony\Component\Debug\Exception\FlattenException as DebugFlattenException;
61716
61717
61718
61719
61720
61721
61722
61723
61724
61725
61726 class FlattenException
61727 {
61728 private $handler;
61729
61730 public static function __callStatic($method, $args)
61731 {
61732 if (!method_exists('Symfony\Component\Debug\Exception\FlattenException', $method)) {
61733 throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_called_class(), $method));
61734 }
61735
61736 return call_user_func_array(array('Symfony\Component\Debug\Exception\FlattenException', $method), $args);
61737 }
61738
61739 public function __call($method, $args)
61740 {
61741 if (!isset($this->handler)) {
61742 $this->handler = new DebugFlattenException();
61743 }
61744
61745 if (!method_exists($this->handler, $method)) {
61746 throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_class($this), $method));
61747 }
61748
61749 return call_user_func_array(array($this->handler, $method), $args);
61750 }
61751 }
61752
61753 namespace Symfony\Component\Debug\Exception;
61754
61755 use Symfony\Component\HttpKernel\Exception\FlattenException as LegacyFlattenException;
61756 use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
61757
61758
61759
61760
61761
61762
61763
61764
61765 class FlattenException extends LegacyFlattenException
61766 {
61767 private $message;
61768 private $code;
61769 private $previous;
61770 private $trace;
61771 private $class;
61772 private $statusCode;
61773 private $headers;
61774 private $file;
61775 private $line;
61776
61777 public static function create(\Exception $exception, $statusCode = null, array $headers = array())
61778 {
61779 $e = new static();
61780 $e->setMessage($exception->getMessage());
61781 $e->setCode($exception->getCode());
61782
61783 if ($exception instanceof HttpExceptionInterface) {
61784 $statusCode = $exception->getStatusCode();
61785 $headers = array_merge($headers, $exception->getHeaders());
61786 }
61787
61788 if (null === $statusCode) {
61789 $statusCode = 500;
61790 }
61791
61792 $e->setStatusCode($statusCode);
61793 $e->setHeaders($headers);
61794 $e->setTraceFromException($exception);
61795 $e->setClass(get_class($exception));
61796 $e->setFile($exception->getFile());
61797 $e->setLine($exception->getLine());
61798
61799 $previous = $exception->getPrevious();
61800
61801 if ($previous instanceof \Exception) {
61802 $e->setPrevious(static::create($previous));
61803 } elseif ($previous instanceof \Throwable) {
61804 $e->setPrevious(static::create(new FatalThrowableError($previous)));
61805 }
61806
61807 return $e;
61808 }
61809
61810 public function toArray()
61811 {
61812 $exceptions = array();
61813 foreach (array_merge(array($this), $this->getAllPrevious()) as $exception) {
61814 $exceptions[] = array(
61815 'message' => $exception->getMessage(),
61816 'class' => $exception->getClass(),
61817 'trace' => $exception->getTrace(),
61818 );
61819 }
61820
61821 return $exceptions;
61822 }
61823
61824 public function getStatusCode()
61825 {
61826 return $this->statusCode;
61827 }
61828
61829 public function setStatusCode($code)
61830 {
61831 $this->statusCode = $code;
61832 }
61833
61834 public function getHeaders()
61835 {
61836 return $this->headers;
61837 }
61838
61839 public function setHeaders(array $headers)
61840 {
61841 $this->headers = $headers;
61842 }
61843
61844 public function getClass()
61845 {
61846 return $this->class;
61847 }
61848
61849 public function setClass($class)
61850 {
61851 $this->class = $class;
61852 }
61853
61854 public function getFile()
61855 {
61856 return $this->file;
61857 }
61858
61859 public function setFile($file)
61860 {
61861 $this->file = $file;
61862 }
61863
61864 public function getLine()
61865 {
61866 return $this->line;
61867 }
61868
61869 public function setLine($line)
61870 {
61871 $this->line = $line;
61872 }
61873
61874 public function getMessage()
61875 {
61876 return $this->message;
61877 }
61878
61879 public function setMessage($message)
61880 {
61881 $this->message = $message;
61882 }
61883
61884 public function getCode()
61885 {
61886 return $this->code;
61887 }
61888
61889 public function setCode($code)
61890 {
61891 $this->code = $code;
61892 }
61893
61894 public function getPrevious()
61895 {
61896 return $this->previous;
61897 }
61898
61899 public function setPrevious(FlattenException $previous)
61900 {
61901 $this->previous = $previous;
61902 }
61903
61904 public function getAllPrevious()
61905 {
61906 $exceptions = array();
61907 $e = $this;
61908 while ($e = $e->getPrevious()) {
61909 $exceptions[] = $e;
61910 }
61911
61912 return $exceptions;
61913 }
61914
61915 public function getTrace()
61916 {
61917 return $this->trace;
61918 }
61919
61920 public function setTraceFromException(\Exception $exception)
61921 {
61922 $this->setTrace($exception->getTrace(), $exception->getFile(), $exception->getLine());
61923 }
61924
61925 public function setTrace($trace, $file, $line)
61926 {
61927 $this->trace = array();
61928 $this->trace[] = array(
61929 'namespace' => '',
61930 'short_class' => '',
61931 'class' => '',
61932 'type' => '',
61933 'function' => '',
61934 'file' => $file,
61935 'line' => $line,
61936 'args' => array(),
61937 );
61938 foreach ($trace as $entry) {
61939 $class = '';
61940 $namespace = '';
61941 if (isset($entry['class'])) {
61942 $parts = explode('\\', $entry['class']);
61943 $class = array_pop($parts);
61944 $namespace = implode('\\', $parts);
61945 }
61946
61947 $this->trace[] = array(
61948 'namespace' => $namespace,
61949 'short_class' => $class,
61950 'class' => isset($entry['class']) ? $entry['class'] : '',
61951 'type' => isset($entry['type']) ? $entry['type'] : '',
61952 'function' => isset($entry['function']) ? $entry['function'] : null,
61953 'file' => isset($entry['file']) ? $entry['file'] : null,
61954 'line' => isset($entry['line']) ? $entry['line'] : null,
61955 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : array(),
61956 );
61957 }
61958 }
61959
61960 private function flattenArgs($args, $level = 0, &$count = 0)
61961 {
61962 $result = array();
61963 foreach ($args as $key => $value) {
61964 if (++$count > 1e4) {
61965 return array('array', '*SKIPPED over 10000 entries*');
61966 }
61967 if ($value instanceof \__PHP_Incomplete_Class) {
61968
61969  $result[$key] = array('incomplete-object', $this->getClassNameFromIncomplete($value));
61970 } elseif (is_object($value)) {
61971 $result[$key] = array('object', get_class($value));
61972 } elseif (is_array($value)) {
61973 if ($level > 10) {
61974 $result[$key] = array('array', '*DEEP NESTED ARRAY*');
61975 } else {
61976 $result[$key] = array('array', $this->flattenArgs($value, $level + 1, $count));
61977 }
61978 } elseif (null === $value) {
61979 $result[$key] = array('null', null);
61980 } elseif (is_bool($value)) {
61981 $result[$key] = array('boolean', $value);
61982 } elseif (is_resource($value)) {
61983 $result[$key] = array('resource', get_resource_type($value));
61984 } else {
61985 $result[$key] = array('string', (string) $value);
61986 }
61987 }
61988
61989 return $result;
61990 }
61991
61992 private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value)
61993 {
61994 $array = new \ArrayObject($value);
61995
61996 return $array['__PHP_Incomplete_Class_Name'];
61997 }
61998 }
61999 <?php
62000
62001
62002
62003
62004
62005
62006
62007
62008
62009
62010 namespace Symfony\Component\Debug\Exception;
62011
62012
62013
62014
62015
62016
62017 class OutOfMemoryException extends FatalErrorException
62018 {
62019 }
62020 <?php
62021
62022
62023
62024
62025
62026
62027
62028
62029
62030
62031 namespace Symfony\Component\Debug\Exception;
62032
62033
62034
62035
62036
62037
62038 class UndefinedFunctionException extends FatalErrorException
62039 {
62040 public function __construct($message, \ErrorException $previous)
62041 {
62042 parent::__construct(
62043 $message,
62044 $previous->getCode(),
62045 $previous->getSeverity(),
62046 $previous->getFile(),
62047 $previous->getLine(),
62048 $previous->getPrevious()
62049 );
62050 $this->setTrace($previous->getTrace());
62051 }
62052 }
62053 <?php
62054
62055
62056
62057
62058
62059
62060
62061
62062
62063
62064 namespace Symfony\Component\Debug\Exception;
62065
62066
62067
62068
62069
62070
62071 class UndefinedMethodException extends FatalErrorException
62072 {
62073 public function __construct($message, \ErrorException $previous)
62074 {
62075 parent::__construct(
62076 $message,
62077 $previous->getCode(),
62078 $previous->getSeverity(),
62079 $previous->getFile(),
62080 $previous->getLine(),
62081 $previous->getPrevious()
62082 );
62083 $this->setTrace($previous->getTrace());
62084 }
62085 }
62086 <?php
62087
62088
62089
62090
62091
62092
62093
62094
62095
62096
62097 namespace Symfony\Component\Debug;
62098
62099 use Symfony\Component\HttpFoundation\Response;
62100 use Symfony\Component\Debug\Exception\FlattenException;
62101 use Symfony\Component\Debug\Exception\OutOfMemoryException;
62102
62103
62104
62105
62106
62107
62108
62109
62110
62111
62112
62113
62114
62115 class ExceptionHandler
62116 {
62117 private $debug;
62118 private $charset;
62119 private $handler;
62120 private $caughtBuffer;
62121 private $caughtLength;
62122 private $fileLinkFormat;
62123
62124 public function __construct($debug = true, $charset = null, $fileLinkFormat = null)
62125 {
62126 if (false !== strpos($charset, '%')) {
62127 @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);
62128
62129
62130  $pivot = $fileLinkFormat;
62131 $fileLinkFormat = $charset;
62132 $charset = $pivot;
62133 }
62134 $this->debug = $debug;
62135 $this->charset = $charset ?: ini_get('default_charset') ?: 'UTF-8';
62136 $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
62137 }
62138
62139
62140
62141
62142
62143
62144
62145
62146
62147
62148 public static function register($debug = true, $charset = null, $fileLinkFormat = null)
62149 {
62150 $handler = new static($debug, $charset, $fileLinkFormat);
62151
62152 $prev = set_exception_handler(array($handler, 'handle'));
62153 if (is_array($prev) && $prev[0] instanceof ErrorHandler) {
62154 restore_exception_handler();
62155 $prev[0]->setExceptionHandler(array($handler, 'handle'));
62156 }
62157
62158 return $handler;
62159 }
62160
62161
62162
62163
62164
62165
62166
62167
62168 public function setHandler($handler)
62169 {
62170 if (null !== $handler && !is_callable($handler)) {
62171 throw new \LogicException('The exception handler must be a valid PHP callable.');
62172 }
62173 $old = $this->handler;
62174 $this->handler = $handler;
62175
62176 return $old;
62177 }
62178
62179
62180
62181
62182
62183
62184
62185
62186 public function setFileLinkFormat($format)
62187 {
62188 $old = $this->fileLinkFormat;
62189 $this->fileLinkFormat = $format;
62190
62191 return $old;
62192 }
62193
62194
62195
62196
62197
62198
62199
62200
62201
62202 public function handle(\Exception $exception)
62203 {
62204 if (null === $this->handler || $exception instanceof OutOfMemoryException) {
62205 $this->failSafeHandle($exception);
62206
62207 return;
62208 }
62209
62210 $caughtLength = $this->caughtLength = 0;
62211
62212 ob_start(array($this, 'catchOutput'));
62213 $this->failSafeHandle($exception);
62214 while (null === $this->caughtBuffer && ob_end_flush()) {
62215
62216  }
62217 if (isset($this->caughtBuffer[0])) {
62218 ob_start(array($this, 'cleanOutput'));
62219 echo $this->caughtBuffer;
62220 $caughtLength = ob_get_length();
62221 }
62222 $this->caughtBuffer = null;
62223
62224 try {
62225 call_user_func($this->handler, $exception);
62226 $this->caughtLength = $caughtLength;
62227 } catch (\Exception $e) {
62228 if (!$caughtLength) {
62229
62230  throw $exception;
62231 }
62232 }
62233 }
62234
62235
62236
62237
62238
62239
62240
62241
62242
62243
62244 private function failSafeHandle(\Exception $exception)
62245 {
62246 if (class_exists('Symfony\Component\HttpFoundation\Response', false)
62247 && __CLASS__ !== get_class($this)
62248 && ($reflector = new \ReflectionMethod($this, 'createResponse'))
62249 && __CLASS__ !== $reflector->class
62250 ) {
62251 $response = $this->createResponse($exception);
62252 $response->sendHeaders();
62253 $response->sendContent();
62254 @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);
62255
62256 return;
62257 }
62258
62259 $this->sendPhpResponse($exception);
62260 }
62261
62262
62263
62264
62265
62266
62267
62268
62269
62270 public function sendPhpResponse($exception)
62271 {
62272 if (!$exception instanceof FlattenException) {
62273 $exception = FlattenException::create($exception);
62274 }
62275
62276 if (!headers_sent()) {
62277 header(sprintf('HTTP/1.0 %s', $exception->getStatusCode()));
62278 foreach ($exception->getHeaders() as $name => $value) {
62279 header($name.': '.$value, false);
62280 }
62281 header('Content-Type: text/html; charset='.$this->charset);
62282 }
62283
62284 echo $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
62285 }
62286
62287
62288
62289
62290
62291
62292
62293
62294
62295
62296 public function createResponse($exception)
62297 {
62298 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
62299
62300 if (!$exception instanceof FlattenException) {
62301 $exception = FlattenException::create($exception);
62302 }
62303
62304 return Response::create($this->getHtml($exception), $exception->getStatusCode(), $exception->getHeaders())->setCharset($this->charset);
62305 }
62306
62307
62308
62309
62310
62311
62312
62313
62314 public function getHtml($exception)
62315 {
62316 if (!$exception instanceof FlattenException) {
62317 $exception = FlattenException::create($exception);
62318 }
62319
62320 return $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
62321 }
62322
62323
62324
62325
62326
62327
62328
62329
62330 public function getContent(FlattenException $exception)
62331 {
62332 switch ($exception->getStatusCode()) {
62333 case 404:
62334 $title = 'Sorry, the page you are looking for could not be found.';
62335 break;
62336 default:
62337 $title = 'Whoops, looks like something went wrong.';
62338 }
62339
62340 $content = '';
62341 if ($this->debug) {
62342 try {
62343 $count = count($exception->getAllPrevious());
62344 $total = $count + 1;
62345 foreach ($exception->toArray() as $position => $e) {
62346 $ind = $count - $position + 1;
62347 $class = $this->formatClass($e['class']);
62348 $message = nl2br($this->escapeHtml($e['message']));
62349 $content .= sprintf(<<<'EOF'
62350                         <h2 class="block_exception clear_fix">
62351                             <span class="exception_counter">%d/%d</span>
62352                             <span class="exception_title">%s%s:</span>
62353                             <span class="exception_message">%s</span>
62354                         </h2>
62355                         <div class="block">
62356                             <ol class="traces list_exception">
62357
62358 EOF
62359 , $ind, $total, $class, $this->formatPath($e['trace'][0]['file'], $e['trace'][0]['line']), $message);
62360 foreach ($e['trace'] as $trace) {
62361 $content .= '       <li>';
62362 if ($trace['function']) {
62363 $content .= sprintf('at %s%s%s(%s)', $this->formatClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args']));
62364 }
62365 if (isset($trace['file']) && isset($trace['line'])) {
62366 $content .= $this->formatPath($trace['file'], $trace['line']);
62367 }
62368 $content .= "</li>\n";
62369 }
62370
62371 $content .= "    </ol>\n</div>\n";
62372 }
62373 } catch (\Exception $e) {
62374
62375  if ($this->debug) {
62376 $title = sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $this->escapeHtml($e->getMessage()));
62377 } else {
62378 $title = 'Whoops, looks like something went wrong.';
62379 }
62380 }
62381 }
62382
62383 return <<<EOF
62384             <div id="sf-resetcontent" class="sf-reset">
62385                 <h1>$title</h1>
62386                 $content
62387             </div>
62388 EOF;
62389 }
62390
62391
62392
62393
62394
62395
62396
62397
62398 public function getStylesheet(FlattenException $exception)
62399 {
62400 return <<<'EOF'
62401             .sf-reset { font: 11px Verdana, Arial, sans-serif; color: #333 }
62402             .sf-reset .clear { clear:both; height:0; font-size:0; line-height:0; }
62403             .sf-reset .clear_fix:after { display:block; height:0; clear:both; visibility:hidden; }
62404             .sf-reset .clear_fix { display:inline-block; }
62405             .sf-reset * html .clear_fix { height:1%; }
62406             .sf-reset .clear_fix { display:block; }
62407             .sf-reset, .sf-reset .block { margin: auto }
62408             .sf-reset abbr { border-bottom: 1px dotted #000; cursor: help; }
62409             .sf-reset p { font-size:14px; line-height:20px; color:#868686; padding-bottom:20px }
62410             .sf-reset strong { font-weight:bold; }
62411             .sf-reset a { color:#6c6159; cursor: default; }
62412             .sf-reset a img { border:none; }
62413             .sf-reset a:hover { text-decoration:underline; }
62414             .sf-reset em { font-style:italic; }
62415             .sf-reset h1, .sf-reset h2 { font: 20px Georgia, "Times New Roman", Times, serif }
62416             .sf-reset .exception_counter { background-color: #fff; color: #333; padding: 6px; float: left; margin-right: 10px; float: left; display: block; }
62417             .sf-reset .exception_title { margin-left: 3em; margin-bottom: 0.7em; display: block; }
62418             .sf-reset .exception_message { margin-left: 3em; display: block; }
62419             .sf-reset .traces li { font-size:12px; padding: 2px 4px; list-style-type:decimal; margin-left:20px; }
62420             .sf-reset .block { background-color:#FFFFFF; padding:10px 28px; margin-bottom:20px;
62421                 -webkit-border-bottom-right-radius: 16px;
62422                 -webkit-border-bottom-left-radius: 16px;
62423                 -moz-border-radius-bottomright: 16px;
62424                 -moz-border-radius-bottomleft: 16px;
62425                 border-bottom-right-radius: 16px;
62426                 border-bottom-left-radius: 16px;
62427                 border-bottom:1px solid #ccc;
62428                 border-right:1px solid #ccc;
62429                 border-left:1px solid #ccc;
62430                 word-wrap: break-word;
62431             }
62432             .sf-reset .block_exception { background-color:#ddd; color: #333; padding:20px;
62433                 -webkit-border-top-left-radius: 16px;
62434                 -webkit-border-top-right-radius: 16px;
62435                 -moz-border-radius-topleft: 16px;
62436                 -moz-border-radius-topright: 16px;
62437                 border-top-left-radius: 16px;
62438                 border-top-right-radius: 16px;
62439                 border-top:1px solid #ccc;
62440                 border-right:1px solid #ccc;
62441                 border-left:1px solid #ccc;
62442                 overflow: hidden;
62443                 word-wrap: break-word;
62444             }
62445             .sf-reset a { background:none; color:#868686; text-decoration:none; }
62446             .sf-reset a:hover { background:none; color:#313131; text-decoration:underline; }
62447             .sf-reset ol { padding: 10px 0; }
62448             .sf-reset h1 { background-color:#FFFFFF; padding: 15px 28px; margin-bottom: 20px;
62449                 -webkit-border-radius: 10px;
62450                 -moz-border-radius: 10px;
62451                 border-radius: 10px;
62452                 border: 1px solid #ccc;
62453             }
62454 EOF;
62455 }
62456
62457 private function decorate($content, $css)
62458 {
62459 return <<<EOF
62460 <!DOCTYPE html>
62461 <html>
62462     <head>
62463         <meta charset="{$this->charset}" />
62464         <meta name="robots" content="noindex,nofollow" />
62465         <style>
62466             /* Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html */
62467             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;}
62468
62469             html { background: #eee; padding: 10px }
62470             img { border: 0; }
62471             #sf-resetcontent { width:970px; margin:0 auto; }
62472             $css
62473         </style>
62474     </head>
62475     <body>
62476         $content
62477     </body>
62478 </html>
62479 EOF;
62480 }
62481
62482 private function formatClass($class)
62483 {
62484 $parts = explode('\\', $class);
62485
62486 return sprintf('<abbr title="%s">%s</abbr>', $class, array_pop($parts));
62487 }
62488
62489 private function formatPath($path, $line)
62490 {
62491 $path = $this->escapeHtml($path);
62492 $file = preg_match('#[^/\\\\]*$#', $path, $file) ? $file[0] : $path;
62493
62494 if ($linkFormat = $this->fileLinkFormat) {
62495 $link = strtr($this->escapeHtml($linkFormat), array('%f' => $path, '%l' => (int) $line));
62496
62497 return sprintf(' in <a href="%s" title="Go to source">%s line %d</a>', $link, $file, $line);
62498 }
62499
62500 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);
62501 }
62502
62503
62504
62505
62506
62507
62508
62509
62510 private function formatArgs(array $args)
62511 {
62512 $result = array();
62513 foreach ($args as $key => $item) {
62514 if ('object' === $item[0]) {
62515 $formattedValue = sprintf('<em>object</em>(%s)', $this->formatClass($item[1]));
62516 } elseif ('array' === $item[0]) {
62517 $formattedValue = sprintf('<em>array</em>(%s)', is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
62518 } elseif ('string' === $item[0]) {
62519 $formattedValue = sprintf("'%s'", $this->escapeHtml($item[1]));
62520 } elseif ('null' === $item[0]) {
62521 $formattedValue = '<em>null</em>';
62522 } elseif ('boolean' === $item[0]) {
62523 $formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>';
62524 } elseif ('resource' === $item[0]) {
62525 $formattedValue = '<em>resource</em>';
62526 } else {
62527 $formattedValue = str_replace("\n", '', var_export($this->escapeHtml((string) $item[1]), true));
62528 }
62529
62530 $result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escapeHtml($key), $formattedValue);
62531 }
62532
62533 return implode(', ', $result);
62534 }
62535
62536
62537
62538
62539
62540
62541 protected static function utf8Htmlize($str)
62542 {
62543 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0.', E_USER_DEPRECATED);
62544
62545 return htmlspecialchars($str, ENT_QUOTES | (\PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), 'UTF-8');
62546 }
62547
62548
62549
62550
62551 private function escapeHtml($str)
62552 {
62553 return htmlspecialchars($str, ENT_QUOTES | (\PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), $this->charset);
62554 }
62555
62556
62557
62558
62559 public function catchOutput($buffer)
62560 {
62561 $this->caughtBuffer = $buffer;
62562
62563 return '';
62564 }
62565
62566
62567
62568
62569 public function cleanOutput($buffer)
62570 {
62571 if ($this->caughtLength) {
62572
62573  $cleanBuffer = substr_replace($buffer, '', 0, $this->caughtLength);
62574 if (isset($cleanBuffer[0])) {
62575 $buffer = $cleanBuffer;
62576 }
62577 }
62578
62579 return $buffer;
62580 }
62581 }
62582 <?php
62583
62584
62585
62586
62587
62588
62589
62590
62591
62592
62593 namespace Symfony\Component\Debug\FatalErrorHandler;
62594
62595 use Symfony\Component\Debug\Exception\ClassNotFoundException;
62596 use Symfony\Component\Debug\Exception\FatalErrorException;
62597 use Symfony\Component\Debug\DebugClassLoader;
62598 use Composer\Autoload\ClassLoader as ComposerClassLoader;
62599 use Symfony\Component\ClassLoader\ClassLoader as SymfonyClassLoader;
62600 use Symfony\Component\ClassLoader\UniversalClassLoader as SymfonyUniversalClassLoader;
62601
62602
62603
62604
62605
62606
62607 class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
62608 {
62609
62610
62611
62612 public function handleError(array $error, FatalErrorException $exception)
62613 {
62614 $messageLen = strlen($error['message']);
62615 $notFoundSuffix = '\' not found';
62616 $notFoundSuffixLen = strlen($notFoundSuffix);
62617 if ($notFoundSuffixLen > $messageLen) {
62618 return;
62619 }
62620
62621 if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
62622 return;
62623 }
62624
62625 foreach (array('class', 'interface', 'trait') as $typeName) {
62626 $prefix = ucfirst($typeName).' \'';
62627 $prefixLen = strlen($prefix);
62628 if (0 !== strpos($error['message'], $prefix)) {
62629 continue;
62630 }
62631
62632 $fullyQualifiedClassName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);
62633 if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) {
62634 $className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1);
62635 $namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex);
62636 $message = sprintf('Attempted to load %s "%s" from namespace "%s".', $typeName, $className, $namespacePrefix);
62637 $tail = ' for another namespace?';
62638 } else {
62639 $className = $fullyQualifiedClassName;
62640 $message = sprintf('Attempted to load %s "%s" from the global namespace.', $typeName, $className);
62641 $tail = '?';
62642 }
62643
62644 if ($candidates = $this->getClassCandidates($className)) {
62645 $tail = array_pop($candidates).'"?';
62646 if ($candidates) {
62647 $tail = ' for e.g. "'.implode('", "', $candidates).'" or "'.$tail;
62648 } else {
62649 $tail = ' for "'.$tail;
62650 }
62651 }
62652 $message .= "\nDid you forget a \"use\" statement".$tail;
62653
62654 return new ClassNotFoundException($message, $exception);
62655 }
62656 }
62657
62658
62659
62660
62661
62662
62663
62664
62665
62666
62667
62668 private function getClassCandidates($class)
62669 {
62670 if (!is_array($functions = spl_autoload_functions())) {
62671 return array();
62672 }
62673
62674
62675  $classes = array();
62676
62677 foreach ($functions as $function) {
62678 if (!is_array($function)) {
62679 continue;
62680 }
62681
62682  if ($function[0] instanceof DebugClassLoader) {
62683 $function = $function[0]->getClassLoader();
62684
62685
62686  if (is_object($function)) {
62687 $function = array($function);
62688 }
62689
62690 if (!is_array($function)) {
62691 continue;
62692 }
62693 }
62694
62695 if ($function[0] instanceof ComposerClassLoader || $function[0] instanceof SymfonyClassLoader || $function[0] instanceof SymfonyUniversalClassLoader) {
62696 foreach ($function[0]->getPrefixes() as $prefix => $paths) {
62697 foreach ($paths as $path) {
62698 $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
62699 }
62700 }
62701 }
62702 if ($function[0] instanceof ComposerClassLoader) {
62703 foreach ($function[0]->getPrefixesPsr4() as $prefix => $paths) {
62704 foreach ($paths as $path) {
62705 $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
62706 }
62707 }
62708 }
62709 }
62710
62711 return array_unique($classes);
62712 }
62713
62714
62715
62716
62717
62718
62719
62720
62721 private function findClassInPath($path, $class, $prefix)
62722 {
62723 if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) {
62724 return array();
62725 }
62726
62727 $classes = array();
62728 $filename = $class.'.php';
62729 foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
62730 if ($filename == $file->getFileName() && $class = $this->convertFileToClass($path, $file->getPathName(), $prefix)) {
62731 $classes[] = $class;
62732 }
62733 }
62734
62735 return $classes;
62736 }
62737
62738
62739
62740
62741
62742
62743
62744
62745 private function convertFileToClass($path, $file, $prefix)
62746 {
62747 $candidates = array(
62748
62749  $namespacedClass = str_replace(array($path.DIRECTORY_SEPARATOR, '.php', '/'), array('', '', '\\'), $file),
62750
62751  $prefix.$namespacedClass,
62752
62753  $prefix.'\\'.$namespacedClass,
62754
62755  str_replace('\\', '_', $namespacedClass),
62756
62757  str_replace('\\', '_', $prefix.$namespacedClass),
62758
62759  str_replace('\\', '_', $prefix.'\\'.$namespacedClass),
62760 );
62761
62762 if ($prefix) {
62763 $candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); });
62764 }
62765
62766
62767  
62768  
62769  foreach ($candidates as $candidate) {
62770 if ($this->classExists($candidate)) {
62771 return $candidate;
62772 }
62773 }
62774
62775 require_once $file;
62776
62777 foreach ($candidates as $candidate) {
62778 if ($this->classExists($candidate)) {
62779 return $candidate;
62780 }
62781 }
62782 }
62783
62784
62785
62786
62787
62788
62789 private function classExists($class)
62790 {
62791 return class_exists($class, false) || interface_exists($class, false) || (function_exists('trait_exists') && trait_exists($class, false));
62792 }
62793 }
62794 <?php
62795
62796
62797
62798
62799
62800
62801
62802
62803
62804
62805 namespace Symfony\Component\Debug\FatalErrorHandler;
62806
62807 use Symfony\Component\Debug\Exception\FatalErrorException;
62808
62809
62810
62811
62812
62813
62814 interface FatalErrorHandlerInterface
62815 {
62816
62817
62818
62819
62820
62821
62822
62823
62824 public function handleError(array $error, FatalErrorException $exception);
62825 }
62826 <?php
62827
62828
62829
62830
62831
62832
62833
62834
62835
62836
62837 namespace Symfony\Component\Debug\FatalErrorHandler;
62838
62839 use Symfony\Component\Debug\Exception\UndefinedFunctionException;
62840 use Symfony\Component\Debug\Exception\FatalErrorException;
62841
62842
62843
62844
62845
62846
62847 class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface
62848 {
62849
62850
62851
62852 public function handleError(array $error, FatalErrorException $exception)
62853 {
62854 $messageLen = strlen($error['message']);
62855 $notFoundSuffix = '()';
62856 $notFoundSuffixLen = strlen($notFoundSuffix);
62857 if ($notFoundSuffixLen > $messageLen) {
62858 return;
62859 }
62860
62861 if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
62862 return;
62863 }
62864
62865 $prefix = 'Call to undefined function ';
62866 $prefixLen = strlen($prefix);
62867 if (0 !== strpos($error['message'], $prefix)) {
62868 return;
62869 }
62870
62871 $fullyQualifiedFunctionName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);
62872 if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedFunctionName, '\\')) {
62873 $functionName = substr($fullyQualifiedFunctionName, $namespaceSeparatorIndex + 1);
62874 $namespacePrefix = substr($fullyQualifiedFunctionName, 0, $namespaceSeparatorIndex);
62875 $message = sprintf('Attempted to call function "%s" from namespace "%s".', $functionName, $namespacePrefix);
62876 } else {
62877 $functionName = $fullyQualifiedFunctionName;
62878 $message = sprintf('Attempted to call function "%s" from the global namespace.', $functionName);
62879 }
62880
62881 $candidates = array();
62882 foreach (get_defined_functions() as $type => $definedFunctionNames) {
62883 foreach ($definedFunctionNames as $definedFunctionName) {
62884 if (false !== $namespaceSeparatorIndex = strrpos($definedFunctionName, '\\')) {
62885 $definedFunctionNameBasename = substr($definedFunctionName, $namespaceSeparatorIndex + 1);
62886 } else {
62887 $definedFunctionNameBasename = $definedFunctionName;
62888 }
62889
62890 if ($definedFunctionNameBasename === $functionName) {
62891 $candidates[] = '\\'.$definedFunctionName;
62892 }
62893 }
62894 }
62895
62896 if ($candidates) {
62897 sort($candidates);
62898 $last = array_pop($candidates).'"?';
62899 if ($candidates) {
62900 $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
62901 } else {
62902 $candidates = '"'.$last;
62903 }
62904 $message .= "\nDid you mean to call ".$candidates;
62905 }
62906
62907 return new UndefinedFunctionException($message, $exception);
62908 }
62909 }
62910 <?php
62911
62912
62913
62914
62915
62916
62917
62918
62919
62920
62921 namespace Symfony\Component\Debug\FatalErrorHandler;
62922
62923 use Symfony\Component\Debug\Exception\FatalErrorException;
62924 use Symfony\Component\Debug\Exception\UndefinedMethodException;
62925
62926
62927
62928
62929
62930
62931 class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface
62932 {
62933
62934
62935
62936 public function handleError(array $error, FatalErrorException $exception)
62937 {
62938 preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $error['message'], $matches);
62939 if (!$matches) {
62940 return;
62941 }
62942
62943 $className = $matches[1];
62944 $methodName = $matches[2];
62945
62946 $message = sprintf('Attempted to call an undefined method named "%s" of class "%s".', $methodName, $className);
62947
62948 if (!class_exists($className) || null === $methods = get_class_methods($className)) {
62949
62950  return new UndefinedMethodException($message, $exception);
62951 }
62952
62953 $candidates = array();
62954 foreach ($methods as $definedMethodName) {
62955 $lev = levenshtein($methodName, $definedMethodName);
62956 if ($lev <= strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) {
62957 $candidates[] = $definedMethodName;
62958 }
62959 }
62960
62961 if ($candidates) {
62962 sort($candidates);
62963 $last = array_pop($candidates).'"?';
62964 if ($candidates) {
62965 $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
62966 } else {
62967 $candidates = '"'.$last;
62968 }
62969
62970 $message .= "\nDid you mean to call ".$candidates;
62971 }
62972
62973 return new UndefinedMethodException($message, $exception);
62974 }
62975 }
62976 Copyright (c) 2004-2017 Fabien Potencier
62977
62978 Permission is hereby granted, free of charge, to any person obtaining a copy
62979 of this software and associated documentation files (the "Software"), to deal
62980 in the Software without restriction, including without limitation the rights
62981 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
62982 copies of the Software, and to permit persons to whom the Software is furnished
62983 to do so, subject to the following conditions:
62984
62985 The above copyright notice and this permission notice shall be included in all
62986 copies or substantial portions of the Software.
62987
62988 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
62989 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
62990 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
62991 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
62992 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
62993 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
62994 THE SOFTWARE.
62995 <?php
62996
62997
62998
62999
63000
63001
63002
63003
63004
63005
63006 namespace Symfony\Component\Filesystem\Exception;
63007
63008
63009
63010
63011
63012
63013 interface ExceptionInterface
63014 {
63015 }
63016 <?php
63017
63018
63019
63020
63021
63022
63023
63024
63025
63026
63027 namespace Symfony\Component\Filesystem\Exception;
63028
63029
63030
63031
63032
63033
63034
63035 class FileNotFoundException extends IOException
63036 {
63037 public function __construct($message = null, $code = 0, \Exception $previous = null, $path = null)
63038 {
63039 if (null === $message) {
63040 if (null === $path) {
63041 $message = 'File could not be found.';
63042 } else {
63043 $message = sprintf('File "%s" could not be found.', $path);
63044 }
63045 }
63046
63047 parent::__construct($message, $code, $previous, $path);
63048 }
63049 }
63050 <?php
63051
63052
63053
63054
63055
63056
63057
63058
63059
63060
63061 namespace Symfony\Component\Filesystem\Exception;
63062
63063
63064
63065
63066
63067
63068
63069
63070 class IOException extends \RuntimeException implements IOExceptionInterface
63071 {
63072 private $path;
63073
63074 public function __construct($message, $code = 0, \Exception $previous = null, $path = null)
63075 {
63076 $this->path = $path;
63077
63078 parent::__construct($message, $code, $previous);
63079 }
63080
63081
63082
63083
63084 public function getPath()
63085 {
63086 return $this->path;
63087 }
63088 }
63089 <?php
63090
63091
63092
63093
63094
63095
63096
63097
63098
63099
63100 namespace Symfony\Component\Filesystem\Exception;
63101
63102
63103
63104
63105
63106
63107 interface IOExceptionInterface extends ExceptionInterface
63108 {
63109
63110
63111
63112
63113
63114 public function getPath();
63115 }
63116 <?php
63117
63118
63119
63120
63121
63122
63123
63124
63125
63126
63127 namespace Symfony\Component\Filesystem;
63128
63129 use Symfony\Component\Filesystem\Exception\IOException;
63130 use Symfony\Component\Filesystem\Exception\FileNotFoundException;
63131
63132
63133
63134
63135
63136
63137 class Filesystem
63138 {
63139
63140
63141
63142
63143
63144
63145
63146
63147
63148
63149
63150
63151
63152
63153 public function copy($originFile, $targetFile, $overwriteNewerFiles = false)
63154 {
63155 $originIsLocal = stream_is_local($originFile) || 0 === stripos($originFile, 'file://');
63156 if ($originIsLocal && !is_file($originFile)) {
63157 throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile);
63158 }
63159
63160 $this->mkdir(dirname($targetFile));
63161
63162 $doCopy = true;
63163 if (!$overwriteNewerFiles && null === parse_url($originFile, PHP_URL_HOST) && is_file($targetFile)) {
63164 $doCopy = filemtime($originFile) > filemtime($targetFile);
63165 }
63166
63167 if ($doCopy) {
63168
63169  if (false === $source = @fopen($originFile, 'r')) {
63170 throw new IOException(sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading.', $originFile, $targetFile), 0, null, $originFile);
63171 }
63172
63173
63174  if (false === $target = @fopen($targetFile, 'w', null, stream_context_create(array('ftp' => array('overwrite' => true))))) {
63175 throw new IOException(sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing.', $originFile, $targetFile), 0, null, $originFile);
63176 }
63177
63178 $bytesCopied = stream_copy_to_stream($source, $target);
63179 fclose($source);
63180 fclose($target);
63181 unset($source, $target);
63182
63183 if (!is_file($targetFile)) {
63184 throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile);
63185 }
63186
63187 if ($originIsLocal) {
63188
63189  @chmod($targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111));
63190
63191 if ($bytesCopied !== $bytesOrigin = filesize($originFile)) {
63192 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);
63193 }
63194 }
63195 }
63196 }
63197
63198
63199
63200
63201
63202
63203
63204
63205
63206 public function mkdir($dirs, $mode = 0777)
63207 {
63208 foreach ($this->toIterator($dirs) as $dir) {
63209 if (is_dir($dir)) {
63210 continue;
63211 }
63212
63213 if (true !== @mkdir($dir, $mode, true)) {
63214 $error = error_get_last();
63215 if (!is_dir($dir)) {
63216
63217  if ($error) {
63218 throw new IOException(sprintf('Failed to create "%s": %s.', $dir, $error['message']), 0, null, $dir);
63219 }
63220 throw new IOException(sprintf('Failed to create "%s"', $dir), 0, null, $dir);
63221 }
63222 }
63223 }
63224 }
63225
63226
63227
63228
63229
63230
63231
63232
63233 public function exists($files)
63234 {
63235 foreach ($this->toIterator($files) as $file) {
63236 if ('\\' === DIRECTORY_SEPARATOR && strlen($file) > 258) {
63237 throw new IOException('Could not check if file exist because path length exceeds 258 characters.', 0, null, $file);
63238 }
63239
63240 if (!file_exists($file)) {
63241 return false;
63242 }
63243 }
63244
63245 return true;
63246 }
63247
63248
63249
63250
63251
63252
63253
63254
63255
63256
63257 public function touch($files, $time = null, $atime = null)
63258 {
63259 foreach ($this->toIterator($files) as $file) {
63260 $touch = $time ? @touch($file, $time, $atime) : @touch($file);
63261 if (true !== $touch) {
63262 throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file);
63263 }
63264 }
63265 }
63266
63267
63268
63269
63270
63271
63272
63273
63274 public function remove($files)
63275 {
63276 if ($files instanceof \Traversable) {
63277 $files = iterator_to_array($files, false);
63278 } elseif (!is_array($files)) {
63279 $files = array($files);
63280 }
63281 $files = array_reverse($files);
63282 foreach ($files as $file) {
63283 if (is_link($file)) {
63284
63285  if (!@(unlink($file) || '\\' !== DIRECTORY_SEPARATOR || rmdir($file)) && file_exists($file)) {
63286 $error = error_get_last();
63287 throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, $error['message']));
63288 }
63289 } elseif (is_dir($file)) {
63290 $this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS));
63291
63292 if (!@rmdir($file) && file_exists($file)) {
63293 $error = error_get_last();
63294 throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, $error['message']));
63295 }
63296 } elseif (!@unlink($file) && file_exists($file)) {
63297 $error = error_get_last();
63298 throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, $error['message']));
63299 }
63300 }
63301 }
63302
63303
63304
63305
63306
63307
63308
63309
63310
63311
63312
63313 public function chmod($files, $mode, $umask = 0000, $recursive = false)
63314 {
63315 foreach ($this->toIterator($files) as $file) {
63316 if (true !== @chmod($file, $mode & ~$umask)) {
63317 throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file);
63318 }
63319 if ($recursive && is_dir($file) && !is_link($file)) {
63320 $this->chmod(new \FilesystemIterator($file), $mode, $umask, true);
63321 }
63322 }
63323 }
63324
63325
63326
63327
63328
63329
63330
63331
63332
63333
63334 public function chown($files, $user, $recursive = false)
63335 {
63336 foreach ($this->toIterator($files) as $file) {
63337 if ($recursive && is_dir($file) && !is_link($file)) {
63338 $this->chown(new \FilesystemIterator($file), $user, true);
63339 }
63340 if (is_link($file) && function_exists('lchown')) {
63341 if (true !== @lchown($file, $user)) {
63342 throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
63343 }
63344 } else {
63345 if (true !== @chown($file, $user)) {
63346 throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
63347 }
63348 }
63349 }
63350 }
63351
63352
63353
63354
63355
63356
63357
63358
63359
63360
63361 public function chgrp($files, $group, $recursive = false)
63362 {
63363 foreach ($this->toIterator($files) as $file) {
63364 if ($recursive && is_dir($file) && !is_link($file)) {
63365 $this->chgrp(new \FilesystemIterator($file), $group, true);
63366 }
63367 if (is_link($file) && function_exists('lchgrp')) {
63368 if (true !== @lchgrp($file, $group) || (defined('HHVM_VERSION') && !posix_getgrnam($group))) {
63369 throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
63370 }
63371 } else {
63372 if (true !== @chgrp($file, $group)) {
63373 throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
63374 }
63375 }
63376 }
63377 }
63378
63379
63380
63381
63382
63383
63384
63385
63386
63387
63388
63389 public function rename($origin, $target, $overwrite = false)
63390 {
63391
63392  if (!$overwrite && $this->isReadable($target)) {
63393 throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target);
63394 }
63395
63396 if (true !== @rename($origin, $target)) {
63397 if (is_dir($origin)) {
63398
63399  $this->mirror($origin, $target, null, array('override' => $overwrite, 'delete' => $overwrite));
63400 $this->remove($origin);
63401
63402 return;
63403 }
63404 throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target);
63405 }
63406 }
63407
63408
63409
63410
63411
63412
63413
63414
63415
63416
63417 private function isReadable($filename)
63418 {
63419 if ('\\' === DIRECTORY_SEPARATOR && strlen($filename) > 258) {
63420 throw new IOException('Could not check if file is readable because path length exceeds 258 characters.', 0, null, $filename);
63421 }
63422
63423 return is_readable($filename);
63424 }
63425
63426
63427
63428
63429
63430
63431
63432
63433
63434
63435 public function symlink($originDir, $targetDir, $copyOnWindows = false)
63436 {
63437 if ('\\' === DIRECTORY_SEPARATOR) {
63438 $originDir = strtr($originDir, '/', '\\');
63439 $targetDir = strtr($targetDir, '/', '\\');
63440
63441 if ($copyOnWindows) {
63442 $this->mirror($originDir, $targetDir);
63443
63444 return;
63445 }
63446 }
63447
63448 $this->mkdir(dirname($targetDir));
63449
63450 $ok = false;
63451 if (is_link($targetDir)) {
63452 if (readlink($targetDir) != $originDir) {
63453 $this->remove($targetDir);
63454 } else {
63455 $ok = true;
63456 }
63457 }
63458
63459 if (!$ok && true !== @symlink($originDir, $targetDir)) {
63460 $report = error_get_last();
63461 if (is_array($report)) {
63462 if ('\\' === DIRECTORY_SEPARATOR && false !== strpos($report['message'], 'error code(1314)')) {
63463 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);
63464 }
63465 }
63466 throw new IOException(sprintf('Failed to create symbolic link from "%s" to "%s".', $originDir, $targetDir), 0, null, $targetDir);
63467 }
63468 }
63469
63470
63471
63472
63473
63474
63475
63476
63477
63478 public function makePathRelative($endPath, $startPath)
63479 {
63480
63481  if ('\\' === DIRECTORY_SEPARATOR) {
63482 $endPath = str_replace('\\', '/', $endPath);
63483 $startPath = str_replace('\\', '/', $startPath);
63484 }
63485
63486
63487  $startPathArr = explode('/', trim($startPath, '/'));
63488 $endPathArr = explode('/', trim($endPath, '/'));
63489
63490 if ('/' !== $startPath[0]) {
63491 array_shift($startPathArr);
63492 }
63493
63494 if ('/' !== $endPath[0]) {
63495 array_shift($endPathArr);
63496 }
63497
63498 $normalizePathArray = function ($pathSegments) {
63499 $result = array();
63500
63501 foreach ($pathSegments as $segment) {
63502 if ('..' === $segment) {
63503 array_pop($result);
63504 } else {
63505 $result[] = $segment;
63506 }
63507 }
63508
63509 return $result;
63510 };
63511
63512 $startPathArr = $normalizePathArray($startPathArr);
63513 $endPathArr = $normalizePathArray($endPathArr);
63514
63515
63516  $index = 0;
63517 while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) {
63518 ++$index;
63519 }
63520
63521
63522  if (count($startPathArr) === 1 && $startPathArr[0] === '') {
63523 $depth = 0;
63524 } else {
63525 $depth = count($startPathArr) - $index;
63526 }
63527
63528
63529  if ('/' === $startPath[0] && 0 === $index && 0 === $depth) {
63530 $traverser = '';
63531 } else {
63532
63533  $traverser = str_repeat('../', $depth);
63534 }
63535
63536 $endPathRemainder = implode('/', array_slice($endPathArr, $index));
63537
63538
63539  $relativePath = $traverser.('' !== $endPathRemainder ? $endPathRemainder.'/' : '');
63540
63541 return '' === $relativePath ? './' : $relativePath;
63542 }
63543
63544
63545
63546
63547
63548
63549
63550
63551
63552
63553
63554
63555
63556
63557
63558 public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array())
63559 {
63560 $targetDir = rtrim($targetDir, '/\\');
63561 $originDir = rtrim($originDir, '/\\');
63562
63563
63564  if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) {
63565 $deleteIterator = $iterator;
63566 if (null === $deleteIterator) {
63567 $flags = \FilesystemIterator::SKIP_DOTS;
63568 $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST);
63569 }
63570 foreach ($deleteIterator as $file) {
63571 $origin = str_replace($targetDir, $originDir, $file->getPathname());
63572 if (!$this->exists($origin)) {
63573 $this->remove($file);
63574 }
63575 }
63576 }
63577
63578 $copyOnWindows = false;
63579 if (isset($options['copy_on_windows'])) {
63580 $copyOnWindows = $options['copy_on_windows'];
63581 }
63582
63583 if (null === $iterator) {
63584 $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS;
63585 $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST);
63586 }
63587
63588 if ($this->exists($originDir)) {
63589 $this->mkdir($targetDir);
63590 }
63591
63592 foreach ($iterator as $file) {
63593 $target = str_replace($originDir, $targetDir, $file->getPathname());
63594
63595 if ($copyOnWindows) {
63596 if (is_file($file)) {
63597 $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
63598 } elseif (is_dir($file)) {
63599 $this->mkdir($target);
63600 } else {
63601 throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
63602 }
63603 } else {
63604 if (is_link($file)) {
63605 $this->symlink($file->getLinkTarget(), $target);
63606 } elseif (is_dir($file)) {
63607 $this->mkdir($target);
63608 } elseif (is_file($file)) {
63609 $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
63610 } else {
63611 throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
63612 }
63613 }
63614 }
63615 }
63616
63617
63618
63619
63620
63621
63622
63623
63624 public function isAbsolutePath($file)
63625 {
63626 return strspn($file, '/\\', 0, 1)
63627 || (strlen($file) > 3 && ctype_alpha($file[0])
63628 && substr($file, 1, 1) === ':'
63629 && strspn($file, '/\\', 2, 1)
63630 )
63631 || null !== parse_url($file, PHP_URL_SCHEME)
63632 ;
63633 }
63634
63635
63636
63637
63638
63639
63640
63641
63642
63643
63644 public function tempnam($dir, $prefix)
63645 {
63646 list($scheme, $hierarchy) = $this->getSchemeAndHierarchy($dir);
63647
63648
63649  if (null === $scheme || 'file' === $scheme || 'gs' === $scheme) {
63650 $tmpFile = @tempnam($hierarchy, $prefix);
63651
63652
63653  if (false !== $tmpFile) {
63654 if (null !== $scheme && 'gs' !== $scheme) {
63655 return $scheme.'://'.$tmpFile;
63656 }
63657
63658 return $tmpFile;
63659 }
63660
63661 throw new IOException('A temporary file could not be created.');
63662 }
63663
63664
63665  for ($i = 0; $i < 10; ++$i) {
63666
63667  $tmpFile = $dir.'/'.$prefix.uniqid(mt_rand(), true);
63668
63669
63670  
63671  $handle = @fopen($tmpFile, 'x+');
63672
63673
63674  if (false === $handle) {
63675 continue;
63676 }
63677
63678
63679  @fclose($handle);
63680
63681 return $tmpFile;
63682 }
63683
63684 throw new IOException('A temporary file could not be created.');
63685 }
63686
63687
63688
63689
63690
63691
63692
63693
63694
63695
63696
63697 public function dumpFile($filename, $content, $mode = 0666)
63698 {
63699 $dir = dirname($filename);
63700
63701 if (!is_dir($dir)) {
63702 $this->mkdir($dir);
63703 }
63704
63705 if (!is_writable($dir)) {
63706 throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir);
63707 }
63708
63709 $tmpFile = $this->tempnam($dir, basename($filename));
63710
63711 if (false === @file_put_contents($tmpFile, $content)) {
63712 throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
63713 }
63714
63715 if (null !== $mode) {
63716 if (func_num_args() > 2) {
63717 @trigger_error('Support for modifying file permissions is deprecated since version 2.3.12 and will be removed in 3.0.', E_USER_DEPRECATED);
63718 }
63719
63720 $this->chmod($tmpFile, $mode);
63721 } elseif (file_exists($filename)) {
63722 @chmod($tmpFile, fileperms($filename));
63723 }
63724
63725 $this->rename($tmpFile, $filename, true);
63726 }
63727
63728
63729
63730
63731
63732
63733 private function toIterator($files)
63734 {
63735 if (!$files instanceof \Traversable) {
63736 $files = new \ArrayObject(is_array($files) ? $files : array($files));
63737 }
63738
63739 return $files;
63740 }
63741
63742
63743
63744
63745
63746
63747
63748
63749 private function getSchemeAndHierarchy($filename)
63750 {
63751 $components = explode('://', $filename, 2);
63752
63753 return 2 === count($components) ? array($components[0], $components[1]) : array(null, $components[0]);
63754 }
63755 }
63756 Copyright (c) 2004-2017 Fabien Potencier
63757
63758 Permission is hereby granted, free of charge, to any person obtaining a copy
63759 of this software and associated documentation files (the "Software"), to deal
63760 in the Software without restriction, including without limitation the rights
63761 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
63762 copies of the Software, and to permit persons to whom the Software is furnished
63763 to do so, subject to the following conditions:
63764
63765 The above copyright notice and this permission notice shall be included in all
63766 copies or substantial portions of the Software.
63767
63768 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63769 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
63770 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
63771 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
63772 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
63773 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
63774 THE SOFTWARE.
63775 <?php
63776
63777
63778
63779
63780
63781
63782
63783
63784
63785
63786 namespace Symfony\Component\Filesystem;
63787
63788 use Symfony\Component\Filesystem\Exception\IOException;
63789
63790
63791
63792
63793
63794
63795
63796
63797
63798
63799
63800
63801
63802
63803 class LockHandler
63804 {
63805 private $file;
63806 private $handle;
63807
63808
63809
63810
63811
63812
63813
63814 public function __construct($name, $lockPath = null)
63815 {
63816 $lockPath = $lockPath ?: sys_get_temp_dir();
63817
63818 if (!is_dir($lockPath)) {
63819 $fs = new Filesystem();
63820 $fs->mkdir($lockPath);
63821 }
63822
63823 if (!is_writable($lockPath)) {
63824 throw new IOException(sprintf('The directory "%s" is not writable.', $lockPath), 0, null, $lockPath);
63825 }
63826
63827 $this->file = sprintf('%s/sf.%s.%s.lock', $lockPath, preg_replace('/[^a-z0-9\._-]+/i', '-', $name), hash('sha256', $name));
63828 }
63829
63830
63831
63832
63833
63834
63835
63836
63837
63838
63839 public function lock($blocking = false)
63840 {
63841 if ($this->handle) {
63842 return true;
63843 }
63844
63845 $error = null;
63846
63847
63848  set_error_handler(function ($errno, $msg) use (&$error) {
63849 $error = $msg;
63850 });
63851
63852 if (!$this->handle = fopen($this->file, 'r')) {
63853 if ($this->handle = fopen($this->file, 'x')) {
63854 chmod($this->file, 0444);
63855 } elseif (!$this->handle = fopen($this->file, 'r')) {
63856 usleep(100); 
63857  $this->handle = fopen($this->file, 'r');
63858 }
63859 }
63860 restore_error_handler();
63861
63862 if (!$this->handle) {
63863 throw new IOException($error, 0, null, $this->file);
63864 }
63865
63866
63867  
63868  if (!flock($this->handle, LOCK_EX | ($blocking ? 0 : LOCK_NB))) {
63869 fclose($this->handle);
63870 $this->handle = null;
63871
63872 return false;
63873 }
63874
63875 return true;
63876 }
63877
63878
63879
63880
63881 public function release()
63882 {
63883 if ($this->handle) {
63884 flock($this->handle, LOCK_UN | LOCK_NB);
63885 fclose($this->handle);
63886 $this->handle = null;
63887 }
63888 }
63889 }
63890 <?php
63891
63892
63893
63894
63895
63896
63897
63898
63899
63900
63901 namespace Symfony\Component\Finder\Adapter;
63902
63903 @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);
63904
63905
63906
63907
63908
63909
63910
63911
63912 abstract class AbstractAdapter implements AdapterInterface
63913 {
63914 protected $followLinks = false;
63915 protected $mode = 0;
63916 protected $minDepth = 0;
63917 protected $maxDepth = PHP_INT_MAX;
63918 protected $exclude = array();
63919 protected $names = array();
63920 protected $notNames = array();
63921 protected $contains = array();
63922 protected $notContains = array();
63923 protected $sizes = array();
63924 protected $dates = array();
63925 protected $filters = array();
63926 protected $sort = false;
63927 protected $paths = array();
63928 protected $notPaths = array();
63929 protected $ignoreUnreadableDirs = false;
63930
63931 private static $areSupported = array();
63932
63933
63934
63935
63936 public function isSupported()
63937 {
63938 $name = $this->getName();
63939
63940 if (!array_key_exists($name, self::$areSupported)) {
63941 self::$areSupported[$name] = $this->canBeUsed();
63942 }
63943
63944 return self::$areSupported[$name];
63945 }
63946
63947
63948
63949
63950 public function setFollowLinks($followLinks)
63951 {
63952 $this->followLinks = $followLinks;
63953
63954 return $this;
63955 }
63956
63957
63958
63959
63960 public function setMode($mode)
63961 {
63962 $this->mode = $mode;
63963
63964 return $this;
63965 }
63966
63967
63968
63969
63970 public function setDepths(array $depths)
63971 {
63972 $this->minDepth = 0;
63973 $this->maxDepth = PHP_INT_MAX;
63974
63975 foreach ($depths as $comparator) {
63976 switch ($comparator->getOperator()) {
63977 case '>':
63978 $this->minDepth = $comparator->getTarget() + 1;
63979 break;
63980 case '>=':
63981 $this->minDepth = $comparator->getTarget();
63982 break;
63983 case '<':
63984 $this->maxDepth = $comparator->getTarget() - 1;
63985 break;
63986 case '<=':
63987 $this->maxDepth = $comparator->getTarget();
63988 break;
63989 default:
63990 $this->minDepth = $this->maxDepth = $comparator->getTarget();
63991 }
63992 }
63993
63994 return $this;
63995 }
63996
63997
63998
63999
64000 public function setExclude(array $exclude)
64001 {
64002 $this->exclude = $exclude;
64003
64004 return $this;
64005 }
64006
64007
64008
64009
64010 public function setNames(array $names)
64011 {
64012 $this->names = $names;
64013
64014 return $this;
64015 }
64016
64017
64018
64019
64020 public function setNotNames(array $notNames)
64021 {
64022 $this->notNames = $notNames;
64023
64024 return $this;
64025 }
64026
64027
64028
64029
64030 public function setContains(array $contains)
64031 {
64032 $this->contains = $contains;
64033
64034 return $this;
64035 }
64036
64037
64038
64039
64040 public function setNotContains(array $notContains)
64041 {
64042 $this->notContains = $notContains;
64043
64044 return $this;
64045 }
64046
64047
64048
64049
64050 public function setSizes(array $sizes)
64051 {
64052 $this->sizes = $sizes;
64053
64054 return $this;
64055 }
64056
64057
64058
64059
64060 public function setDates(array $dates)
64061 {
64062 $this->dates = $dates;
64063
64064 return $this;
64065 }
64066
64067
64068
64069
64070 public function setFilters(array $filters)
64071 {
64072 $this->filters = $filters;
64073
64074 return $this;
64075 }
64076
64077
64078
64079
64080 public function setSort($sort)
64081 {
64082 $this->sort = $sort;
64083
64084 return $this;
64085 }
64086
64087
64088
64089
64090 public function setPath(array $paths)
64091 {
64092 $this->paths = $paths;
64093
64094 return $this;
64095 }
64096
64097
64098
64099
64100 public function setNotPath(array $notPaths)
64101 {
64102 $this->notPaths = $notPaths;
64103
64104 return $this;
64105 }
64106
64107
64108
64109
64110 public function ignoreUnreadableDirs($ignore = true)
64111 {
64112 $this->ignoreUnreadableDirs = (bool) $ignore;
64113
64114 return $this;
64115 }
64116
64117
64118
64119
64120
64121
64122
64123
64124
64125
64126
64127
64128 abstract protected function canBeUsed();
64129 }
64130 <?php
64131
64132
64133
64134
64135
64136
64137
64138
64139
64140
64141 namespace Symfony\Component\Finder\Adapter;
64142
64143 @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);
64144
64145 use Symfony\Component\Finder\Exception\AccessDeniedException;
64146 use Symfony\Component\Finder\Iterator;
64147 use Symfony\Component\Finder\Shell\Shell;
64148 use Symfony\Component\Finder\Expression\Expression;
64149 use Symfony\Component\Finder\Shell\Command;
64150 use Symfony\Component\Finder\Comparator\NumberComparator;
64151 use Symfony\Component\Finder\Comparator\DateComparator;
64152
64153
64154
64155
64156
64157
64158
64159
64160 abstract class AbstractFindAdapter extends AbstractAdapter
64161 {
64162
64163
64164
64165 protected $shell;
64166
64167
64168
64169
64170 public function __construct()
64171 {
64172 $this->shell = new Shell();
64173 }
64174
64175
64176
64177
64178 public function searchInDirectory($dir)
64179 {
64180
64181  $dir = realpath($dir);
64182
64183
64184  if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) {
64185 return new Iterator\FilePathsIterator(array(), $dir);
64186 }
64187
64188 $command = Command::create();
64189 $find = $this->buildFindCommand($command, $dir);
64190
64191 if ($this->followLinks) {
64192 $find->add('-follow');
64193 }
64194
64195 $find->add('-mindepth')->add($this->minDepth + 1);
64196
64197 if (PHP_INT_MAX !== $this->maxDepth) {
64198 $find->add('-maxdepth')->add($this->maxDepth + 1);
64199 }
64200
64201 if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) {
64202 $find->add('-type d');
64203 } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) {
64204 $find->add('-type f');
64205 }
64206
64207 $this->buildNamesFiltering($find, $this->names);
64208 $this->buildNamesFiltering($find, $this->notNames, true);
64209 $this->buildPathsFiltering($find, $dir, $this->paths);
64210 $this->buildPathsFiltering($find, $dir, $this->notPaths, true);
64211 $this->buildSizesFiltering($find, $this->sizes);
64212 $this->buildDatesFiltering($find, $this->dates);
64213
64214 $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs');
64215 $useSort = is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut');
64216
64217 if ($useGrep && ($this->contains || $this->notContains)) {
64218 $grep = $command->ins('grep');
64219 $this->buildContentFiltering($grep, $this->contains);
64220 $this->buildContentFiltering($grep, $this->notContains, true);
64221 }
64222
64223 if ($useSort) {
64224 $this->buildSorting($command, $this->sort);
64225 }
64226
64227 $command->setErrorHandler(
64228 $this->ignoreUnreadableDirs
64229
64230  ? function ($stderr) { }
64231 : function ($stderr) { throw new AccessDeniedException($stderr); }
64232 );
64233
64234 $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute());
64235 $iterator = new Iterator\FilePathsIterator($paths, $dir);
64236
64237 if ($this->exclude) {
64238 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
64239 }
64240
64241 if (!$useGrep && ($this->contains || $this->notContains)) {
64242 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
64243 }
64244
64245 if ($this->filters) {
64246 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
64247 }
64248
64249 if (!$useSort && $this->sort) {
64250 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
64251 $iterator = $iteratorAggregate->getIterator();
64252 }
64253
64254 return $iterator;
64255 }
64256
64257
64258
64259
64260 protected function canBeUsed()
64261 {
64262 return $this->shell->testCommand('find');
64263 }
64264
64265
64266
64267
64268
64269
64270
64271 protected function buildFindCommand(Command $command, $dir)
64272 {
64273 return $command
64274 ->ins('find')
64275 ->add('find ')
64276 ->arg($dir)
64277 ->add('-noleaf'); 
64278  }
64279
64280
64281
64282
64283
64284
64285 private function buildNamesFiltering(Command $command, array $names, $not = false)
64286 {
64287 if (0 === count($names)) {
64288 return;
64289 }
64290
64291 $command->add($not ? '-not' : null)->cmd('(');
64292
64293 foreach ($names as $i => $name) {
64294 $expr = Expression::create($name);
64295
64296
64297  if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
64298 $expr = Expression::create($expr->getGlob()->toRegex(false));
64299 }
64300
64301
64302  
64303  
64304  if ($expr->isRegex()) {
64305 $regex = $expr->getRegex();
64306 $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*')
64307 ->setStartFlag(false)
64308 ->setStartJoker(true)
64309 ->replaceJokers('[^/]');
64310 if (!$regex->hasEndFlag() || $regex->hasEndJoker()) {
64311 $regex->setEndJoker(false)->append('[^/]*');
64312 }
64313 }
64314
64315 $command
64316 ->add($i > 0 ? '-or' : null)
64317 ->add($expr->isRegex()
64318 ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
64319 : ($expr->isCaseSensitive() ? '-name' : '-iname')
64320 )
64321 ->arg($expr->renderPattern());
64322 }
64323
64324 $command->cmd(')');
64325 }
64326
64327
64328
64329
64330
64331
64332
64333 private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false)
64334 {
64335 if (0 === count($paths)) {
64336 return;
64337 }
64338
64339 $command->add($not ? '-not' : null)->cmd('(');
64340
64341 foreach ($paths as $i => $path) {
64342 $expr = Expression::create($path);
64343
64344
64345  if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
64346 $expr = Expression::create($expr->getGlob()->toRegex(false));
64347 }
64348
64349
64350  if ($expr->isRegex()) {
64351 $regex = $expr->getRegex();
64352 $regex->prepend($regex->hasStartFlag() ? preg_quote($dir).DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag());
64353 } else {
64354 $expr->prepend('*')->append('*');
64355 }
64356
64357 $command
64358 ->add($i > 0 ? '-or' : null)
64359 ->add($expr->isRegex()
64360 ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
64361 : ($expr->isCaseSensitive() ? '-path' : '-ipath')
64362 )
64363 ->arg($expr->renderPattern());
64364 }
64365
64366 $command->cmd(')');
64367 }
64368
64369
64370
64371
64372
64373 private function buildSizesFiltering(Command $command, array $sizes)
64374 {
64375 foreach ($sizes as $i => $size) {
64376 $command->add($i > 0 ? '-and' : null);
64377
64378 switch ($size->getOperator()) {
64379 case '<=':
64380 $command->add('-size -'.($size->getTarget() + 1).'c');
64381 break;
64382 case '>=':
64383 $command->add('-size +'.($size->getTarget() - 1).'c');
64384 break;
64385 case '>':
64386 $command->add('-size +'.$size->getTarget().'c');
64387 break;
64388 case '!=':
64389 $command->add('-size -'.$size->getTarget().'c');
64390 $command->add('-size +'.$size->getTarget().'c');
64391 break;
64392 case '<':
64393 default:
64394 $command->add('-size -'.$size->getTarget().'c');
64395 }
64396 }
64397 }
64398
64399
64400
64401
64402
64403 private function buildDatesFiltering(Command $command, array $dates)
64404 {
64405 foreach ($dates as $i => $date) {
64406 $command->add($i > 0 ? '-and' : null);
64407
64408 $mins = (int) round((time() - $date->getTarget()) / 60);
64409
64410 if (0 > $mins) {
64411
64412  $command->add(' -mmin -0');
64413
64414  return;
64415 }
64416
64417 switch ($date->getOperator()) {
64418 case '<=':
64419 $command->add('-mmin +'.($mins - 1));
64420 break;
64421 case '>=':
64422 $command->add('-mmin -'.($mins + 1));
64423 break;
64424 case '>':
64425 $command->add('-mmin -'.$mins);
64426 break;
64427 case '!=':
64428 $command->add('-mmin +'.$mins.' -or -mmin -'.$mins);
64429 break;
64430 case '<':
64431 default:
64432 $command->add('-mmin +'.$mins);
64433 }
64434 }
64435 }
64436
64437
64438
64439
64440
64441
64442
64443 private function buildSorting(Command $command, $sort)
64444 {
64445 $this->buildFormatSorting($command, $sort);
64446 }
64447
64448
64449
64450
64451
64452 abstract protected function buildFormatSorting(Command $command, $sort);
64453
64454
64455
64456
64457
64458
64459 abstract protected function buildContentFiltering(Command $command, array $contains, $not = false);
64460 }
64461 <?php
64462
64463
64464
64465
64466
64467
64468
64469
64470
64471
64472 namespace Symfony\Component\Finder\Adapter;
64473
64474
64475
64476
64477
64478
64479 interface AdapterInterface
64480 {
64481
64482
64483
64484
64485
64486 public function setFollowLinks($followLinks);
64487
64488
64489
64490
64491
64492
64493 public function setMode($mode);
64494
64495
64496
64497
64498
64499
64500 public function setExclude(array $exclude);
64501
64502
64503
64504
64505
64506
64507 public function setDepths(array $depths);
64508
64509
64510
64511
64512
64513
64514 public function setNames(array $names);
64515
64516
64517
64518
64519
64520
64521 public function setNotNames(array $notNames);
64522
64523
64524
64525
64526
64527
64528 public function setContains(array $contains);
64529
64530
64531
64532
64533
64534
64535 public function setNotContains(array $notContains);
64536
64537
64538
64539
64540
64541
64542 public function setSizes(array $sizes);
64543
64544
64545
64546
64547
64548
64549 public function setDates(array $dates);
64550
64551
64552
64553
64554
64555
64556 public function setFilters(array $filters);
64557
64558
64559
64560
64561
64562
64563 public function setSort($sort);
64564
64565
64566
64567
64568
64569
64570 public function setPath(array $paths);
64571
64572
64573
64574
64575
64576
64577 public function setNotPath(array $notPaths);
64578
64579
64580
64581
64582
64583
64584 public function ignoreUnreadableDirs($ignore = true);
64585
64586
64587
64588
64589
64590
64591 public function searchInDirectory($dir);
64592
64593
64594
64595
64596
64597
64598 public function isSupported();
64599
64600
64601
64602
64603
64604
64605 public function getName();
64606 }
64607 <?php
64608
64609
64610
64611
64612
64613
64614
64615
64616
64617
64618 namespace Symfony\Component\Finder\Adapter;
64619
64620 @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);
64621
64622 use Symfony\Component\Finder\Shell\Shell;
64623 use Symfony\Component\Finder\Shell\Command;
64624 use Symfony\Component\Finder\Iterator\SortableIterator;
64625 use Symfony\Component\Finder\Expression\Expression;
64626
64627
64628
64629
64630
64631
64632
64633
64634 class BsdFindAdapter extends AbstractFindAdapter
64635 {
64636
64637
64638
64639 public function getName()
64640 {
64641 return 'bsd_find';
64642 }
64643
64644
64645
64646
64647 protected function canBeUsed()
64648 {
64649 return in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed();
64650 }
64651
64652
64653
64654
64655 protected function buildFormatSorting(Command $command, $sort)
64656 {
64657 switch ($sort) {
64658 case SortableIterator::SORT_BY_NAME:
64659 $command->ins('sort')->add('| sort');
64660
64661 return;
64662 case SortableIterator::SORT_BY_TYPE:
64663 $format = '%HT';
64664 break;
64665 case SortableIterator::SORT_BY_ACCESSED_TIME:
64666 $format = '%a';
64667 break;
64668 case SortableIterator::SORT_BY_CHANGED_TIME:
64669 $format = '%c';
64670 break;
64671 case SortableIterator::SORT_BY_MODIFIED_TIME:
64672 $format = '%m';
64673 break;
64674 default:
64675 throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
64676 }
64677
64678 $command
64679 ->add('-print0 | xargs -0 stat -f')
64680 ->arg($format.'%t%N')
64681 ->add('| sort | cut -f 2');
64682 }
64683
64684
64685
64686
64687 protected function buildFindCommand(Command $command, $dir)
64688 {
64689 parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1);
64690
64691 return $command;
64692 }
64693
64694
64695
64696
64697 protected function buildContentFiltering(Command $command, array $contains, $not = false)
64698 {
64699 foreach ($contains as $contain) {
64700 $expr = Expression::create($contain);
64701
64702
64703  $command
64704 ->add('| grep -v \'^$\'')
64705 ->add('| xargs -I{} grep -I')
64706 ->add($expr->isCaseSensitive() ? null : '-i')
64707 ->add($not ? '-L' : '-l')
64708 ->add('-Ee')->arg($expr->renderPattern())
64709 ->add('{}')
64710 ;
64711 }
64712 }
64713 }
64714 <?php
64715
64716
64717
64718
64719
64720
64721
64722
64723
64724
64725 namespace Symfony\Component\Finder\Adapter;
64726
64727 @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);
64728
64729 use Symfony\Component\Finder\Shell\Shell;
64730 use Symfony\Component\Finder\Shell\Command;
64731 use Symfony\Component\Finder\Iterator\SortableIterator;
64732 use Symfony\Component\Finder\Expression\Expression;
64733
64734
64735
64736
64737
64738
64739
64740
64741 class GnuFindAdapter extends AbstractFindAdapter
64742 {
64743
64744
64745
64746 public function getName()
64747 {
64748 return 'gnu_find';
64749 }
64750
64751
64752
64753
64754 protected function buildFormatSorting(Command $command, $sort)
64755 {
64756 switch ($sort) {
64757 case SortableIterator::SORT_BY_NAME:
64758 $command->ins('sort')->add('| sort');
64759
64760 return;
64761 case SortableIterator::SORT_BY_TYPE:
64762 $format = '%y';
64763 break;
64764 case SortableIterator::SORT_BY_ACCESSED_TIME:
64765 $format = '%A@';
64766 break;
64767 case SortableIterator::SORT_BY_CHANGED_TIME:
64768 $format = '%C@';
64769 break;
64770 case SortableIterator::SORT_BY_MODIFIED_TIME:
64771 $format = '%T@';
64772 break;
64773 default:
64774 throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
64775 }
64776
64777 $command
64778 ->get('find')
64779 ->add('-printf')
64780 ->arg($format.' %h/%f\\n')
64781 ->add('| sort | cut')
64782 ->arg('-d ')
64783 ->arg('-f2-')
64784 ;
64785 }
64786
64787
64788
64789
64790 protected function canBeUsed()
64791 {
64792 return $this->shell->getType() === Shell::TYPE_UNIX && parent::canBeUsed();
64793 }
64794
64795
64796
64797
64798 protected function buildFindCommand(Command $command, $dir)
64799 {
64800 return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended');
64801 }
64802
64803
64804
64805
64806 protected function buildContentFiltering(Command $command, array $contains, $not = false)
64807 {
64808 foreach ($contains as $contain) {
64809 $expr = Expression::create($contain);
64810
64811
64812  $command
64813 ->add('| xargs -I{} -r grep -I')
64814 ->add($expr->isCaseSensitive() ? null : '-i')
64815 ->add($not ? '-L' : '-l')
64816 ->add('-Ee')->arg($expr->renderPattern())
64817 ->add('{}')
64818 ;
64819 }
64820 }
64821 }
64822 <?php
64823
64824
64825
64826
64827
64828
64829
64830
64831
64832
64833 namespace Symfony\Component\Finder\Adapter;
64834
64835 @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);
64836
64837 use Symfony\Component\Finder\Iterator;
64838
64839
64840
64841
64842
64843
64844
64845
64846 class PhpAdapter extends AbstractAdapter
64847 {
64848
64849
64850
64851 public function searchInDirectory($dir)
64852 {
64853 $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
64854
64855 if ($this->followLinks) {
64856 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
64857 }
64858
64859 $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
64860
64861 if ($this->exclude) {
64862 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
64863 }
64864
64865 $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
64866
64867 if ($this->minDepth > 0 || $this->maxDepth < PHP_INT_MAX) {
64868 $iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth);
64869 }
64870
64871 if ($this->mode) {
64872 $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
64873 }
64874
64875 if ($this->names || $this->notNames) {
64876 $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
64877 }
64878
64879 if ($this->contains || $this->notContains) {
64880 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
64881 }
64882
64883 if ($this->sizes) {
64884 $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
64885 }
64886
64887 if ($this->dates) {
64888 $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
64889 }
64890
64891 if ($this->filters) {
64892 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
64893 }
64894
64895 if ($this->paths || $this->notPaths) {
64896 $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
64897 }
64898
64899 if ($this->sort) {
64900 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
64901 $iterator = $iteratorAggregate->getIterator();
64902 }
64903
64904 return $iterator;
64905 }
64906
64907
64908
64909
64910 public function getName()
64911 {
64912 return 'php';
64913 }
64914
64915
64916
64917
64918 protected function canBeUsed()
64919 {
64920 return true;
64921 }
64922 }
64923 <?php
64924
64925
64926
64927
64928
64929
64930
64931
64932
64933
64934 namespace Symfony\Component\Finder\Comparator;
64935
64936
64937
64938
64939
64940
64941 class Comparator
64942 {
64943 private $target;
64944 private $operator = '==';
64945
64946
64947
64948
64949
64950
64951 public function getTarget()
64952 {
64953 return $this->target;
64954 }
64955
64956
64957
64958
64959
64960
64961 public function setTarget($target)
64962 {
64963 $this->target = $target;
64964 }
64965
64966
64967
64968
64969
64970
64971 public function getOperator()
64972 {
64973 return $this->operator;
64974 }
64975
64976
64977
64978
64979
64980
64981
64982
64983 public function setOperator($operator)
64984 {
64985 if (!$operator) {
64986 $operator = '==';
64987 }
64988
64989 if (!in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) {
64990 throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
64991 }
64992
64993 $this->operator = $operator;
64994 }
64995
64996
64997
64998
64999
65000
65001
65002
65003 public function test($test)
65004 {
65005 switch ($this->operator) {
65006 case '>':
65007 return $test > $this->target;
65008 case '>=':
65009 return $test >= $this->target;
65010 case '<':
65011 return $test < $this->target;
65012 case '<=':
65013 return $test <= $this->target;
65014 case '!=':
65015 return $test != $this->target;
65016 }
65017
65018 return $test == $this->target;
65019 }
65020 }
65021 <?php
65022
65023
65024
65025
65026
65027
65028
65029
65030
65031
65032 namespace Symfony\Component\Finder\Comparator;
65033
65034
65035
65036
65037
65038
65039 class DateComparator extends Comparator
65040 {
65041
65042
65043
65044
65045
65046
65047
65048 public function __construct($test)
65049 {
65050 if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) {
65051 throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test));
65052 }
65053
65054 try {
65055 $date = new \DateTime($matches[2]);
65056 $target = $date->format('U');
65057 } catch (\Exception $e) {
65058 throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2]));
65059 }
65060
65061 $operator = isset($matches[1]) ? $matches[1] : '==';
65062 if ('since' === $operator || 'after' === $operator) {
65063 $operator = '>';
65064 }
65065
65066 if ('until' === $operator || 'before' === $operator) {
65067 $operator = '<';
65068 }
65069
65070 $this->setOperator($operator);
65071 $this->setTarget($target);
65072 }
65073 }
65074 <?php
65075
65076
65077
65078
65079
65080
65081
65082
65083
65084
65085 namespace Symfony\Component\Finder\Comparator;
65086
65087
65088
65089
65090
65091
65092
65093
65094
65095
65096
65097
65098
65099
65100
65101
65102
65103
65104
65105
65106
65107
65108 class NumberComparator extends Comparator
65109 {
65110
65111
65112
65113
65114
65115
65116
65117 public function __construct($test)
65118 {
65119 if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
65120 throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test));
65121 }
65122
65123 $target = $matches[2];
65124 if (!is_numeric($target)) {
65125 throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target));
65126 }
65127 if (isset($matches[3])) {
65128
65129  switch (strtolower($matches[3])) {
65130 case 'k':
65131 $target *= 1000;
65132 break;
65133 case 'ki':
65134 $target *= 1024;
65135 break;
65136 case 'm':
65137 $target *= 1000000;
65138 break;
65139 case 'mi':
65140 $target *= 1024 * 1024;
65141 break;
65142 case 'g':
65143 $target *= 1000000000;
65144 break;
65145 case 'gi':
65146 $target *= 1024 * 1024 * 1024;
65147 break;
65148 }
65149 }
65150
65151 $this->setTarget($target);
65152 $this->setOperator(isset($matches[1]) ? $matches[1] : '==');
65153 }
65154 }
65155 <?php
65156
65157
65158
65159
65160
65161
65162
65163
65164
65165
65166 namespace Symfony\Component\Finder\Exception;
65167
65168
65169
65170
65171 class AccessDeniedException extends \UnexpectedValueException
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__.'\AdapterFailureException 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
65191
65192
65193
65194
65195
65196
65197
65198 class AdapterFailureException extends \RuntimeException implements ExceptionInterface
65199 {
65200
65201
65202
65203 private $adapter;
65204
65205
65206
65207
65208
65209
65210 public function __construct(AdapterInterface $adapter, $message = null, \Exception $previous = null)
65211 {
65212 $this->adapter = $adapter;
65213 parent::__construct($message ?: 'Search failed with "'.$adapter->getName().'" adapter.', $previous);
65214 }
65215
65216
65217
65218
65219 public function getAdapter()
65220 {
65221 return $this->adapter;
65222 }
65223 }
65224 <?php
65225
65226
65227
65228
65229
65230
65231
65232
65233
65234
65235 namespace Symfony\Component\Finder\Exception;
65236
65237
65238
65239
65240 interface ExceptionInterface
65241 {
65242
65243
65244
65245 public function getAdapter();
65246 }
65247 <?php
65248
65249
65250
65251
65252
65253
65254
65255
65256
65257
65258 namespace Symfony\Component\Finder\Exception;
65259
65260 @trigger_error('The '.__NAMESPACE__.'\OperationNotPermitedException class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65261
65262
65263
65264
65265
65266
65267 class OperationNotPermitedException extends AdapterFailureException
65268 {
65269 }
65270 <?php
65271
65272
65273
65274
65275
65276
65277
65278
65279
65280
65281 namespace Symfony\Component\Finder\Exception;
65282
65283 @trigger_error('The '.__NAMESPACE__.'\ShellCommandFailureException class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65284
65285 use Symfony\Component\Finder\Adapter\AdapterInterface;
65286 use Symfony\Component\Finder\Shell\Command;
65287
65288
65289
65290
65291
65292
65293 class ShellCommandFailureException extends AdapterFailureException
65294 {
65295
65296
65297
65298 private $command;
65299
65300
65301
65302
65303
65304
65305 public function __construct(AdapterInterface $adapter, Command $command, \Exception $previous = null)
65306 {
65307 $this->command = $command;
65308 parent::__construct($adapter, 'Shell command failed: "'.$command->join().'".', $previous);
65309 }
65310
65311
65312
65313
65314 public function getCommand()
65315 {
65316 return $this->command;
65317 }
65318 }
65319 <?php
65320
65321
65322
65323
65324
65325
65326
65327
65328
65329
65330 namespace Symfony\Component\Finder\Expression;
65331
65332 @trigger_error('The '.__NAMESPACE__.'\Expression class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65333
65334
65335
65336
65337 class Expression implements ValueInterface
65338 {
65339 const TYPE_REGEX = 1;
65340 const TYPE_GLOB = 2;
65341
65342
65343
65344
65345 private $value;
65346
65347
65348
65349
65350
65351
65352 public static function create($expr)
65353 {
65354 return new self($expr);
65355 }
65356
65357
65358
65359
65360 public function __construct($expr)
65361 {
65362 try {
65363 $this->value = Regex::create($expr);
65364 } catch (\InvalidArgumentException $e) {
65365 $this->value = new Glob($expr);
65366 }
65367 }
65368
65369
65370
65371
65372 public function __toString()
65373 {
65374 return $this->render();
65375 }
65376
65377
65378
65379
65380 public function render()
65381 {
65382 return $this->value->render();
65383 }
65384
65385
65386
65387
65388 public function renderPattern()
65389 {
65390 return $this->value->renderPattern();
65391 }
65392
65393
65394
65395
65396 public function isCaseSensitive()
65397 {
65398 return $this->value->isCaseSensitive();
65399 }
65400
65401
65402
65403
65404 public function getType()
65405 {
65406 return $this->value->getType();
65407 }
65408
65409
65410
65411
65412 public function prepend($expr)
65413 {
65414 $this->value->prepend($expr);
65415
65416 return $this;
65417 }
65418
65419
65420
65421
65422 public function append($expr)
65423 {
65424 $this->value->append($expr);
65425
65426 return $this;
65427 }
65428
65429
65430
65431
65432 public function isRegex()
65433 {
65434 return self::TYPE_REGEX === $this->value->getType();
65435 }
65436
65437
65438
65439
65440 public function isGlob()
65441 {
65442 return self::TYPE_GLOB === $this->value->getType();
65443 }
65444
65445
65446
65447
65448
65449
65450 public function getGlob()
65451 {
65452 if (self::TYPE_GLOB !== $this->value->getType()) {
65453 throw new \LogicException('Regex can\'t be transformed to glob.');
65454 }
65455
65456 return $this->value;
65457 }
65458
65459
65460
65461
65462 public function getRegex()
65463 {
65464 return self::TYPE_REGEX === $this->value->getType() ? $this->value : $this->value->toRegex();
65465 }
65466 }
65467 <?php
65468
65469
65470
65471
65472
65473
65474
65475
65476
65477
65478 namespace Symfony\Component\Finder\Expression;
65479
65480 @trigger_error('The '.__NAMESPACE__.'\Glob class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65481
65482 use Symfony\Component\Finder\Glob as FinderGlob;
65483
65484
65485
65486
65487 class Glob implements ValueInterface
65488 {
65489
65490
65491
65492 private $pattern;
65493
65494
65495
65496
65497 public function __construct($pattern)
65498 {
65499 $this->pattern = $pattern;
65500 }
65501
65502
65503
65504
65505 public function render()
65506 {
65507 return $this->pattern;
65508 }
65509
65510
65511
65512
65513 public function renderPattern()
65514 {
65515 return $this->pattern;
65516 }
65517
65518
65519
65520
65521 public function getType()
65522 {
65523 return Expression::TYPE_GLOB;
65524 }
65525
65526
65527
65528
65529 public function isCaseSensitive()
65530 {
65531 return true;
65532 }
65533
65534
65535
65536
65537 public function prepend($expr)
65538 {
65539 $this->pattern = $expr.$this->pattern;
65540
65541 return $this;
65542 }
65543
65544
65545
65546
65547 public function append($expr)
65548 {
65549 $this->pattern .= $expr;
65550
65551 return $this;
65552 }
65553
65554
65555
65556
65557
65558
65559 public function isExpandable()
65560 {
65561 return false !== strpos($this->pattern, '{')
65562 && false !== strpos($this->pattern, '}');
65563 }
65564
65565
65566
65567
65568
65569
65570
65571 public function toRegex($strictLeadingDot = true, $strictWildcardSlash = true)
65572 {
65573 $regex = FinderGlob::toRegex($this->pattern, $strictLeadingDot, $strictWildcardSlash, '');
65574
65575 return new Regex($regex);
65576 }
65577 }
65578 <?php
65579
65580
65581
65582
65583
65584
65585
65586
65587
65588
65589 namespace Symfony\Component\Finder\Expression;
65590
65591 @trigger_error('The '.__NAMESPACE__.'\Regex class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65592
65593
65594
65595
65596 class Regex implements ValueInterface
65597 {
65598 const START_FLAG = '^';
65599 const END_FLAG = '$';
65600 const BOUNDARY = '~';
65601 const JOKER = '.*';
65602 const ESCAPING = '\\';
65603
65604
65605
65606
65607 private $pattern;
65608
65609
65610
65611
65612 private $options;
65613
65614
65615
65616
65617 private $startFlag;
65618
65619
65620
65621
65622 private $endFlag;
65623
65624
65625
65626
65627 private $startJoker;
65628
65629
65630
65631
65632 private $endJoker;
65633
65634
65635
65636
65637
65638
65639
65640
65641 public static function create($expr)
65642 {
65643 if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) {
65644 $start = substr($m[1], 0, 1);
65645 $end = substr($m[1], -1);
65646
65647 if (
65648 ($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start))
65649 || ($start === '{' && $end === '}')
65650 || ($start === '(' && $end === ')')
65651 ) {
65652 return new self(substr($m[1], 1, -1), $m[2], $end);
65653 }
65654 }
65655
65656 throw new \InvalidArgumentException('Given expression is not a regex.');
65657 }
65658
65659
65660
65661
65662
65663
65664 public function __construct($pattern, $options = '', $delimiter = null)
65665 {
65666 if (null !== $delimiter) {
65667
65668  $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern);
65669 }
65670
65671 $this->parsePattern($pattern);
65672 $this->options = $options;
65673 }
65674
65675
65676
65677
65678 public function __toString()
65679 {
65680 return $this->render();
65681 }
65682
65683
65684
65685
65686 public function render()
65687 {
65688 return self::BOUNDARY
65689 .$this->renderPattern()
65690 .self::BOUNDARY
65691 .$this->options;
65692 }
65693
65694
65695
65696
65697 public function renderPattern()
65698 {
65699 return ($this->startFlag ? self::START_FLAG : '')
65700 .($this->startJoker ? self::JOKER : '')
65701 .str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern)
65702 .($this->endJoker ? self::JOKER : '')
65703 .($this->endFlag ? self::END_FLAG : '');
65704 }
65705
65706
65707
65708
65709 public function isCaseSensitive()
65710 {
65711 return !$this->hasOption('i');
65712 }
65713
65714
65715
65716
65717 public function getType()
65718 {
65719 return Expression::TYPE_REGEX;
65720 }
65721
65722
65723
65724
65725 public function prepend($expr)
65726 {
65727 $this->pattern = $expr.$this->pattern;
65728
65729 return $this;
65730 }
65731
65732
65733
65734
65735 public function append($expr)
65736 {
65737 $this->pattern .= $expr;
65738
65739 return $this;
65740 }
65741
65742
65743
65744
65745
65746
65747 public function hasOption($option)
65748 {
65749 return false !== strpos($this->options, $option);
65750 }
65751
65752
65753
65754
65755
65756
65757 public function addOption($option)
65758 {
65759 if (!$this->hasOption($option)) {
65760 $this->options .= $option;
65761 }
65762
65763 return $this;
65764 }
65765
65766
65767
65768
65769
65770
65771 public function removeOption($option)
65772 {
65773 $this->options = str_replace($option, '', $this->options);
65774
65775 return $this;
65776 }
65777
65778
65779
65780
65781
65782
65783 public function setStartFlag($startFlag)
65784 {
65785 $this->startFlag = $startFlag;
65786
65787 return $this;
65788 }
65789
65790
65791
65792
65793 public function hasStartFlag()
65794 {
65795 return $this->startFlag;
65796 }
65797
65798
65799
65800
65801
65802
65803 public function setEndFlag($endFlag)
65804 {
65805 $this->endFlag = (bool) $endFlag;
65806
65807 return $this;
65808 }
65809
65810
65811
65812
65813 public function hasEndFlag()
65814 {
65815 return $this->endFlag;
65816 }
65817
65818
65819
65820
65821
65822
65823 public function setStartJoker($startJoker)
65824 {
65825 $this->startJoker = $startJoker;
65826
65827 return $this;
65828 }
65829
65830
65831
65832
65833 public function hasStartJoker()
65834 {
65835 return $this->startJoker;
65836 }
65837
65838
65839
65840
65841
65842
65843 public function setEndJoker($endJoker)
65844 {
65845 $this->endJoker = (bool) $endJoker;
65846
65847 return $this;
65848 }
65849
65850
65851
65852
65853 public function hasEndJoker()
65854 {
65855 return $this->endJoker;
65856 }
65857
65858
65859
65860
65861
65862
65863 public function replaceJokers($replacement)
65864 {
65865 $replace = function ($subject) use ($replacement) {
65866 $subject = $subject[0];
65867 $replace = 0 === substr_count($subject, '\\') % 2;
65868
65869 return $replace ? str_replace('.', $replacement, $subject) : $subject;
65870 };
65871
65872 $this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern);
65873
65874 return $this;
65875 }
65876
65877
65878
65879
65880 private function parsePattern($pattern)
65881 {
65882 if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) {
65883 $pattern = substr($pattern, 1);
65884 }
65885
65886 if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) {
65887 $pattern = substr($pattern, 2);
65888 }
65889
65890 if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) {
65891 $pattern = substr($pattern, 0, -1);
65892 }
65893
65894 if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) {
65895 $pattern = substr($pattern, 0, -2);
65896 }
65897
65898 $this->pattern = $pattern;
65899 }
65900 }
65901 <?php
65902
65903
65904
65905
65906
65907
65908
65909
65910
65911
65912 namespace Symfony\Component\Finder\Expression;
65913
65914 @trigger_error('The '.__NAMESPACE__.'\ValueInterface interface is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65915
65916
65917
65918
65919 interface ValueInterface
65920 {
65921
65922
65923
65924
65925
65926 public function render();
65927
65928
65929
65930
65931
65932
65933 public function renderPattern();
65934
65935
65936
65937
65938
65939
65940 public function isCaseSensitive();
65941
65942
65943
65944
65945
65946
65947 public function getType();
65948
65949
65950
65951
65952
65953
65954 public function prepend($expr);
65955
65956
65957
65958
65959
65960
65961 public function append($expr);
65962 }
65963 <?php
65964
65965
65966
65967
65968
65969
65970
65971
65972
65973
65974 namespace Symfony\Component\Finder;
65975
65976 use Symfony\Component\Finder\Adapter\AdapterInterface;
65977 use Symfony\Component\Finder\Adapter\GnuFindAdapter;
65978 use Symfony\Component\Finder\Adapter\BsdFindAdapter;
65979 use Symfony\Component\Finder\Adapter\PhpAdapter;
65980 use Symfony\Component\Finder\Comparator\DateComparator;
65981 use Symfony\Component\Finder\Comparator\NumberComparator;
65982 use Symfony\Component\Finder\Exception\ExceptionInterface;
65983 use Symfony\Component\Finder\Iterator\CustomFilterIterator;
65984 use Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
65985 use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;
65986 use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
65987 use Symfony\Component\Finder\Iterator\FilecontentFilterIterator;
65988 use Symfony\Component\Finder\Iterator\FilenameFilterIterator;
65989 use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
65990 use Symfony\Component\Finder\Iterator\SortableIterator;
65991
65992
65993
65994
65995
65996
65997
65998
65999
66000
66001
66002
66003
66004
66005 class Finder implements \IteratorAggregate, \Countable
66006 {
66007 const IGNORE_VCS_FILES = 1;
66008 const IGNORE_DOT_FILES = 2;
66009
66010 private $mode = 0;
66011 private $names = array();
66012 private $notNames = array();
66013 private $exclude = array();
66014 private $filters = array();
66015 private $depths = array();
66016 private $sizes = array();
66017 private $followLinks = false;
66018 private $sort = false;
66019 private $ignore = 0;
66020 private $dirs = array();
66021 private $dates = array();
66022 private $iterators = array();
66023 private $contains = array();
66024 private $notContains = array();
66025 private $adapters = null;
66026 private $paths = array();
66027 private $notPaths = array();
66028 private $ignoreUnreadableDirs = false;
66029
66030 private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg');
66031
66032
66033
66034
66035 public function __construct()
66036 {
66037 $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
66038 }
66039
66040
66041
66042
66043
66044
66045 public static function create()
66046 {
66047 return new static();
66048 }
66049
66050
66051
66052
66053
66054
66055
66056
66057
66058
66059
66060 public function addAdapter(AdapterInterface $adapter, $priority = 0)
66061 {
66062 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66063
66064 $this->initDefaultAdapters();
66065
66066 $this->adapters[$adapter->getName()] = array(
66067 'adapter' => $adapter,
66068 'priority' => $priority,
66069 'selected' => false,
66070 );
66071
66072 return $this->sortAdapters();
66073 }
66074
66075
66076
66077
66078
66079
66080
66081
66082 public function useBestAdapter()
66083 {
66084 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66085
66086 $this->initDefaultAdapters();
66087
66088 $this->resetAdapterSelection();
66089
66090 return $this->sortAdapters();
66091 }
66092
66093
66094
66095
66096
66097
66098
66099
66100
66101
66102
66103
66104 public function setAdapter($name)
66105 {
66106 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66107
66108 $this->initDefaultAdapters();
66109
66110 if (!isset($this->adapters[$name])) {
66111 throw new \InvalidArgumentException(sprintf('Adapter "%s" does not exist.', $name));
66112 }
66113
66114 $this->resetAdapterSelection();
66115 $this->adapters[$name]['selected'] = true;
66116
66117 return $this->sortAdapters();
66118 }
66119
66120
66121
66122
66123
66124
66125
66126
66127 public function removeAdapters()
66128 {
66129 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66130
66131 $this->adapters = array();
66132
66133 return $this;
66134 }
66135
66136
66137
66138
66139
66140
66141
66142
66143 public function getAdapters()
66144 {
66145 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66146
66147 $this->initDefaultAdapters();
66148
66149 return array_values(array_map(function (array $adapter) {
66150 return $adapter['adapter'];
66151 }, $this->adapters));
66152 }
66153
66154
66155
66156
66157
66158
66159 public function directories()
66160 {
66161 $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES;
66162
66163 return $this;
66164 }
66165
66166
66167
66168
66169
66170
66171 public function files()
66172 {
66173 $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES;
66174
66175 return $this;
66176 }
66177
66178
66179
66180
66181
66182
66183
66184
66185
66186
66187
66188
66189
66190
66191
66192
66193 public function depth($level)
66194 {
66195 $this->depths[] = new Comparator\NumberComparator($level);
66196
66197 return $this;
66198 }
66199
66200
66201
66202
66203
66204
66205
66206
66207
66208
66209
66210
66211
66212
66213
66214
66215
66216
66217
66218 public function date($date)
66219 {
66220 $this->dates[] = new Comparator\DateComparator($date);
66221
66222 return $this;
66223 }
66224
66225
66226
66227
66228
66229
66230
66231
66232
66233
66234
66235
66236
66237
66238
66239
66240 public function name($pattern)
66241 {
66242 $this->names[] = $pattern;
66243
66244 return $this;
66245 }
66246
66247
66248
66249
66250
66251
66252
66253
66254
66255
66256 public function notName($pattern)
66257 {
66258 $this->notNames[] = $pattern;
66259
66260 return $this;
66261 }
66262
66263
66264
66265
66266
66267
66268
66269
66270
66271
66272
66273
66274
66275
66276
66277 public function contains($pattern)
66278 {
66279 $this->contains[] = $pattern;
66280
66281 return $this;
66282 }
66283
66284
66285
66286
66287
66288
66289
66290
66291
66292
66293
66294
66295
66296
66297
66298 public function notContains($pattern)
66299 {
66300 $this->notContains[] = $pattern;
66301
66302 return $this;
66303 }
66304
66305
66306
66307
66308
66309
66310
66311
66312
66313
66314
66315
66316
66317
66318
66319
66320
66321 public function path($pattern)
66322 {
66323 $this->paths[] = $pattern;
66324
66325 return $this;
66326 }
66327
66328
66329
66330
66331
66332
66333
66334
66335
66336
66337
66338
66339
66340
66341
66342
66343
66344 public function notPath($pattern)
66345 {
66346 $this->notPaths[] = $pattern;
66347
66348 return $this;
66349 }
66350
66351
66352
66353
66354
66355
66356
66357
66358
66359
66360
66361
66362
66363
66364
66365 public function size($size)
66366 {
66367 $this->sizes[] = new Comparator\NumberComparator($size);
66368
66369 return $this;
66370 }
66371
66372
66373
66374
66375
66376
66377
66378
66379
66380
66381 public function exclude($dirs)
66382 {
66383 $this->exclude = array_merge($this->exclude, (array) $dirs);
66384
66385 return $this;
66386 }
66387
66388
66389
66390
66391
66392
66393
66394
66395
66396
66397 public function ignoreDotFiles($ignoreDotFiles)
66398 {
66399 if ($ignoreDotFiles) {
66400 $this->ignore |= static::IGNORE_DOT_FILES;
66401 } else {
66402 $this->ignore &= ~static::IGNORE_DOT_FILES;
66403 }
66404
66405 return $this;
66406 }
66407
66408
66409
66410
66411
66412
66413
66414
66415
66416
66417 public function ignoreVCS($ignoreVCS)
66418 {
66419 if ($ignoreVCS) {
66420 $this->ignore |= static::IGNORE_VCS_FILES;
66421 } else {
66422 $this->ignore &= ~static::IGNORE_VCS_FILES;
66423 }
66424
66425 return $this;
66426 }
66427
66428
66429
66430
66431
66432
66433
66434
66435 public static function addVCSPattern($pattern)
66436 {
66437 foreach ((array) $pattern as $p) {
66438 self::$vcsPatterns[] = $p;
66439 }
66440
66441 self::$vcsPatterns = array_unique(self::$vcsPatterns);
66442 }
66443
66444
66445
66446
66447
66448
66449
66450
66451
66452
66453
66454
66455
66456
66457 public function sort(\Closure $closure)
66458 {
66459 $this->sort = $closure;
66460
66461 return $this;
66462 }
66463
66464
66465
66466
66467
66468
66469
66470
66471
66472
66473 public function sortByName()
66474 {
66475 $this->sort = Iterator\SortableIterator::SORT_BY_NAME;
66476
66477 return $this;
66478 }
66479
66480
66481
66482
66483
66484
66485
66486
66487
66488
66489 public function sortByType()
66490 {
66491 $this->sort = Iterator\SortableIterator::SORT_BY_TYPE;
66492
66493 return $this;
66494 }
66495
66496
66497
66498
66499
66500
66501
66502
66503
66504
66505
66506
66507 public function sortByAccessedTime()
66508 {
66509 $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME;
66510
66511 return $this;
66512 }
66513
66514
66515
66516
66517
66518
66519
66520
66521
66522
66523
66524
66525
66526
66527 public function sortByChangedTime()
66528 {
66529 $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME;
66530
66531 return $this;
66532 }
66533
66534
66535
66536
66537
66538
66539
66540
66541
66542
66543
66544
66545 public function sortByModifiedTime()
66546 {
66547 $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME;
66548
66549 return $this;
66550 }
66551
66552
66553
66554
66555
66556
66557
66558
66559
66560
66561
66562
66563
66564 public function filter(\Closure $closure)
66565 {
66566 $this->filters[] = $closure;
66567
66568 return $this;
66569 }
66570
66571
66572
66573
66574
66575
66576 public function followLinks()
66577 {
66578 $this->followLinks = true;
66579
66580 return $this;
66581 }
66582
66583
66584
66585
66586
66587
66588
66589
66590
66591
66592 public function ignoreUnreadableDirs($ignore = true)
66593 {
66594 $this->ignoreUnreadableDirs = (bool) $ignore;
66595
66596 return $this;
66597 }
66598
66599
66600
66601
66602
66603
66604
66605
66606
66607
66608 public function in($dirs)
66609 {
66610 $resolvedDirs = array();
66611
66612 foreach ((array) $dirs as $dir) {
66613 if (is_dir($dir)) {
66614 $resolvedDirs[] = $dir;
66615 } elseif ($glob = glob($dir, (defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR)) {
66616 $resolvedDirs = array_merge($resolvedDirs, $glob);
66617 } else {
66618 throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir));
66619 }
66620 }
66621
66622 $this->dirs = array_merge($this->dirs, $resolvedDirs);
66623
66624 return $this;
66625 }
66626
66627
66628
66629
66630
66631
66632
66633
66634
66635
66636 public function getIterator()
66637 {
66638 if (0 === count($this->dirs) && 0 === count($this->iterators)) {
66639 throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.');
66640 }
66641
66642 if (1 === count($this->dirs) && 0 === count($this->iterators)) {
66643 return $this->searchInDirectory($this->dirs[0]);
66644 }
66645
66646 $iterator = new \AppendIterator();
66647 foreach ($this->dirs as $dir) {
66648 $iterator->append($this->searchInDirectory($dir));
66649 }
66650
66651 foreach ($this->iterators as $it) {
66652 $iterator->append($it);
66653 }
66654
66655 return $iterator;
66656 }
66657
66658
66659
66660
66661
66662
66663
66664
66665
66666
66667
66668
66669 public function append($iterator)
66670 {
66671 if ($iterator instanceof \IteratorAggregate) {
66672 $this->iterators[] = $iterator->getIterator();
66673 } elseif ($iterator instanceof \Iterator) {
66674 $this->iterators[] = $iterator;
66675 } elseif ($iterator instanceof \Traversable || is_array($iterator)) {
66676 $it = new \ArrayIterator();
66677 foreach ($iterator as $file) {
66678 $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file));
66679 }
66680 $this->iterators[] = $it;
66681 } else {
66682 throw new \InvalidArgumentException('Finder::append() method wrong argument type.');
66683 }
66684
66685 return $this;
66686 }
66687
66688
66689
66690
66691
66692
66693 public function count()
66694 {
66695 return iterator_count($this->getIterator());
66696 }
66697
66698
66699
66700
66701 private function sortAdapters()
66702 {
66703 uasort($this->adapters, function (array $a, array $b) {
66704 if ($a['selected'] || $b['selected']) {
66705 return $a['selected'] ? -1 : 1;
66706 }
66707
66708 return $a['priority'] > $b['priority'] ? -1 : 1;
66709 });
66710
66711 return $this;
66712 }
66713
66714
66715
66716
66717
66718
66719 private function searchInDirectory($dir)
66720 {
66721 if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
66722 $this->exclude = array_merge($this->exclude, self::$vcsPatterns);
66723 }
66724
66725 if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
66726 $this->notPaths[] = '#(^|/)\..+(/|$)#';
66727 }
66728
66729 if ($this->adapters) {
66730 foreach ($this->adapters as $adapter) {
66731 if ($adapter['adapter']->isSupported()) {
66732 try {
66733 return $this
66734 ->buildAdapter($adapter['adapter'])
66735 ->searchInDirectory($dir);
66736 } catch (ExceptionInterface $e) {
66737 }
66738 }
66739 }
66740 }
66741
66742 $minDepth = 0;
66743 $maxDepth = PHP_INT_MAX;
66744
66745 foreach ($this->depths as $comparator) {
66746 switch ($comparator->getOperator()) {
66747 case '>':
66748 $minDepth = $comparator->getTarget() + 1;
66749 break;
66750 case '>=':
66751 $minDepth = $comparator->getTarget();
66752 break;
66753 case '<':
66754 $maxDepth = $comparator->getTarget() - 1;
66755 break;
66756 case '<=':
66757 $maxDepth = $comparator->getTarget();
66758 break;
66759 default:
66760 $minDepth = $maxDepth = $comparator->getTarget();
66761 }
66762 }
66763
66764 $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
66765
66766 if ($this->followLinks) {
66767 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
66768 }
66769
66770 $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
66771
66772 if ($this->exclude) {
66773 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
66774 }
66775
66776 $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
66777
66778 if ($minDepth > 0 || $maxDepth < PHP_INT_MAX) {
66779 $iterator = new Iterator\DepthRangeFilterIterator($iterator, $minDepth, $maxDepth);
66780 }
66781
66782 if ($this->mode) {
66783 $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
66784 }
66785
66786 if ($this->names || $this->notNames) {
66787 $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
66788 }
66789
66790 if ($this->contains || $this->notContains) {
66791 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
66792 }
66793
66794 if ($this->sizes) {
66795 $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
66796 }
66797
66798 if ($this->dates) {
66799 $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
66800 }
66801
66802 if ($this->filters) {
66803 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
66804 }
66805
66806 if ($this->paths || $this->notPaths) {
66807 $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
66808 }
66809
66810 if ($this->sort) {
66811 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
66812 $iterator = $iteratorAggregate->getIterator();
66813 }
66814
66815 return $iterator;
66816 }
66817
66818
66819
66820
66821
66822
66823 private function buildAdapter(AdapterInterface $adapter)
66824 {
66825 return $adapter
66826 ->setFollowLinks($this->followLinks)
66827 ->setDepths($this->depths)
66828 ->setMode($this->mode)
66829 ->setExclude($this->exclude)
66830 ->setNames($this->names)
66831 ->setNotNames($this->notNames)
66832 ->setContains($this->contains)
66833 ->setNotContains($this->notContains)
66834 ->setSizes($this->sizes)
66835 ->setDates($this->dates)
66836 ->setFilters($this->filters)
66837 ->setSort($this->sort)
66838 ->setPath($this->paths)
66839 ->setNotPath($this->notPaths)
66840 ->ignoreUnreadableDirs($this->ignoreUnreadableDirs);
66841 }
66842
66843
66844
66845
66846 private function resetAdapterSelection()
66847 {
66848 $this->adapters = array_map(function (array $properties) {
66849 $properties['selected'] = false;
66850
66851 return $properties;
66852 }, $this->adapters);
66853 }
66854
66855 private function initDefaultAdapters()
66856 {
66857 if (null === $this->adapters) {
66858 $this->adapters = array();
66859 $this
66860 ->addAdapter(new GnuFindAdapter())
66861 ->addAdapter(new BsdFindAdapter())
66862 ->addAdapter(new PhpAdapter(), -50)
66863 ->setAdapter('php')
66864 ;
66865 }
66866 }
66867 }
66868 <?php
66869
66870
66871
66872
66873
66874
66875
66876
66877
66878
66879 namespace Symfony\Component\Finder;
66880
66881
66882
66883
66884
66885
66886
66887
66888
66889
66890
66891
66892
66893
66894
66895
66896
66897
66898
66899
66900
66901
66902
66903 class Glob
66904 {
66905
66906
66907
66908
66909
66910
66911
66912
66913
66914
66915 public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true, $delimiter = '#')
66916 {
66917 $firstByte = true;
66918 $escaping = false;
66919 $inCurlies = 0;
66920 $regex = '';
66921 $sizeGlob = strlen($glob);
66922 for ($i = 0; $i < $sizeGlob; ++$i) {
66923 $car = $glob[$i];
66924 if ($firstByte) {
66925 if ($strictLeadingDot && '.' !== $car) {
66926 $regex .= '(?=[^\.])';
66927 }
66928
66929 $firstByte = false;
66930 }
66931
66932 if ('/' === $car) {
66933 $firstByte = true;
66934 }
66935
66936 if ($delimiter === $car || '.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
66937 $regex .= "\\$car";
66938 } elseif ('*' === $car) {
66939 $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
66940 } elseif ('?' === $car) {
66941 $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.');
66942 } elseif ('{' === $car) {
66943 $regex .= $escaping ? '\\{' : '(';
66944 if (!$escaping) {
66945 ++$inCurlies;
66946 }
66947 } elseif ('}' === $car && $inCurlies) {
66948 $regex .= $escaping ? '}' : ')';
66949 if (!$escaping) {
66950 --$inCurlies;
66951 }
66952 } elseif (',' === $car && $inCurlies) {
66953 $regex .= $escaping ? ',' : '|';
66954 } elseif ('\\' === $car) {
66955 if ($escaping) {
66956 $regex .= '\\\\';
66957 $escaping = false;
66958 } else {
66959 $escaping = true;
66960 }
66961
66962 continue;
66963 } else {
66964 $regex .= $car;
66965 }
66966 $escaping = false;
66967 }
66968
66969 return $delimiter.'^'.$regex.'$'.$delimiter;
66970 }
66971 }
66972 <?php
66973
66974
66975
66976
66977
66978
66979
66980
66981
66982
66983 namespace Symfony\Component\Finder\Iterator;
66984
66985
66986
66987
66988
66989
66990
66991
66992
66993 class CustomFilterIterator extends FilterIterator
66994 {
66995 private $filters = array();
66996
66997
66998
66999
67000
67001
67002
67003
67004
67005 public function __construct(\Iterator $iterator, array $filters)
67006 {
67007 foreach ($filters as $filter) {
67008 if (!is_callable($filter)) {
67009 throw new \InvalidArgumentException('Invalid PHP callback.');
67010 }
67011 }
67012 $this->filters = $filters;
67013
67014 parent::__construct($iterator);
67015 }
67016
67017
67018
67019
67020
67021
67022 public function accept()
67023 {
67024 $fileinfo = $this->current();
67025
67026 foreach ($this->filters as $filter) {
67027 if (false === call_user_func($filter, $fileinfo)) {
67028 return false;
67029 }
67030 }
67031
67032 return true;
67033 }
67034 }
67035 <?php
67036
67037
67038
67039
67040
67041
67042
67043
67044
67045
67046 namespace Symfony\Component\Finder\Iterator;
67047
67048 use Symfony\Component\Finder\Comparator\DateComparator;
67049
67050
67051
67052
67053
67054
67055 class DateRangeFilterIterator extends FilterIterator
67056 {
67057 private $comparators = array();
67058
67059
67060
67061
67062
67063
67064
67065 public function __construct(\Iterator $iterator, array $comparators)
67066 {
67067 $this->comparators = $comparators;
67068
67069 parent::__construct($iterator);
67070 }
67071
67072
67073
67074
67075
67076
67077 public function accept()
67078 {
67079 $fileinfo = $this->current();
67080
67081 if (!file_exists($fileinfo->getPathname())) {
67082 return false;
67083 }
67084
67085 $filedate = $fileinfo->getMTime();
67086 foreach ($this->comparators as $compare) {
67087 if (!$compare->test($filedate)) {
67088 return false;
67089 }
67090 }
67091
67092 return true;
67093 }
67094 }
67095 <?php
67096
67097
67098
67099
67100
67101
67102
67103
67104
67105
67106 namespace Symfony\Component\Finder\Iterator;
67107
67108
67109
67110
67111
67112
67113 class DepthRangeFilterIterator extends FilterIterator
67114 {
67115 private $minDepth = 0;
67116
67117
67118
67119
67120
67121
67122
67123
67124 public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX)
67125 {
67126 $this->minDepth = $minDepth;
67127 $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth);
67128
67129 parent::__construct($iterator);
67130 }
67131
67132
67133
67134
67135
67136
67137 public function accept()
67138 {
67139 return $this->getInnerIterator()->getDepth() >= $this->minDepth;
67140 }
67141 }
67142 <?php
67143
67144
67145
67146
67147
67148
67149
67150
67151
67152
67153 namespace Symfony\Component\Finder\Iterator;
67154
67155
67156
67157
67158
67159
67160 class ExcludeDirectoryFilterIterator extends FilterIterator implements \RecursiveIterator
67161 {
67162 private $iterator;
67163 private $isRecursive;
67164 private $excludedDirs = array();
67165 private $excludedPattern;
67166
67167
67168
67169
67170
67171
67172
67173 public function __construct(\Iterator $iterator, array $directories)
67174 {
67175 $this->iterator = $iterator;
67176 $this->isRecursive = $iterator instanceof \RecursiveIterator;
67177 $patterns = array();
67178 foreach ($directories as $directory) {
67179 $directory = rtrim($directory, '/');
67180 if (!$this->isRecursive || false !== strpos($directory, '/')) {
67181 $patterns[] = preg_quote($directory, '#');
67182 } else {
67183 $this->excludedDirs[$directory] = true;
67184 }
67185 }
67186 if ($patterns) {
67187 $this->excludedPattern = '#(?:^|/)(?:'.implode('|', $patterns).')(?:/|$)#';
67188 }
67189
67190 parent::__construct($iterator);
67191 }
67192
67193
67194
67195
67196
67197
67198 public function accept()
67199 {
67200 if ($this->isRecursive && isset($this->excludedDirs[$this->getFilename()]) && $this->isDir()) {
67201 return false;
67202 }
67203
67204 if ($this->excludedPattern) {
67205 $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
67206 $path = str_replace('\\', '/', $path);
67207
67208 return !preg_match($this->excludedPattern, $path);
67209 }
67210
67211 return true;
67212 }
67213
67214 public function hasChildren()
67215 {
67216 return $this->isRecursive && $this->iterator->hasChildren();
67217 }
67218
67219 public function getChildren()
67220 {
67221 $children = new self($this->iterator->getChildren(), array());
67222 $children->excludedDirs = $this->excludedDirs;
67223 $children->excludedPattern = $this->excludedPattern;
67224
67225 return $children;
67226 }
67227 }
67228 <?php
67229
67230
67231
67232
67233
67234
67235
67236
67237
67238
67239 namespace Symfony\Component\Finder\Iterator;
67240
67241 @trigger_error('The '.__NAMESPACE__.'\FilePathsIterator class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
67242
67243 use Symfony\Component\Finder\SplFileInfo;
67244
67245
67246
67247
67248
67249
67250
67251
67252 class FilePathsIterator extends \ArrayIterator
67253 {
67254
67255
67256
67257 private $baseDir;
67258
67259
67260
67261
67262 private $baseDirLength;
67263
67264
67265
67266
67267 private $subPath;
67268
67269
67270
67271
67272 private $subPathname;
67273
67274
67275
67276
67277 private $current;
67278
67279
67280
67281
67282
67283 public function __construct(array $paths, $baseDir)
67284 {
67285 $this->baseDir = $baseDir;
67286 $this->baseDirLength = strlen($baseDir);
67287
67288 parent::__construct($paths);
67289 }
67290
67291
67292
67293
67294
67295
67296
67297 public function __call($name, array $arguments)
67298 {
67299 return call_user_func_array(array($this->current(), $name), $arguments);
67300 }
67301
67302
67303
67304
67305
67306
67307 public function current()
67308 {
67309 return $this->current;
67310 }
67311
67312
67313
67314
67315 public function key()
67316 {
67317 return $this->current->getPathname();
67318 }
67319
67320 public function next()
67321 {
67322 parent::next();
67323 $this->buildProperties();
67324 }
67325
67326 public function rewind()
67327 {
67328 parent::rewind();
67329 $this->buildProperties();
67330 }
67331
67332
67333
67334
67335 public function getSubPath()
67336 {
67337 return $this->subPath;
67338 }
67339
67340
67341
67342
67343 public function getSubPathname()
67344 {
67345 return $this->subPathname;
67346 }
67347
67348 private function buildProperties()
67349 {
67350 $absolutePath = parent::current();
67351
67352 if ($this->baseDir === substr($absolutePath, 0, $this->baseDirLength)) {
67353 $this->subPathname = ltrim(substr($absolutePath, $this->baseDirLength), '/\\');
67354 $dir = dirname($this->subPathname);
67355 $this->subPath = '.' === $dir ? '' : $dir;
67356 } else {
67357 $this->subPath = $this->subPathname = '';
67358 }
67359
67360 $this->current = new SplFileInfo(parent::current(), $this->subPath, $this->subPathname);
67361 }
67362 }
67363 <?php
67364
67365
67366
67367
67368
67369
67370
67371
67372
67373
67374 namespace Symfony\Component\Finder\Iterator;
67375
67376
67377
67378
67379
67380
67381 class FileTypeFilterIterator extends FilterIterator
67382 {
67383 const ONLY_FILES = 1;
67384 const ONLY_DIRECTORIES = 2;
67385
67386 private $mode;
67387
67388
67389
67390
67391
67392
67393
67394 public function __construct(\Iterator $iterator, $mode)
67395 {
67396 $this->mode = $mode;
67397
67398 parent::__construct($iterator);
67399 }
67400
67401
67402
67403
67404
67405
67406 public function accept()
67407 {
67408 $fileinfo = $this->current();
67409 if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) {
67410 return false;
67411 } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) {
67412 return false;
67413 }
67414
67415 return true;
67416 }
67417 }
67418 <?php
67419
67420
67421
67422
67423
67424
67425
67426
67427
67428
67429 namespace Symfony\Component\Finder\Iterator;
67430
67431
67432
67433
67434
67435
67436
67437 class FilecontentFilterIterator extends MultiplePcreFilterIterator
67438 {
67439
67440
67441
67442
67443
67444 public function accept()
67445 {
67446 if (!$this->matchRegexps && !$this->noMatchRegexps) {
67447 return true;
67448 }
67449
67450 $fileinfo = $this->current();
67451
67452 if ($fileinfo->isDir() || !$fileinfo->isReadable()) {
67453 return false;
67454 }
67455
67456 $content = $fileinfo->getContents();
67457 if (!$content) {
67458 return false;
67459 }
67460
67461 return $this->isAccepted($content);
67462 }
67463
67464
67465
67466
67467
67468
67469
67470
67471 protected function toRegex($str)
67472 {
67473 return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
67474 }
67475 }
67476 <?php
67477
67478
67479
67480
67481
67482
67483
67484
67485
67486
67487 namespace Symfony\Component\Finder\Iterator;
67488
67489 use Symfony\Component\Finder\Glob;
67490
67491
67492
67493
67494
67495
67496 class FilenameFilterIterator extends MultiplePcreFilterIterator
67497 {
67498
67499
67500
67501
67502
67503 public function accept()
67504 {
67505 return $this->isAccepted($this->current()->getFilename());
67506 }
67507
67508
67509
67510
67511
67512
67513
67514
67515
67516
67517
67518 protected function toRegex($str)
67519 {
67520 return $this->isRegex($str) ? $str : Glob::toRegex($str);
67521 }
67522 }
67523 <?php
67524
67525
67526
67527
67528
67529
67530
67531
67532
67533
67534 namespace Symfony\Component\Finder\Iterator;
67535
67536
67537
67538
67539
67540
67541
67542
67543
67544 abstract class FilterIterator extends \FilterIterator
67545 {
67546
67547
67548
67549
67550
67551
67552 public function rewind()
67553 {
67554 if (\PHP_VERSION_ID > 50607 || (\PHP_VERSION_ID > 50523 && \PHP_VERSION_ID < 50600)) {
67555 parent::rewind();
67556
67557 return;
67558 }
67559
67560 $iterator = $this;
67561 while ($iterator instanceof \OuterIterator) {
67562 $innerIterator = $iterator->getInnerIterator();
67563
67564 if ($innerIterator instanceof RecursiveDirectoryIterator) {
67565
67566  if ($innerIterator->isRewindable()) {
67567 $innerIterator->next();
67568 $innerIterator->rewind();
67569 }
67570 } elseif ($innerIterator instanceof \FilesystemIterator) {
67571 $innerIterator->next();
67572 $innerIterator->rewind();
67573 }
67574
67575 $iterator = $innerIterator;
67576 }
67577
67578 parent::rewind();
67579 }
67580 }
67581 <?php
67582
67583
67584
67585
67586
67587
67588
67589
67590
67591
67592 namespace Symfony\Component\Finder\Iterator;
67593
67594
67595
67596
67597
67598
67599 abstract class MultiplePcreFilterIterator extends FilterIterator
67600 {
67601 protected $matchRegexps = array();
67602 protected $noMatchRegexps = array();
67603
67604
67605
67606
67607
67608
67609
67610
67611 public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns)
67612 {
67613 foreach ($matchPatterns as $pattern) {
67614 $this->matchRegexps[] = $this->toRegex($pattern);
67615 }
67616
67617 foreach ($noMatchPatterns as $pattern) {
67618 $this->noMatchRegexps[] = $this->toRegex($pattern);
67619 }
67620
67621 parent::__construct($iterator);
67622 }
67623
67624
67625
67626
67627
67628
67629
67630
67631
67632
67633
67634
67635 protected function isAccepted($string)
67636 {
67637
67638  foreach ($this->noMatchRegexps as $regex) {
67639 if (preg_match($regex, $string)) {
67640 return false;
67641 }
67642 }
67643
67644
67645  if ($this->matchRegexps) {
67646 foreach ($this->matchRegexps as $regex) {
67647 if (preg_match($regex, $string)) {
67648 return true;
67649 }
67650 }
67651
67652 return false;
67653 }
67654
67655
67656  return true;
67657 }
67658
67659
67660
67661
67662
67663
67664
67665
67666 protected function isRegex($str)
67667 {
67668 if (preg_match('/^(.{3,}?)[imsxuADU]*$/', $str, $m)) {
67669 $start = substr($m[1], 0, 1);
67670 $end = substr($m[1], -1);
67671
67672 if ($start === $end) {
67673 return !preg_match('/[*?[:alnum:] \\\\]/', $start);
67674 }
67675
67676 foreach (array(array('{', '}'), array('(', ')'), array('[', ']'), array('<', '>')) as $delimiters) {
67677 if ($start === $delimiters[0] && $end === $delimiters[1]) {
67678 return true;
67679 }
67680 }
67681 }
67682
67683 return false;
67684 }
67685
67686
67687
67688
67689
67690
67691
67692
67693 abstract protected function toRegex($str);
67694 }
67695 <?php
67696
67697
67698
67699
67700
67701
67702
67703
67704
67705
67706 namespace Symfony\Component\Finder\Iterator;
67707
67708
67709
67710
67711
67712
67713
67714 class PathFilterIterator extends MultiplePcreFilterIterator
67715 {
67716
67717
67718
67719
67720
67721 public function accept()
67722 {
67723 $filename = $this->current()->getRelativePathname();
67724
67725 if ('\\' === DIRECTORY_SEPARATOR) {
67726 $filename = str_replace('\\', '/', $filename);
67727 }
67728
67729 return $this->isAccepted($filename);
67730 }
67731
67732
67733
67734
67735
67736
67737
67738
67739
67740
67741
67742
67743
67744
67745
67746 protected function toRegex($str)
67747 {
67748 return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
67749 }
67750 }
67751 <?php
67752
67753
67754
67755
67756
67757
67758
67759
67760
67761
67762 namespace Symfony\Component\Finder\Iterator;
67763
67764 use Symfony\Component\Finder\Exception\AccessDeniedException;
67765 use Symfony\Component\Finder\SplFileInfo;
67766
67767
67768
67769
67770
67771
67772 class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
67773 {
67774
67775
67776
67777 private $ignoreUnreadableDirs;
67778
67779
67780
67781
67782 private $rewindable;
67783
67784
67785  private $rootPath;
67786 private $subPath;
67787 private $directorySeparator = '/';
67788
67789
67790
67791
67792
67793
67794
67795
67796
67797
67798 public function __construct($path, $flags, $ignoreUnreadableDirs = false)
67799 {
67800 if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
67801 throw new \RuntimeException('This iterator only support returning current as fileinfo.');
67802 }
67803
67804 parent::__construct($path, $flags);
67805 $this->ignoreUnreadableDirs = $ignoreUnreadableDirs;
67806 $this->rootPath = (string) $path;
67807 if ('/' !== DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) {
67808 $this->directorySeparator = DIRECTORY_SEPARATOR;
67809 }
67810 }
67811
67812
67813
67814
67815
67816
67817 public function current()
67818 {
67819
67820
67821 if (null === $subPathname = $this->subPath) {
67822 $subPathname = $this->subPath = (string) $this->getSubPath();
67823 }
67824 if ('' !== $subPathname) {
67825 $subPathname .= $this->directorySeparator;
67826 }
67827 $subPathname .= $this->getFilename();
67828
67829 return new SplFileInfo($this->rootPath.$this->directorySeparator.$subPathname, $this->subPath, $subPathname);
67830 }
67831
67832
67833
67834
67835
67836
67837 public function getChildren()
67838 {
67839 try {
67840 $children = parent::getChildren();
67841
67842 if ($children instanceof self) {
67843
67844  $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs;
67845
67846
67847  $children->rewindable = &$this->rewindable;
67848 $children->rootPath = $this->rootPath;
67849 }
67850
67851 return $children;
67852 } catch (\UnexpectedValueException $e) {
67853 if ($this->ignoreUnreadableDirs) {
67854
67855  return new \RecursiveArrayIterator(array());
67856 } else {
67857 throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
67858 }
67859 }
67860 }
67861
67862
67863
67864
67865 public function rewind()
67866 {
67867 if (false === $this->isRewindable()) {
67868 return;
67869 }
67870
67871
67872  if (\PHP_VERSION_ID < 50523 || \PHP_VERSION_ID >= 50600 && \PHP_VERSION_ID < 50607) {
67873 parent::next();
67874 }
67875
67876 parent::rewind();
67877 }
67878
67879
67880
67881
67882
67883
67884 public function isRewindable()
67885 {
67886 if (null !== $this->rewindable) {
67887 return $this->rewindable;
67888 }
67889
67890
67891  if ('' === $this->getPath()) {
67892 return $this->rewindable = false;
67893 }
67894
67895 if (false !== $stream = @opendir($this->getPath())) {
67896 $infos = stream_get_meta_data($stream);
67897 closedir($stream);
67898
67899 if ($infos['seekable']) {
67900 return $this->rewindable = true;
67901 }
67902 }
67903
67904 return $this->rewindable = false;
67905 }
67906 }
67907 <?php
67908
67909
67910
67911
67912
67913
67914
67915
67916
67917
67918 namespace Symfony\Component\Finder\Iterator;
67919
67920 use Symfony\Component\Finder\Comparator\NumberComparator;
67921
67922
67923
67924
67925
67926
67927 class SizeRangeFilterIterator extends FilterIterator
67928 {
67929 private $comparators = array();
67930
67931
67932
67933
67934
67935
67936
67937 public function __construct(\Iterator $iterator, array $comparators)
67938 {
67939 $this->comparators = $comparators;
67940
67941 parent::__construct($iterator);
67942 }
67943
67944
67945
67946
67947
67948
67949 public function accept()
67950 {
67951 $fileinfo = $this->current();
67952 if (!$fileinfo->isFile()) {
67953 return true;
67954 }
67955
67956 $filesize = $fileinfo->getSize();
67957 foreach ($this->comparators as $compare) {
67958 if (!$compare->test($filesize)) {
67959 return false;
67960 }
67961 }
67962
67963 return true;
67964 }
67965 }
67966 <?php
67967
67968
67969
67970
67971
67972
67973
67974
67975
67976
67977 namespace Symfony\Component\Finder\Iterator;
67978
67979
67980
67981
67982
67983
67984 class SortableIterator implements \IteratorAggregate
67985 {
67986 const SORT_BY_NAME = 1;
67987 const SORT_BY_TYPE = 2;
67988 const SORT_BY_ACCESSED_TIME = 3;
67989 const SORT_BY_CHANGED_TIME = 4;
67990 const SORT_BY_MODIFIED_TIME = 5;
67991
67992 private $iterator;
67993 private $sort;
67994
67995
67996
67997
67998
67999
68000
68001
68002
68003 public function __construct(\Traversable $iterator, $sort)
68004 {
68005 $this->iterator = $iterator;
68006
68007 if (self::SORT_BY_NAME === $sort) {
68008 $this->sort = function ($a, $b) {
68009 return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
68010 };
68011 } elseif (self::SORT_BY_TYPE === $sort) {
68012 $this->sort = function ($a, $b) {
68013 if ($a->isDir() && $b->isFile()) {
68014 return -1;
68015 } elseif ($a->isFile() && $b->isDir()) {
68016 return 1;
68017 }
68018
68019 return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
68020 };
68021 } elseif (self::SORT_BY_ACCESSED_TIME === $sort) {
68022 $this->sort = function ($a, $b) {
68023 return $a->getATime() - $b->getATime();
68024 };
68025 } elseif (self::SORT_BY_CHANGED_TIME === $sort) {
68026 $this->sort = function ($a, $b) {
68027 return $a->getCTime() - $b->getCTime();
68028 };
68029 } elseif (self::SORT_BY_MODIFIED_TIME === $sort) {
68030 $this->sort = function ($a, $b) {
68031 return $a->getMTime() - $b->getMTime();
68032 };
68033 } elseif (is_callable($sort)) {
68034 $this->sort = $sort;
68035 } else {
68036 throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.');
68037 }
68038 }
68039
68040 public function getIterator()
68041 {
68042 $array = iterator_to_array($this->iterator, true);
68043 uasort($array, $this->sort);
68044
68045 return new \ArrayIterator($array);
68046 }
68047 }
68048 Copyright (c) 2004-2017 Fabien Potencier
68049
68050 Permission is hereby granted, free of charge, to any person obtaining a copy
68051 of this software and associated documentation files (the "Software"), to deal
68052 in the Software without restriction, including without limitation the rights
68053 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
68054 copies of the Software, and to permit persons to whom the Software is furnished
68055 to do so, subject to the following conditions:
68056
68057 The above copyright notice and this permission notice shall be included in all
68058 copies or substantial portions of the Software.
68059
68060 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
68061 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
68062 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
68063 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
68064 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
68065 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
68066 THE SOFTWARE.
68067 <?php
68068
68069
68070
68071
68072
68073
68074
68075
68076
68077
68078 namespace Symfony\Component\Finder\Shell;
68079
68080 @trigger_error('The '.__NAMESPACE__.'\Command class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68081
68082
68083
68084
68085
68086
68087 class Command
68088 {
68089
68090
68091
68092 private $parent;
68093
68094
68095
68096
68097 private $bits = array();
68098
68099
68100
68101
68102 private $labels = array();
68103
68104
68105
68106
68107 private $errorHandler;
68108
68109
68110
68111
68112
68113
68114 public function __construct(Command $parent = null)
68115 {
68116 $this->parent = $parent;
68117 }
68118
68119
68120
68121
68122
68123
68124 public function __toString()
68125 {
68126 return $this->join();
68127 }
68128
68129
68130
68131
68132
68133
68134
68135
68136 public static function create(Command $parent = null)
68137 {
68138 return new self($parent);
68139 }
68140
68141
68142
68143
68144
68145
68146
68147
68148 public static function escape($input)
68149 {
68150 return escapeshellcmd($input);
68151 }
68152
68153
68154
68155
68156
68157
68158
68159
68160 public static function quote($input)
68161 {
68162 return escapeshellarg($input);
68163 }
68164
68165
68166
68167
68168
68169
68170
68171
68172 public function add($bit)
68173 {
68174 $this->bits[] = $bit;
68175
68176 return $this;
68177 }
68178
68179
68180
68181
68182
68183
68184
68185
68186 public function top($bit)
68187 {
68188 array_unshift($this->bits, $bit);
68189
68190 foreach ($this->labels as $label => $index) {
68191 $this->labels[$label] += 1;
68192 }
68193
68194 return $this;
68195 }
68196
68197
68198
68199
68200
68201
68202
68203
68204 public function arg($arg)
68205 {
68206 $this->bits[] = self::quote($arg);
68207
68208 return $this;
68209 }
68210
68211
68212
68213
68214
68215
68216
68217
68218 public function cmd($esc)
68219 {
68220 $this->bits[] = self::escape($esc);
68221
68222 return $this;
68223 }
68224
68225
68226
68227
68228
68229
68230
68231
68232
68233
68234 public function ins($label)
68235 {
68236 if (isset($this->labels[$label])) {
68237 throw new \RuntimeException(sprintf('Label "%s" already exists.', $label));
68238 }
68239
68240 $this->bits[] = self::create($this);
68241 $this->labels[$label] = count($this->bits) - 1;
68242
68243 return $this->bits[$this->labels[$label]];
68244 }
68245
68246
68247
68248
68249
68250
68251
68252
68253
68254
68255 public function get($label)
68256 {
68257 if (!isset($this->labels[$label])) {
68258 throw new \RuntimeException(sprintf('Label "%s" does not exist.', $label));
68259 }
68260
68261 return $this->bits[$this->labels[$label]];
68262 }
68263
68264
68265
68266
68267
68268
68269
68270
68271 public function end()
68272 {
68273 if (null === $this->parent) {
68274 throw new \RuntimeException('Calling end on root command doesn\'t make sense.');
68275 }
68276
68277 return $this->parent;
68278 }
68279
68280
68281
68282
68283
68284
68285 public function length()
68286 {
68287 return count($this->bits);
68288 }
68289
68290
68291
68292
68293
68294
68295 public function setErrorHandler(\Closure $errorHandler)
68296 {
68297 $this->errorHandler = $errorHandler;
68298
68299 return $this;
68300 }
68301
68302
68303
68304
68305 public function getErrorHandler()
68306 {
68307 return $this->errorHandler;
68308 }
68309
68310
68311
68312
68313
68314
68315
68316
68317 public function execute()
68318 {
68319 if (null === $errorHandler = $this->errorHandler) {
68320 exec($this->join(), $output);
68321 } else {
68322 $process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes);
68323 $output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY);
68324
68325 if ($error = stream_get_contents($pipes[2])) {
68326 $errorHandler($error);
68327 }
68328
68329 proc_close($process);
68330 }
68331
68332 return $output ?: array();
68333 }
68334
68335
68336
68337
68338
68339
68340 public function join()
68341 {
68342 return implode(' ', array_filter(
68343 array_map(function ($bit) {
68344 return $bit instanceof Command ? $bit->join() : ($bit ?: null);
68345 }, $this->bits),
68346 function ($bit) { return null !== $bit; }
68347 ));
68348 }
68349
68350
68351
68352
68353
68354
68355
68356
68357
68358 public function addAtIndex($bit, $index)
68359 {
68360 array_splice($this->bits, $index, 0, $bit instanceof self ? array($bit) : $bit);
68361
68362 return $this;
68363 }
68364 }
68365 <?php
68366
68367
68368
68369
68370
68371
68372
68373
68374
68375
68376 namespace Symfony\Component\Finder\Shell;
68377
68378 @trigger_error('The '.__NAMESPACE__.'\Shell class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68379
68380
68381
68382
68383
68384
68385 class Shell
68386 {
68387 const TYPE_UNIX = 1;
68388 const TYPE_DARWIN = 2;
68389 const TYPE_CYGWIN = 3;
68390 const TYPE_WINDOWS = 4;
68391 const TYPE_BSD = 5;
68392
68393
68394
68395
68396 private $type;
68397
68398
68399
68400
68401
68402
68403 public function getType()
68404 {
68405 if (null === $this->type) {
68406 $this->type = $this->guessType();
68407 }
68408
68409 return $this->type;
68410 }
68411
68412
68413
68414
68415
68416
68417
68418
68419 public function testCommand($command)
68420 {
68421 if (!function_exists('exec')) {
68422 return false;
68423 }
68424
68425
68426  $testCommand = 'which ';
68427 if (self::TYPE_WINDOWS === $this->type) {
68428 $testCommand = 'where ';
68429 }
68430
68431 $command = escapeshellcmd($command);
68432
68433 exec($testCommand.$command, $output, $code);
68434
68435 return 0 === $code && count($output) > 0;
68436 }
68437
68438
68439
68440
68441
68442
68443 private function guessType()
68444 {
68445 $os = strtolower(PHP_OS);
68446
68447 if (false !== strpos($os, 'cygwin')) {
68448 return self::TYPE_CYGWIN;
68449 }
68450
68451 if (false !== strpos($os, 'darwin')) {
68452 return self::TYPE_DARWIN;
68453 }
68454
68455 if (false !== strpos($os, 'bsd')) {
68456 return self::TYPE_BSD;
68457 }
68458
68459 if (0 === strpos($os, 'win')) {
68460 return self::TYPE_WINDOWS;
68461 }
68462
68463 return self::TYPE_UNIX;
68464 }
68465 }
68466 <?php
68467
68468
68469
68470
68471
68472
68473
68474
68475
68476
68477 namespace Symfony\Component\Finder;
68478
68479
68480
68481
68482
68483
68484 class SplFileInfo extends \SplFileInfo
68485 {
68486 private $relativePath;
68487 private $relativePathname;
68488
68489
68490
68491
68492
68493
68494
68495
68496 public function __construct($file, $relativePath, $relativePathname)
68497 {
68498 parent::__construct($file);
68499 $this->relativePath = $relativePath;
68500 $this->relativePathname = $relativePathname;
68501 }
68502
68503
68504
68505
68506
68507
68508
68509
68510 public function getRelativePath()
68511 {
68512 return $this->relativePath;
68513 }
68514
68515
68516
68517
68518
68519
68520
68521
68522 public function getRelativePathname()
68523 {
68524 return $this->relativePathname;
68525 }
68526
68527
68528
68529
68530
68531
68532
68533
68534 public function getContents()
68535 {
68536 $level = error_reporting(0);
68537 $content = file_get_contents($this->getPathname());
68538 error_reporting($level);
68539 if (false === $content) {
68540 $error = error_get_last();
68541 throw new \RuntimeException($error['message']);
68542 }
68543
68544 return $content;
68545 }
68546 }
68547 Copyright (c) 2014-2016 Fabien Potencier
68548
68549 Permission is hereby granted, free of charge, to any person obtaining a copy
68550 of this software and associated documentation files (the "Software"), to deal
68551 in the Software without restriction, including without limitation the rights
68552 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
68553 copies of the Software, and to permit persons to whom the Software is furnished
68554 to do so, subject to the following conditions:
68555
68556 The above copyright notice and this permission notice shall be included in all
68557 copies or substantial portions of the Software.
68558
68559 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
68560 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
68561 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
68562 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
68563 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
68564 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
68565 THE SOFTWARE.
68566 <?php
68567
68568
68569
68570
68571
68572
68573
68574
68575
68576
68577 namespace Symfony\Polyfill\Mbstring;
68578
68579
68580
68581
68582
68583
68584
68585
68586
68587
68588
68589
68590
68591
68592
68593
68594
68595
68596
68597
68598
68599
68600
68601
68602
68603
68604
68605
68606
68607
68608
68609
68610
68611
68612
68613
68614
68615
68616
68617
68618
68619
68620
68621
68622
68623
68624
68625
68626
68627
68628
68629
68630
68631 final class Mbstring
68632 {
68633 const MB_CASE_FOLD = PHP_INT_MAX;
68634
68635 private static $encodingList = array('ASCII', 'UTF-8');
68636 private static $language = 'neutral';
68637 private static $internalEncoding = 'UTF-8';
68638 private static $caseFold = array(
68639 array('µ','ſ',"\xCD\x85",'ς',"\xCF\x90","\xCF\x91","\xCF\x95","\xCF\x96","\xCF\xB0","\xCF\xB1","\xCF\xB5","\xE1\xBA\x9B","\xE1\xBE\xBE"),
68640 array('μ','s','ι', 'σ','β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1",'ι'),
68641 );
68642
68643 public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
68644 {
68645 if (is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
68646 $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
68647 } else {
68648 $fromEncoding = self::getEncoding($fromEncoding);
68649 }
68650
68651 $toEncoding = self::getEncoding($toEncoding);
68652
68653 if ('BASE64' === $fromEncoding) {
68654 $s = base64_decode($s);
68655 $fromEncoding = $toEncoding;
68656 }
68657
68658 if ('BASE64' === $toEncoding) {
68659 return base64_encode($s);
68660 }
68661
68662 if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
68663 if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
68664 $fromEncoding = 'Windows-1252';
68665 }
68666 if ('UTF-8' !== $fromEncoding) {
68667 $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s);
68668 }
68669
68670 return preg_replace_callback('/[\x80-\xFF]+/', array(__CLASS__, 'html_encoding_callback'), $s);
68671 }
68672
68673 if ('HTML-ENTITIES' === $fromEncoding) {
68674 $s = html_entity_decode($s, ENT_COMPAT, 'UTF-8');
68675 $fromEncoding = 'UTF-8';
68676 }
68677
68678 return iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
68679 }
68680
68681 public static function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null)
68682 {
68683 $vars = array(&$a, &$b, &$c, &$d, &$e, &$f);
68684
68685 $ok = true;
68686 array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) {
68687 if (false === $v = Mbstring::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {
68688 $ok = false;
68689 }
68690 });
68691
68692 return $ok ? $fromEncoding : false;
68693 }
68694
68695 public static function mb_decode_mimeheader($s)
68696 {
68697 return iconv_mime_decode($s, 2, self::$internalEncoding);
68698 }
68699
68700 public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
68701 {
68702 trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', E_USER_WARNING);
68703 }
68704
68705 public static function mb_convert_case($s, $mode, $encoding = null)
68706 {
68707 if ('' === $s .= '') {
68708 return '';
68709 }
68710
68711 $encoding = self::getEncoding($encoding);
68712
68713 if ('UTF-8' === $encoding) {
68714 $encoding = null;
68715 if (!preg_match('//u', $s)) {
68716 $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
68717 }
68718 } else {
68719 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
68720 }
68721
68722 if (MB_CASE_TITLE == $mode) {
68723 $s = preg_replace_callback('/\b\p{Ll}/u', array(__CLASS__, 'title_case_upper'), $s);
68724 $s = preg_replace_callback('/\B[\p{Lu}\p{Lt}]+/u', array(__CLASS__, 'title_case_lower'), $s);
68725 } else {
68726 if (MB_CASE_UPPER == $mode) {
68727 static $upper = null;
68728 if (null === $upper) {
68729 $upper = self::getData('upperCase');
68730 }
68731 $map = $upper;
68732 } else {
68733 if (self::MB_CASE_FOLD === $mode) {
68734 $s = str_replace(self::$caseFold[0], self::$caseFold[1], $s);
68735 }
68736
68737 static $lower = null;
68738 if (null === $lower) {
68739 $lower = self::getData('lowerCase');
68740 }
68741 $map = $lower;
68742 }
68743
68744 static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
68745
68746 $i = 0;
68747 $len = strlen($s);
68748
68749 while ($i < $len) {
68750 $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
68751 $uchr = substr($s, $i, $ulen);
68752 $i += $ulen;
68753
68754 if (isset($map[$uchr])) {
68755 $uchr = $map[$uchr];
68756 $nlen = strlen($uchr);
68757
68758 if ($nlen == $ulen) {
68759 $nlen = $i;
68760 do {
68761 $s[--$nlen] = $uchr[--$ulen];
68762 } while ($ulen);
68763 } else {
68764 $s = substr_replace($s, $uchr, $i - $ulen, $ulen);
68765 $len += $nlen - $ulen;
68766 $i += $nlen - $ulen;
68767 }
68768 }
68769 }
68770 }
68771
68772 if (null === $encoding) {
68773 return $s;
68774 }
68775
68776 return iconv('UTF-8', $encoding.'//IGNORE', $s);
68777 }
68778
68779 public static function mb_internal_encoding($encoding = null)
68780 {
68781 if (null === $encoding) {
68782 return self::$internalEncoding;
68783 }
68784
68785 $encoding = self::getEncoding($encoding);
68786
68787 if ('UTF-8' === $encoding || false !== @iconv($encoding, $encoding, ' ')) {
68788 self::$internalEncoding = $encoding;
68789
68790 return true;
68791 }
68792
68793 return false;
68794 }
68795
68796 public static function mb_language($lang = null)
68797 {
68798 if (null === $lang) {
68799 return self::$language;
68800 }
68801
68802 switch ($lang = strtolower($lang)) {
68803 case 'uni':
68804 case 'neutral':
68805 self::$language = $lang;
68806
68807 return true;
68808 }
68809
68810 return false;
68811 }
68812
68813 public static function mb_list_encodings()
68814 {
68815 return array('UTF-8');
68816 }
68817
68818 public static function mb_encoding_aliases($encoding)
68819 {
68820 switch (strtoupper($encoding)) {
68821 case 'UTF8':
68822 case 'UTF-8':
68823 return array('utf8');
68824 }
68825
68826 return false;
68827 }
68828
68829 public static function mb_check_encoding($var = null, $encoding = null)
68830 {
68831 if (null === $encoding) {
68832 if (null === $var) {
68833 return false;
68834 }
68835 $encoding = self::$internalEncoding;
68836 }
68837
68838 return self::mb_detect_encoding($var, array($encoding)) || false !== @iconv($encoding, $encoding, $var);
68839 }
68840
68841 public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
68842 {
68843 if (null === $encodingList) {
68844 $encodingList = self::$encodingList;
68845 } else {
68846 if (!is_array($encodingList)) {
68847 $encodingList = array_map('trim', explode(',', $encodingList));
68848 }
68849 $encodingList = array_map('strtoupper', $encodingList);
68850 }
68851
68852 foreach ($encodingList as $enc) {
68853 switch ($enc) {
68854 case 'ASCII':
68855 if (!preg_match('/[\x80-\xFF]/', $str)) {
68856 return $enc;
68857 }
68858 break;
68859
68860 case 'UTF8':
68861 case 'UTF-8':
68862 if (preg_match('//u', $str)) {
68863 return 'UTF-8';
68864 }
68865 break;
68866
68867 default:
68868 if (0 === strncmp($enc, 'ISO-8859-', 9)) {
68869 return $enc;
68870 }
68871 }
68872 }
68873
68874 return false;
68875 }
68876
68877 public static function mb_detect_order($encodingList = null)
68878 {
68879 if (null === $encodingList) {
68880 return self::$encodingList;
68881 }
68882
68883 if (!is_array($encodingList)) {
68884 $encodingList = array_map('trim', explode(',', $encodingList));
68885 }
68886 $encodingList = array_map('strtoupper', $encodingList);
68887
68888 foreach ($encodingList as $enc) {
68889 switch ($enc) {
68890 default:
68891 if (strncmp($enc, 'ISO-8859-', 9)) {
68892 return false;
68893 }
68894 case 'ASCII':
68895 case 'UTF8':
68896 case 'UTF-8':
68897 }
68898 }
68899
68900 self::$encodingList = $encodingList;
68901
68902 return true;
68903 }
68904
68905 public static function mb_strlen($s, $encoding = null)
68906 {
68907 $encoding = self::getEncoding($encoding);
68908 if ('CP850' === $encoding || 'ASCII' === $encoding) {
68909 return strlen($s);
68910 }
68911
68912 return @iconv_strlen($s, $encoding);
68913 }
68914
68915 public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
68916 {
68917 $encoding = self::getEncoding($encoding);
68918 if ('CP850' === $encoding || 'ASCII' === $encoding) {
68919 return strpos($haystack, $needle, $offset);
68920 }
68921
68922 if ('' === $needle .= '') {
68923 trigger_error(__METHOD__.': Empty delimiter', E_USER_WARNING);
68924
68925 return false;
68926 }
68927
68928 return iconv_strpos($haystack, $needle, $offset, $encoding);
68929 }
68930
68931 public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
68932 {
68933 $encoding = self::getEncoding($encoding);
68934 if ('CP850' === $encoding || 'ASCII' === $encoding) {
68935 return strrpos($haystack, $needle, $offset);
68936 }
68937
68938 if ($offset != (int) $offset) {
68939 $offset = 0;
68940 } elseif ($offset = (int) $offset) {
68941 if ($offset < 0) {
68942 $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
68943 $offset = 0;
68944 } else {
68945 $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
68946 }
68947 }
68948
68949 $pos = iconv_strrpos($haystack, $needle, $encoding);
68950
68951 return false !== $pos ? $offset + $pos : false;
68952 }
68953
68954 public static function mb_strtolower($s, $encoding = null)
68955 {
68956 return self::mb_convert_case($s, MB_CASE_LOWER, $encoding);
68957 }
68958
68959 public static function mb_strtoupper($s, $encoding = null)
68960 {
68961 return self::mb_convert_case($s, MB_CASE_UPPER, $encoding);
68962 }
68963
68964 public static function mb_substitute_character($c = null)
68965 {
68966 if (0 === strcasecmp($c, 'none')) {
68967 return true;
68968 }
68969
68970 return null !== $c ? false : 'none';
68971 }
68972
68973 public static function mb_substr($s, $start, $length = null, $encoding = null)
68974 {
68975 $encoding = self::getEncoding($encoding);
68976 if ('CP850' === $encoding || 'ASCII' === $encoding) {
68977 return substr($s, $start, null === $length ? 2147483647 : $length);
68978 }
68979
68980 if ($start < 0) {
68981 $start = iconv_strlen($s, $encoding) + $start;
68982 if ($start < 0) {
68983 $start = 0;
68984 }
68985 }
68986
68987 if (null === $length) {
68988 $length = 2147483647;
68989 } elseif ($length < 0) {
68990 $length = iconv_strlen($s, $encoding) + $length - $start;
68991 if ($length < 0) {
68992 return '';
68993 }
68994 }
68995
68996 return iconv_substr($s, $start, $length, $encoding).'';
68997 }
68998
68999 public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
69000 {
69001 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
69002 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
69003
69004 return self::mb_strpos($haystack, $needle, $offset, $encoding);
69005 }
69006
69007 public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
69008 {
69009 $pos = self::mb_stripos($haystack, $needle, 0, $encoding);
69010
69011 return self::getSubpart($pos, $part, $haystack, $encoding);
69012 }
69013
69014 public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
69015 {
69016 $encoding = self::getEncoding($encoding);
69017 if ('CP850' === $encoding || 'ASCII' === $encoding) {
69018 return strrchr($haystack, $needle, $part);
69019 }
69020 $needle = self::mb_substr($needle, 0, 1, $encoding);
69021 $pos = iconv_strrpos($haystack, $needle, $encoding);
69022
69023 return self::getSubpart($pos, $part, $haystack, $encoding);
69024 }
69025
69026 public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
69027 {
69028 $needle = self::mb_substr($needle, 0, 1, $encoding);
69029 $pos = self::mb_strripos($haystack, $needle, $encoding);
69030
69031 return self::getSubpart($pos, $part, $haystack, $encoding);
69032 }
69033
69034 public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
69035 {
69036 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
69037 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
69038
69039 return self::mb_strrpos($haystack, $needle, $offset, $encoding);
69040 }
69041
69042 public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
69043 {
69044 $pos = strpos($haystack, $needle);
69045 if (false === $pos) {
69046 return false;
69047 }
69048 if ($part) {
69049 return substr($haystack, 0, $pos);
69050 }
69051
69052 return substr($haystack, $pos);
69053 }
69054
69055 public static function mb_get_info($type = 'all')
69056 {
69057 $info = array(
69058 'internal_encoding' => self::$internalEncoding,
69059 'http_output' => 'pass',
69060 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
69061 'func_overload' => 0,
69062 'func_overload_list' => 'no overload',
69063 'mail_charset' => 'UTF-8',
69064 'mail_header_encoding' => 'BASE64',
69065 'mail_body_encoding' => 'BASE64',
69066 'illegal_chars' => 0,
69067 'encoding_translation' => 'Off',
69068 'language' => self::$language,
69069 'detect_order' => self::$encodingList,
69070 'substitute_character' => 'none',
69071 'strict_detection' => 'Off',
69072 );
69073
69074 if ('all' === $type) {
69075 return $info;
69076 }
69077 if (isset($info[$type])) {
69078 return $info[$type];
69079 }
69080
69081 return false;
69082 }
69083
69084 public static function mb_http_input($type = '')
69085 {
69086 return false;
69087 }
69088
69089 public static function mb_http_output($encoding = null)
69090 {
69091 return null !== $encoding ? 'pass' === $encoding : 'pass';
69092 }
69093
69094 public static function mb_strwidth($s, $encoding = null)
69095 {
69096 $encoding = self::getEncoding($encoding);
69097
69098 if ('UTF-8' !== $encoding) {
69099 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
69100 }
69101
69102 $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);
69103
69104 return ($wide << 1) + iconv_strlen($s, 'UTF-8');
69105 }
69106
69107 public static function mb_substr_count($haystack, $needle, $encoding = null)
69108 {
69109 return substr_count($haystack, $needle);
69110 }
69111
69112 public static function mb_output_handler($contents, $status)
69113 {
69114 return $contents;
69115 }
69116
69117 public static function mb_chr($code, $encoding = null)
69118 {
69119 if (0x80 > $code %= 0x200000) {
69120 $s = chr($code);
69121 } elseif (0x800 > $code) {
69122 $s = chr(0xC0 | $code >> 6).chr(0x80 | $code & 0x3F);
69123 } elseif (0x10000 > $code) {
69124 $s = chr(0xE0 | $code >> 12).chr(0x80 | $code >> 6 & 0x3F).chr(0x80 | $code & 0x3F);
69125 } else {
69126 $s = chr(0xF0 | $code >> 18).chr(0x80 | $code >> 12 & 0x3F).chr(0x80 | $code >> 6 & 0x3F).chr(0x80 | $code & 0x3F);
69127 }
69128
69129 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
69130 $s = mb_convert_encoding($s, $encoding, 'UTF-8');
69131 }
69132
69133 return $s;
69134 }
69135
69136 public static function mb_ord($s, $encoding = null)
69137 {
69138 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
69139 $s = mb_convert_encoding($s, 'UTF-8', $encoding);
69140 }
69141
69142 $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
69143 if (0xF0 <= $code) {
69144 return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
69145 }
69146 if (0xE0 <= $code) {
69147 return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
69148 }
69149 if (0xC0 <= $code) {
69150 return (($code - 0xC0) << 6) + $s[2] - 0x80;
69151 }
69152
69153 return $code;
69154 }
69155
69156 private static function getSubpart($pos, $part, $haystack, $encoding)
69157 {
69158 if (false === $pos) {
69159 return false;
69160 }
69161 if ($part) {
69162 return self::mb_substr($haystack, 0, $pos, $encoding);
69163 }
69164
69165 return self::mb_substr($haystack, $pos, null, $encoding);
69166 }
69167
69168 private static function html_encoding_callback($m)
69169 {
69170 $i = 1;
69171 $entities = '';
69172 $m = unpack('C*', htmlentities($m[0], ENT_COMPAT, 'UTF-8'));
69173
69174 while (isset($m[$i])) {
69175 if (0x80 > $m[$i]) {
69176 $entities .= chr($m[$i++]);
69177 continue;
69178 }
69179 if (0xF0 <= $m[$i]) {
69180 $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
69181 } elseif (0xE0 <= $m[$i]) {
69182 $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
69183 } else {
69184 $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
69185 }
69186
69187 $entities .= '&#'.$c.';';
69188 }
69189
69190 return $entities;
69191 }
69192
69193 private static function title_case_lower($s)
69194 {
69195 return self::mb_convert_case($s[0], MB_CASE_LOWER, 'UTF-8');
69196 }
69197
69198 private static function title_case_upper($s)
69199 {
69200 return self::mb_convert_case($s[0], MB_CASE_UPPER, 'UTF-8');
69201 }
69202
69203 private static function getData($file)
69204 {
69205 if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
69206 return require $file;
69207 }
69208
69209 return false;
69210 }
69211
69212 private static function getEncoding($encoding)
69213 {
69214 if (null === $encoding) {
69215 return self::$internalEncoding;
69216 }
69217
69218 $encoding = strtoupper($encoding);
69219
69220 if ('8BIT' === $encoding || 'BINARY' === $encoding) {
69221 return 'CP850';
69222 }
69223 if ('UTF8' === $encoding) {
69224 return 'UTF-8';
69225 }
69226
69227 return $encoding;
69228 }
69229 }
69230 <?php
69231
69232 static $data = array (
69233 'A' => 'a',
69234 'B' => 'b',
69235 'C' => 'c',
69236 'D' => 'd',
69237 'E' => 'e',
69238 'F' => 'f',
69239 'G' => 'g',
69240 'H' => 'h',
69241 'I' => 'i',
69242 'J' => 'j',
69243 'K' => 'k',
69244 'L' => 'l',
69245 'M' => 'm',
69246 'N' => 'n',
69247 'O' => 'o',
69248 'P' => 'p',
69249 'Q' => 'q',
69250 'R' => 'r',
69251 'S' => 's',
69252 'T' => 't',
69253 'U' => 'u',
69254 'V' => 'v',
69255 'W' => 'w',
69256 'X' => 'x',
69257 'Y' => 'y',
69258 'Z' => 'z',
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 'Ć' => 'ć',
69293 'Ĉ' => 'ĉ',
69294 'Ċ' => 'ċ',
69295 'Č' => 'č',
69296 'Ď' => 'ď',
69297 'Đ' => 'đ',
69298 'Ē' => 'ē',
69299 'Ĕ' => 'ĕ',
69300 'Ė' => 'ė',
69301 'Ę' => 'ę',
69302 'Ě' => 'ě',
69303 'Ĝ' => 'ĝ',
69304 'Ğ' => 'ğ',
69305 'Ġ' => 'ġ',
69306 'Ģ' => 'ģ',
69307 'Ĥ' => 'ĥ',
69308 'Ħ' => 'ħ',
69309 'Ĩ' => 'ĩ',
69310 'Ī' => 'ī',
69311 'Ĭ' => 'ĭ',
69312 'Į' => 'į',
69313 'İ' => 'i',
69314 'IJ' => 'ij',
69315 'Ĵ' => 'ĵ',
69316 'Ķ' => 'ķ',
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 'DŽ' => 'dž',
69389 'Dž' => 'dž',
69390 'LJ' => 'lj',
69391 'Lj' => 'lj',
69392 'NJ' => 'nj',
69393 'Nj' => 'nj',
69394 'Ǎ' => 'ǎ',
69395 'Ǐ' => 'ǐ',
69396 'Ǒ' => 'ǒ',
69397 'Ǔ' => 'ǔ',
69398 'Ǖ' => 'ǖ',
69399 'Ǘ' => 'ǘ',
69400 'Ǚ' => 'ǚ',
69401 'Ǜ' => 'ǜ',
69402 'Ǟ' => 'ǟ',
69403 'Ǡ' => 'ǡ',
69404 'Ǣ' => 'ǣ',
69405 'Ǥ' => 'ǥ',
69406 'Ǧ' => 'ǧ',
69407 'Ǩ' => 'ǩ',
69408 'Ǫ' => 'ǫ',
69409 'Ǭ' => 'ǭ',
69410 'Ǯ' => 'ǯ',
69411 'DZ' => 'dz',
69412 'Dz' => 'dz',
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 'Ἁ' => 'ἁ',
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 'K' => 'k',
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 'Ꙏ' => 'ꙏ',
70132 'Ꙑ' => 'ꙑ',
70133 'Ꙓ' => 'ꙓ',
70134 'Ꙕ' => 'ꙕ',
70135 'Ꙗ' => 'ꙗ',
70136 'Ꙙ' => 'ꙙ',
70137 'Ꙛ' => 'ꙛ',
70138 'Ꙝ' => 'ꙝ',
70139 'Ꙟ' => 'ꙟ',
70140 'Ꙡ' => 'ꙡ',
70141 'Ꙣ' => 'ꙣ',
70142 'Ꙥ' => 'ꙥ',
70143 'Ꙧ' => 'ꙧ',
70144 'Ꙩ' => 'ꙩ',
70145 'Ꙫ' => 'ꙫ',
70146 'Ꙭ' => 'ꙭ',
70147 'Ꚁ' => 'ꚁ',
70148 'Ꚃ' => 'ꚃ',
70149 'Ꚅ' => 'ꚅ',
70150 'Ꚇ' => 'ꚇ',
70151 'Ꚉ' => 'ꚉ',
70152 'Ꚋ' => 'ꚋ',
70153 'Ꚍ' => 'ꚍ',
70154 'Ꚏ' => 'ꚏ',
70155 'Ꚑ' => 'ꚑ',
70156 'Ꚓ' => 'ꚓ',
70157 'Ꚕ' => 'ꚕ',
70158 'Ꚗ' => 'ꚗ',
70159 'Ꚙ' => 'ꚙ',
70160 'Ꚛ' => 'ꚛ',
70161 'Ꜣ' => 'ꜣ',
70162 'Ꜥ' => 'ꜥ',
70163 'Ꜧ' => 'ꜧ',
70164 'Ꜩ' => 'ꜩ',
70165 'Ꜫ' => 'ꜫ',
70166 'Ꜭ' => 'ꜭ',
70167 'Ꜯ' => 'ꜯ',
70168 'Ꜳ' => 'ꜳ',
70169 'Ꜵ' => 'ꜵ',
70170 'Ꜷ' => 'ꜷ',
70171 'Ꜹ' => 'ꜹ',
70172 'Ꜻ' => 'ꜻ',
70173 'Ꜽ' => 'ꜽ',
70174 'Ꜿ' => 'ꜿ',
70175 'Ꝁ' => 'ꝁ',
70176 'Ꝃ' => 'ꝃ',
70177 'Ꝅ' => 'ꝅ',
70178 'Ꝇ' => 'ꝇ',
70179 'Ꝉ' => 'ꝉ',
70180 'Ꝋ' => 'ꝋ',
70181 'Ꝍ' => 'ꝍ',
70182 'Ꝏ' => 'ꝏ',
70183 'Ꝑ' => 'ꝑ',
70184 'Ꝓ' => 'ꝓ',
70185 'Ꝕ' => 'ꝕ',
70186 'Ꝗ' => 'ꝗ',
70187 'Ꝙ' => 'ꝙ',
70188 'Ꝛ' => 'ꝛ',
70189 'Ꝝ' => 'ꝝ',
70190 'Ꝟ' => 'ꝟ',
70191 'Ꝡ' => 'ꝡ',
70192 'Ꝣ' => 'ꝣ',
70193 'Ꝥ' => 'ꝥ',
70194 'Ꝧ' => 'ꝧ',
70195 'Ꝩ' => 'ꝩ',
70196 'Ꝫ' => 'ꝫ',
70197 'Ꝭ' => 'ꝭ',
70198 'Ꝯ' => 'ꝯ',
70199 'Ꝺ' => 'ꝺ',
70200 'Ꝼ' => 'ꝼ',
70201 'Ᵹ' => 'ᵹ',
70202 'Ꝿ' => 'ꝿ',
70203 'Ꞁ' => 'ꞁ',
70204 'Ꞃ' => 'ꞃ',
70205 'Ꞅ' => 'ꞅ',
70206 'Ꞇ' => 'ꞇ',
70207 'Ꞌ' => 'ꞌ',
70208 'Ɥ' => 'ɥ',
70209 'Ꞑ' => 'ꞑ',
70210 'Ꞓ' => 'ꞓ',
70211 'Ꞗ' => 'ꞗ',
70212 'Ꞙ' => 'ꞙ',
70213 'Ꞛ' => 'ꞛ',
70214 'Ꞝ' => 'ꞝ',
70215 'Ꞟ' => 'ꞟ',
70216 'Ꞡ' => 'ꞡ',
70217 'Ꞣ' => 'ꞣ',
70218 'Ꞥ' => 'ꞥ',
70219 'Ꞧ' => 'ꞧ',
70220 'Ꞩ' => 'ꞩ',
70221 'Ɦ' => 'ɦ',
70222 'Ɜ' => 'ɜ',
70223 'Ɡ' => 'ɡ',
70224 'Ɬ' => 'ɬ',
70225 'Ʞ' => 'ʞ',
70226 'Ʇ' => 'ʇ',
70227 'A' => 'a',
70228 'B' => 'b',
70229 'C' => 'c',
70230 'D' => 'd',
70231 'E' => 'e',
70232 'F' => 'f',
70233 'G' => 'g',
70234 'H' => 'h',
70235 'I' => 'i',
70236 'J' => 'j',
70237 'K' => 'k',
70238 'L' => 'l',
70239 'M' => 'm',
70240 'N' => 'n',
70241 'O' => 'o',
70242 'P' => 'p',
70243 'Q' => 'q',
70244 'R' => 'r',
70245 'S' => 's',
70246 'T' => 't',
70247 'U' => 'u',
70248 'V' => 'v',
70249 'W' => 'w',
70250 'X' => 'x',
70251 'Y' => 'y',
70252 'Z' => 'z',
70253 '𐐀' => '𐐨',
70254 '𐐁' => '𐐩',
70255 '𐐂' => '𐐪',
70256 '𐐃' => '𐐫',
70257 '𐐄' => '𐐬',
70258 '𐐅' => '𐐭',
70259 '𐐆' => '𐐮',
70260 '𐐇' => '𐐯',
70261 '𐐈' => '𐐰',
70262 '𐐉' => '𐐱',
70263 '𐐊' => '𐐲',
70264 '𐐋' => '𐐳',
70265 '𐐌' => '𐐴',
70266 '𐐍' => '𐐵',
70267 '𐐎' => '𐐶',
70268 '𐐏' => '𐐷',
70269 '𐐐' => '𐐸',
70270 '𐐑' => '𐐹',
70271 '𐐒' => '𐐺',
70272 '𐐓' => '𐐻',
70273 '𐐔' => '𐐼',
70274 '𐐕' => '𐐽',
70275 '𐐖' => '𐐾',
70276 '𐐗' => '𐐿',
70277 '𐐘' => '𐑀',
70278 '𐐙' => '𐑁',
70279 '𐐚' => '𐑂',
70280 '𐐛' => '𐑃',
70281 '𐐜' => '𐑄',
70282 '𐐝' => '𐑅',
70283 '𐐞' => '𐑆',
70284 '𐐟' => '𐑇',
70285 '𐐠' => '𐑈',
70286 '𐐡' => '𐑉',
70287 '𐐢' => '𐑊',
70288 '𐐣' => '𐑋',
70289 '𐐤' => '𐑌',
70290 '𐐥' => '𐑍',
70291 '𐐦' => '𐑎',
70292 '𐐧' => '𐑏',
70293 '𑢠' => '𑣀',
70294 '𑢡' => '𑣁',
70295 '𑢢' => '𑣂',
70296 '𑢣' => '𑣃',
70297 '𑢤' => '𑣄',
70298 '𑢥' => '𑣅',
70299 '𑢦' => '𑣆',
70300 '𑢧' => '𑣇',
70301 '𑢨' => '𑣈',
70302 '𑢩' => '𑣉',
70303 '𑢪' => '𑣊',
70304 '𑢫' => '𑣋',
70305 '𑢬' => '𑣌',
70306 '𑢭' => '𑣍',
70307 '𑢮' => '𑣎',
70308 '𑢯' => '𑣏',
70309 '𑢰' => '𑣐',
70310 '𑢱' => '𑣑',
70311 '𑢲' => '𑣒',
70312 '𑢳' => '𑣓',
70313 '𑢴' => '𑣔',
70314 '𑢵' => '𑣕',
70315 '𑢶' => '𑣖',
70316 '𑢷' => '𑣗',
70317 '𑢸' => '𑣘',
70318 '𑢹' => '𑣙',
70319 '𑢺' => '𑣚',
70320 '𑢻' => '𑣛',
70321 '𑢼' => '𑣜',
70322 '𑢽' => '𑣝',
70323 '𑢾' => '𑣞',
70324 '𑢿' => '𑣟',
70325 );
70326
70327 $result =& $data;
70328 unset($data);
70329
70330 return $result;
70331 <?php
70332
70333 static $data = array (
70334 'a' => 'A',
70335 'b' => 'B',
70336 'c' => 'C',
70337 'd' => 'D',
70338 'e' => 'E',
70339 'f' => 'F',
70340 'g' => 'G',
70341 'h' => 'H',
70342 'i' => 'I',
70343 'j' => 'J',
70344 'k' => 'K',
70345 'l' => 'L',
70346 'm' => 'M',
70347 'n' => 'N',
70348 'o' => 'O',
70349 'p' => 'P',
70350 'q' => 'Q',
70351 'r' => 'R',
70352 's' => 'S',
70353 't' => 'T',
70354 'u' => 'U',
70355 'v' => 'V',
70356 'w' => 'W',
70357 'x' => 'X',
70358 'y' => 'Y',
70359 'z' => 'Z',
70360 'µ' => 'Μ',
70361 'à' => 'À',
70362 'á' => 'Á',
70363 'â' => 'Â',
70364 'ã' => 'Ã',
70365 'ä' => 'Ä',
70366 'å' => 'Å',
70367 'æ' => 'Æ',
70368 'ç' => 'Ç',
70369 'è' => 'È',
70370 'é' => 'É',
70371 'ê' => 'Ê',
70372 'ë' => 'Ë',
70373 'ì' => 'Ì',
70374 'í' => 'Í',
70375 'î' => 'Î',
70376 'ï' => 'Ï',
70377 'ð' => 'Ð',
70378 'ñ' => 'Ñ',
70379 'ò' => 'Ò',
70380 'ó' => 'Ó',
70381 'ô' => 'Ô',
70382 'õ' => 'Õ',
70383 'ö' => 'Ö',
70384 'ø' => 'Ø',
70385 'ù' => 'Ù',
70386 'ú' => 'Ú',
70387 'û' => 'Û',
70388 'ü' => 'Ü',
70389 'ý' => 'Ý',
70390 'þ' => 'Þ',
70391 'ÿ' => 'Ÿ',
70392 'ā' => 'Ā',
70393 'ă' => 'Ă',
70394 'ą' => 'Ą',
70395 'ć' => 'Ć',
70396 'ĉ' => 'Ĉ',
70397 'ċ' => 'Ċ',
70398 'č' => 'Č',
70399 'ď' => 'Ď',
70400 'đ' => 'Đ',
70401 'ē' => 'Ē',
70402 'ĕ' => 'Ĕ',
70403 'ė' => 'Ė',
70404 'ę' => 'Ę',
70405 'ě' => 'Ě',
70406 'ĝ' => 'Ĝ',
70407 'ğ' => 'Ğ',
70408 'ġ' => 'Ġ',
70409 'ģ' => 'Ģ',
70410 'ĥ' => 'Ĥ',
70411 'ħ' => 'Ħ',
70412 'ĩ' => 'Ĩ',
70413 'ī' => 'Ī',
70414 'ĭ' => 'Ĭ',
70415 'į' => 'Į',
70416 'ı' => 'I',
70417 'ij' => 'IJ',
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 'ſ' => 'S',
70455 'ƀ' => 'Ƀ',
70456 'ƃ' => 'Ƃ',
70457 'ƅ' => 'Ƅ',
70458 'ƈ' => 'Ƈ',
70459 'ƌ' => 'Ƌ',
70460 'ƒ' => 'Ƒ',
70461 'ƕ' => 'Ƕ',
70462 'ƙ' => 'Ƙ',
70463 'ƚ' => 'Ƚ',
70464 'ƞ' => 'Ƞ',
70465 'ơ' => 'Ơ',
70466 'ƣ' => 'Ƣ',
70467 'ƥ' => 'Ƥ',
70468 'ƨ' => 'Ƨ',
70469 'ƭ' => 'Ƭ',
70470 'ư' => 'Ư',
70471 'ƴ' => 'Ƴ',
70472 'ƶ' => 'Ƶ',
70473 'ƹ' => 'Ƹ',
70474 'ƽ' => 'Ƽ',
70475 'ƿ' => 'Ƿ',
70476 'Dž' => 'DŽ',
70477 'dž' => 'DŽ',
70478 'Lj' => 'LJ',
70479 'lj' => 'LJ',
70480 'Nj' => 'NJ',
70481 'nj' => 'NJ',
70482 'ǎ' => 'Ǎ',
70483 'ǐ' => 'Ǐ',
70484 'ǒ' => 'Ǒ',
70485 'ǔ' => 'Ǔ',
70486 'ǖ' => 'Ǖ',
70487 'ǘ' => 'Ǘ',
70488 'ǚ' => 'Ǚ',
70489 'ǜ' => 'Ǜ',
70490 'ǝ' => 'Ǝ',
70491 'ǟ' => 'Ǟ',
70492 'ǡ' => 'Ǡ',
70493 'ǣ' => 'Ǣ',
70494 'ǥ' => 'Ǥ',
70495 'ǧ' => 'Ǧ',
70496 'ǩ' => 'Ǩ',
70497 'ǫ' => 'Ǫ',
70498 'ǭ' => 'Ǭ',
70499 'ǯ' => 'Ǯ',
70500 'Dz' => 'DZ',
70501 'dz' => 'DZ',
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 'ⴭ' => 'Ⴭ',
71241 'ꙁ' => 'Ꙁ',
71242 'ꙃ' => 'Ꙃ',
71243 'ꙅ' => 'Ꙅ',
71244 'ꙇ' => 'Ꙇ',
71245 'ꙉ' => 'Ꙉ',
71246 'ꙋ' => 'Ꙋ',
71247 'ꙍ' => 'Ꙍ',
71248 'ꙏ' => 'Ꙏ',
71249 'ꙑ' => 'Ꙑ',
71250 'ꙓ' => 'Ꙓ',
71251 'ꙕ' => 'Ꙕ',
71252 'ꙗ' => 'Ꙗ',
71253 'ꙙ' => 'Ꙙ',
71254 'ꙛ' => 'Ꙛ',
71255 'ꙝ' => 'Ꙝ',
71256 'ꙟ' => 'Ꙟ',
71257 'ꙡ' => 'Ꙡ',
71258 'ꙣ' => 'Ꙣ',
71259 'ꙥ' => 'Ꙥ',
71260 'ꙧ' => 'Ꙧ',
71261 'ꙩ' => 'Ꙩ',
71262 'ꙫ' => 'Ꙫ',
71263 'ꙭ' => 'Ꙭ',
71264 'ꚁ' => 'Ꚁ',
71265 'ꚃ' => 'Ꚃ',
71266 'ꚅ' => 'Ꚅ',
71267 'ꚇ' => 'Ꚇ',
71268 'ꚉ' => 'Ꚉ',
71269 'ꚋ' => 'Ꚋ',
71270 'ꚍ' => 'Ꚍ',
71271 'ꚏ' => 'Ꚏ',
71272 'ꚑ' => 'Ꚑ',
71273 'ꚓ' => 'Ꚓ',
71274 'ꚕ' => 'Ꚕ',
71275 'ꚗ' => 'Ꚗ',
71276 'ꚙ' => 'Ꚙ',
71277 'ꚛ' => 'Ꚛ',
71278 'ꜣ' => 'Ꜣ',
71279 'ꜥ' => 'Ꜥ',
71280 'ꜧ' => 'Ꜧ',
71281 'ꜩ' => 'Ꜩ',
71282 'ꜫ' => 'Ꜫ',
71283 'ꜭ' => 'Ꜭ',
71284 'ꜯ' => 'Ꜯ',
71285 'ꜳ' => 'Ꜳ',
71286 'ꜵ' => 'Ꜵ',
71287 'ꜷ' => 'Ꜷ',
71288 'ꜹ' => 'Ꜹ',
71289 'ꜻ' => 'Ꜻ',
71290 'ꜽ' => 'Ꜽ',
71291 'ꜿ' => 'Ꜿ',
71292 'ꝁ' => 'Ꝁ',
71293 'ꝃ' => 'Ꝃ',
71294 'ꝅ' => 'Ꝅ',
71295 'ꝇ' => 'Ꝇ',
71296 'ꝉ' => 'Ꝉ',
71297 'ꝋ' => 'Ꝋ',
71298 'ꝍ' => 'Ꝍ',
71299 'ꝏ' => 'Ꝏ',
71300 'ꝑ' => 'Ꝑ',
71301 'ꝓ' => 'Ꝓ',
71302 'ꝕ' => 'Ꝕ',
71303 'ꝗ' => 'Ꝗ',
71304 'ꝙ' => 'Ꝙ',
71305 'ꝛ' => 'Ꝛ',
71306 'ꝝ' => 'Ꝝ',
71307 'ꝟ' => 'Ꝟ',
71308 'ꝡ' => 'Ꝡ',
71309 'ꝣ' => 'Ꝣ',
71310 'ꝥ' => 'Ꝥ',
71311 'ꝧ' => 'Ꝧ',
71312 'ꝩ' => 'Ꝩ',
71313 'ꝫ' => 'Ꝫ',
71314 'ꝭ' => 'Ꝭ',
71315 'ꝯ' => 'Ꝯ',
71316 'ꝺ' => 'Ꝺ',
71317 'ꝼ' => 'Ꝼ',
71318 'ꝿ' => 'Ꝿ',
71319 'ꞁ' => 'Ꞁ',
71320 'ꞃ' => 'Ꞃ',
71321 'ꞅ' => 'Ꞅ',
71322 'ꞇ' => 'Ꞇ',
71323 'ꞌ' => 'Ꞌ',
71324 'ꞑ' => 'Ꞑ',
71325 'ꞓ' => 'Ꞓ',
71326 'ꞗ' => 'Ꞗ',
71327 'ꞙ' => 'Ꞙ',
71328 'ꞛ' => 'Ꞛ',
71329 'ꞝ' => 'Ꞝ',
71330 'ꞟ' => 'Ꞟ',
71331 'ꞡ' => 'Ꞡ',
71332 'ꞣ' => 'Ꞣ',
71333 'ꞥ' => 'Ꞥ',
71334 'ꞧ' => 'Ꞧ',
71335 'ꞩ' => 'Ꞩ',
71336 'a' => 'A',
71337 'b' => 'B',
71338 'c' => 'C',
71339 'd' => 'D',
71340 'e' => 'E',
71341 'f' => 'F',
71342 'g' => 'G',
71343 'h' => 'H',
71344 'i' => 'I',
71345 'j' => 'J',
71346 'k' => 'K',
71347 'l' => 'L',
71348 'm' => 'M',
71349 'n' => 'N',
71350 'o' => 'O',
71351 'p' => 'P',
71352 'q' => 'Q',
71353 'r' => 'R',
71354 's' => 'S',
71355 't' => 'T',
71356 'u' => 'U',
71357 'v' => 'V',
71358 'w' => 'W',
71359 'x' => 'X',
71360 'y' => 'Y',
71361 'z' => 'Z',
71362 '𐐨' => '𐐀',
71363 '𐐩' => '𐐁',
71364 '𐐪' => '𐐂',
71365 '𐐫' => '𐐃',
71366 '𐐬' => '𐐄',
71367 '𐐭' => '𐐅',
71368 '𐐮' => '𐐆',
71369 '𐐯' => '𐐇',
71370 '𐐰' => '𐐈',
71371 '𐐱' => '𐐉',
71372 '𐐲' => '𐐊',
71373 '𐐳' => '𐐋',
71374 '𐐴' => '𐐌',
71375 '𐐵' => '𐐍',
71376 '𐐶' => '𐐎',
71377 '𐐷' => '𐐏',
71378 '𐐸' => '𐐐',
71379 '𐐹' => '𐐑',
71380 '𐐺' => '𐐒',
71381 '𐐻' => '𐐓',
71382 '𐐼' => '𐐔',
71383 '𐐽' => '𐐕',
71384 '𐐾' => '𐐖',
71385 '𐐿' => '𐐗',
71386 '𐑀' => '𐐘',
71387 '𐑁' => '𐐙',
71388 '𐑂' => '𐐚',
71389 '𐑃' => '𐐛',
71390 '𐑄' => '𐐜',
71391 '𐑅' => '𐐝',
71392 '𐑆' => '𐐞',
71393 '𐑇' => '𐐟',
71394 '𐑈' => '𐐠',
71395 '𐑉' => '𐐡',
71396 '𐑊' => '𐐢',
71397 '𐑋' => '𐐣',
71398 '𐑌' => '𐐤',
71399 '𐑍' => '𐐥',
71400 '𐑎' => '𐐦',
71401 '𐑏' => '𐐧',
71402 '𑣀' => '𑢠',
71403 '𑣁' => '𑢡',
71404 '𑣂' => '𑢢',
71405 '𑣃' => '𑢣',
71406 '𑣄' => '𑢤',
71407 '𑣅' => '𑢥',
71408 '𑣆' => '𑢦',
71409 '𑣇' => '𑢧',
71410 '𑣈' => '𑢨',
71411 '𑣉' => '𑢩',
71412 '𑣊' => '𑢪',
71413 '𑣋' => '𑢫',
71414 '𑣌' => '𑢬',
71415 '𑣍' => '𑢭',
71416 '𑣎' => '𑢮',
71417 '𑣏' => '𑢯',
71418 '𑣐' => '𑢰',
71419 '𑣑' => '𑢱',
71420 '𑣒' => '𑢲',
71421 '𑣓' => '𑢳',
71422 '𑣔' => '𑢴',
71423 '𑣕' => '𑢵',
71424 '𑣖' => '𑢶',
71425 '𑣗' => '𑢷',
71426 '𑣘' => '𑢸',
71427 '𑣙' => '𑢹',
71428 '𑣚' => '𑢺',
71429 '𑣛' => '𑢻',
71430 '𑣜' => '𑢼',
71431 '𑣝' => '𑢽',
71432 '𑣞' => '𑢾',
71433 '𑣟' => '𑢿',
71434 );
71435
71436 $result =& $data;
71437 unset($data);
71438
71439 return $result;
71440 <?php
71441
71442
71443
71444
71445
71446
71447
71448
71449
71450
71451 use Symfony\Polyfill\Mbstring as p;
71452
71453 if (!function_exists('mb_strlen')) {
71454 define('MB_CASE_UPPER', 0);
71455 define('MB_CASE_LOWER', 1);
71456 define('MB_CASE_TITLE', 2);
71457
71458 function mb_convert_encoding($s, $to, $from = null) { return p\Mbstring::mb_convert_encoding($s, $to, $from); }
71459 function mb_decode_mimeheader($s) { return p\Mbstring::mb_decode_mimeheader($s); }
71460 function mb_encode_mimeheader($s, $charset = null, $transferEnc = null, $lf = null, $indent = null) { return p\Mbstring::mb_encode_mimeheader($s, $charset, $transferEnc, $lf, $indent); }
71461 function mb_convert_case($s, $mode, $enc = null) { return p\Mbstring::mb_convert_case($s, $mode, $enc); }
71462 function mb_internal_encoding($enc = null) { return p\Mbstring::mb_internal_encoding($enc); }
71463 function mb_language($lang = null) { return p\Mbstring::mb_language($lang); }
71464 function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); }
71465 function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); }
71466 function mb_check_encoding($var = null, $encoding = null) { return p\Mbstring::mb_check_encoding($var, $encoding); }
71467 function mb_detect_encoding($str, $encodingList = null, $strict = false) { return p\Mbstring::mb_detect_encoding($str, $encodingList, $strict); }
71468 function mb_detect_order($encodingList = null) { return p\Mbstring::mb_detect_order($encodingList); }
71469 function mb_parse_str($s, &$result = array()) { parse_str($s, $result); }
71470 function mb_strlen($s, $enc = null) { return p\Mbstring::mb_strlen($s, $enc); }
71471 function mb_strpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strpos($s, $needle, $offset, $enc); }
71472 function mb_strtolower($s, $enc = null) { return p\Mbstring::mb_strtolower($s, $enc); }
71473 function mb_strtoupper($s, $enc = null) { return p\Mbstring::mb_strtoupper($s, $enc); }
71474 function mb_substitute_character($char = null) { return p\Mbstring::mb_substitute_character($char); }
71475 function mb_substr($s, $start, $length = 2147483647, $enc = null) { return p\Mbstring::mb_substr($s, $start, $length, $enc); }
71476 function mb_stripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_stripos($s, $needle, $offset, $enc); }
71477 function mb_stristr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_stristr($s, $needle, $part, $enc); }
71478 function mb_strrchr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrchr($s, $needle, $part, $enc); }
71479 function mb_strrichr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrichr($s, $needle, $part, $enc); }
71480 function mb_strripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strripos($s, $needle, $offset, $enc); }
71481 function mb_strrpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strrpos($s, $needle, $offset, $enc); }
71482 function mb_strstr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strstr($s, $needle, $part, $enc); }
71483 function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); }
71484 function mb_http_output($enc = null) { return p\Mbstring::mb_http_output($enc); }
71485 function mb_strwidth($s, $enc = null) { return p\Mbstring::mb_strwidth($s, $enc); }
71486 function mb_substr_count($haystack, $needle, $enc = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $enc); }
71487 function mb_output_handler($contents, $status) { return p\Mbstring::mb_output_handler($contents, $status); }
71488 function mb_http_input($type = '') { return p\Mbstring::mb_http_input($type); }
71489 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); }
71490 }
71491 if (!function_exists('mb_chr')) {
71492 function mb_ord($s, $enc = null) { return p\Mbstring::mb_ord($s, $enc); }
71493 function mb_chr($code, $enc = null) { return p\Mbstring::mb_chr($code, $enc); }
71494 function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); }
71495 }
71496 <?php
71497
71498
71499
71500
71501
71502
71503
71504
71505
71506
71507 namespace Symfony\Component\Process\Exception;
71508
71509
71510
71511
71512
71513
71514 interface ExceptionInterface
71515 {
71516 }
71517 <?php
71518
71519
71520
71521
71522
71523
71524
71525
71526
71527
71528 namespace Symfony\Component\Process\Exception;
71529
71530
71531
71532
71533
71534
71535 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
71536 {
71537 }
71538 <?php
71539
71540
71541
71542
71543
71544
71545
71546
71547
71548
71549 namespace Symfony\Component\Process\Exception;
71550
71551
71552
71553
71554
71555
71556 class LogicException extends \LogicException implements ExceptionInterface
71557 {
71558 }
71559 <?php
71560
71561
71562
71563
71564
71565
71566
71567
71568
71569
71570 namespace Symfony\Component\Process\Exception;
71571
71572 use Symfony\Component\Process\Process;
71573
71574
71575
71576
71577
71578
71579 class ProcessFailedException extends RuntimeException
71580 {
71581 private $process;
71582
71583 public function __construct(Process $process)
71584 {
71585 if ($process->isSuccessful()) {
71586 throw new InvalidArgumentException('Expected a failed process, but the given process was successful.');
71587 }
71588
71589 $error = sprintf('The command "%s" failed.'."\n\nExit Code: %s(%s)\n\nWorking directory: %s",
71590 $process->getCommandLine(),
71591 $process->getExitCode(),
71592 $process->getExitCodeText(),
71593 $process->getWorkingDirectory()
71594 );
71595
71596 if (!$process->isOutputDisabled()) {
71597 $error .= sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s",
71598 $process->getOutput(),
71599 $process->getErrorOutput()
71600 );
71601 }
71602
71603 parent::__construct($error);
71604
71605 $this->process = $process;
71606 }
71607
71608 public function getProcess()
71609 {
71610 return $this->process;
71611 }
71612 }
71613 <?php
71614
71615
71616
71617
71618
71619
71620
71621
71622
71623
71624 namespace Symfony\Component\Process\Exception;
71625
71626 use Symfony\Component\Process\Process;
71627
71628
71629
71630
71631
71632
71633 class ProcessTimedOutException extends RuntimeException
71634 {
71635 const TYPE_GENERAL = 1;
71636 const TYPE_IDLE = 2;
71637
71638 private $process;
71639 private $timeoutType;
71640
71641 public function __construct(Process $process, $timeoutType)
71642 {
71643 $this->process = $process;
71644 $this->timeoutType = $timeoutType;
71645
71646 parent::__construct(sprintf(
71647 'The process "%s" exceeded the timeout of %s seconds.',
71648 $process->getCommandLine(),
71649 $this->getExceededTimeout()
71650 ));
71651 }
71652
71653 public function getProcess()
71654 {
71655 return $this->process;
71656 }
71657
71658 public function isGeneralTimeout()
71659 {
71660 return $this->timeoutType === self::TYPE_GENERAL;
71661 }
71662
71663 public function isIdleTimeout()
71664 {
71665 return $this->timeoutType === self::TYPE_IDLE;
71666 }
71667
71668 public function getExceededTimeout()
71669 {
71670 switch ($this->timeoutType) {
71671 case self::TYPE_GENERAL:
71672 return $this->process->getTimeout();
71673
71674 case self::TYPE_IDLE:
71675 return $this->process->getIdleTimeout();
71676
71677 default:
71678 throw new \LogicException(sprintf('Unknown timeout type "%d".', $this->timeoutType));
71679 }
71680 }
71681 }
71682 <?php
71683
71684
71685
71686
71687
71688
71689
71690
71691
71692
71693 namespace Symfony\Component\Process\Exception;
71694
71695
71696
71697
71698
71699
71700 class RuntimeException extends \RuntimeException implements ExceptionInterface
71701 {
71702 }
71703 <?php
71704
71705
71706
71707
71708
71709
71710
71711
71712
71713
71714 namespace Symfony\Component\Process;
71715
71716
71717
71718
71719
71720
71721
71722 class ExecutableFinder
71723 {
71724 private $suffixes = array('.exe', '.bat', '.cmd', '.com');
71725
71726
71727
71728
71729
71730
71731 public function setSuffixes(array $suffixes)
71732 {
71733 $this->suffixes = $suffixes;
71734 }
71735
71736
71737
71738
71739
71740
71741 public function addSuffix($suffix)
71742 {
71743 $this->suffixes[] = $suffix;
71744 }
71745
71746
71747
71748
71749
71750
71751
71752
71753
71754
71755 public function find($name, $default = null, array $extraDirs = array())
71756 {
71757 if (ini_get('open_basedir')) {
71758 $searchPath = explode(PATH_SEPARATOR, ini_get('open_basedir'));
71759 $dirs = array();
71760 foreach ($searchPath as $path) {
71761
71762  if (@is_dir($path)) {
71763 $dirs[] = $path;
71764 } else {
71765 if (basename($path) == $name && @is_executable($path)) {
71766 return $path;
71767 }
71768 }
71769 }
71770 } else {
71771 $dirs = array_merge(
71772 explode(PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')),
71773 $extraDirs
71774 );
71775 }
71776
71777 $suffixes = array('');
71778 if ('\\' === DIRECTORY_SEPARATOR) {
71779 $pathExt = getenv('PATHEXT');
71780 $suffixes = array_merge($suffixes, $pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes);
71781 }
71782 foreach ($suffixes as $suffix) {
71783 foreach ($dirs as $dir) {
71784 if (@is_file($file = $dir.DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === DIRECTORY_SEPARATOR || is_executable($file))) {
71785 return $file;
71786 }
71787 }
71788 }
71789
71790 return $default;
71791 }
71792 }
71793 Copyright (c) 2004-2017 Fabien Potencier
71794
71795 Permission is hereby granted, free of charge, to any person obtaining a copy
71796 of this software and associated documentation files (the "Software"), to deal
71797 in the Software without restriction, including without limitation the rights
71798 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
71799 copies of the Software, and to permit persons to whom the Software is furnished
71800 to do so, subject to the following conditions:
71801
71802 The above copyright notice and this permission notice shall be included in all
71803 copies or substantial portions of the Software.
71804
71805 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
71806 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
71807 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
71808 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
71809 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
71810 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
71811 THE SOFTWARE.
71812 <?php
71813
71814
71815
71816
71817
71818
71819
71820
71821
71822
71823 namespace Symfony\Component\Process;
71824
71825
71826
71827
71828
71829
71830
71831 class PhpExecutableFinder
71832 {
71833 private $executableFinder;
71834
71835 public function __construct()
71836 {
71837 $this->executableFinder = new ExecutableFinder();
71838 }
71839
71840
71841
71842
71843
71844
71845
71846
71847 public function find($includeArgs = true)
71848 {
71849 $args = $this->findArguments();
71850 $args = $includeArgs && $args ? ' '.implode(' ', $args) : '';
71851
71852
71853  if (defined('HHVM_VERSION')) {
71854 return (getenv('PHP_BINARY') ?: PHP_BINARY).$args;
71855 }
71856
71857
71858  if (defined('PHP_BINARY') && PHP_BINARY && in_array(PHP_SAPI, array('cli', 'cli-server', 'phpdbg')) && is_file(PHP_BINARY)) {
71859 return PHP_BINARY.$args;
71860 }
71861
71862 if ($php = getenv('PHP_PATH')) {
71863 if (!is_executable($php)) {
71864 return false;
71865 }
71866
71867 return $php;
71868 }
71869
71870 if ($php = getenv('PHP_PEAR_PHP_BIN')) {
71871 if (is_executable($php)) {
71872 return $php;
71873 }
71874 }
71875
71876 $dirs = array(PHP_BINDIR);
71877 if ('\\' === DIRECTORY_SEPARATOR) {
71878 $dirs[] = 'C:\xampp\php\\';
71879 }
71880
71881 return $this->executableFinder->find('php', false, $dirs);
71882 }
71883
71884
71885
71886
71887
71888
71889 public function findArguments()
71890 {
71891 $arguments = array();
71892
71893 if (defined('HHVM_VERSION')) {
71894 $arguments[] = '--php';
71895 } elseif ('phpdbg' === PHP_SAPI) {
71896 $arguments[] = '-qrr';
71897 }
71898
71899 return $arguments;
71900 }
71901 }
71902 <?php
71903
71904
71905
71906
71907
71908
71909
71910
71911
71912
71913 namespace Symfony\Component\Process;
71914
71915 use Symfony\Component\Process\Exception\RuntimeException;
71916
71917
71918
71919
71920
71921
71922
71923
71924
71925
71926 class PhpProcess extends Process
71927 {
71928
71929
71930
71931
71932
71933
71934
71935
71936
71937 public function __construct($script, $cwd = null, array $env = null, $timeout = 60, array $options = array())
71938 {
71939 $executableFinder = new PhpExecutableFinder();
71940 if (false === $php = $executableFinder->find()) {
71941 $php = null;
71942 }
71943 if ('phpdbg' === PHP_SAPI) {
71944 $file = tempnam(sys_get_temp_dir(), 'dbg');
71945 file_put_contents($file, $script);
71946 register_shutdown_function('unlink', $file);
71947 $php .= ' '.ProcessUtils::escapeArgument($file);
71948 $script = null;
71949 }
71950 if ('\\' !== DIRECTORY_SEPARATOR && null !== $php) {
71951
71952  
71953  
71954  $php = 'exec '.$php;
71955 }
71956
71957 parent::__construct($php, $cwd, $env, $script, $timeout, $options);
71958 }
71959
71960
71961
71962
71963 public function setPhpBinary($php)
71964 {
71965 $this->setCommandLine($php);
71966 }
71967
71968
71969
71970
71971 public function start($callback = null)
71972 {
71973 if (null === $this->getCommandLine()) {
71974 throw new RuntimeException('Unable to find the PHP executable.');
71975 }
71976
71977 parent::start($callback);
71978 }
71979 }
71980 <?php
71981
71982
71983
71984
71985
71986
71987
71988
71989
71990
71991 namespace Symfony\Component\Process\Pipes;
71992
71993
71994
71995
71996
71997
71998 abstract class AbstractPipes implements PipesInterface
71999 {
72000
72001 public $pipes = array();
72002
72003
72004 private $inputBuffer = '';
72005
72006 private $input;
72007
72008 private $blocked = true;
72009
72010 public function __construct($input)
72011 {
72012 if (is_resource($input)) {
72013 $this->input = $input;
72014 } elseif (is_string($input)) {
72015 $this->inputBuffer = $input;
72016 } else {
72017 $this->inputBuffer = (string) $input;
72018 }
72019 }
72020
72021
72022
72023
72024 public function close()
72025 {
72026 foreach ($this->pipes as $pipe) {
72027 fclose($pipe);
72028 }
72029 $this->pipes = array();
72030 }
72031
72032
72033
72034
72035
72036
72037 protected function hasSystemCallBeenInterrupted()
72038 {
72039 $lastError = error_get_last();
72040
72041
72042  return isset($lastError['message']) && false !== stripos($lastError['message'], 'interrupted system call');
72043 }
72044
72045
72046
72047
72048 protected function unblock()
72049 {
72050 if (!$this->blocked) {
72051 return;
72052 }
72053
72054 foreach ($this->pipes as $pipe) {
72055 stream_set_blocking($pipe, 0);
72056 }
72057 if (null !== $this->input) {
72058 stream_set_blocking($this->input, 0);
72059 }
72060
72061 $this->blocked = false;
72062 }
72063
72064
72065
72066
72067 protected function write()
72068 {
72069 if (!isset($this->pipes[0])) {
72070 return;
72071 }
72072 $input = $this->input;
72073 $r = $e = array();
72074 $w = array($this->pipes[0]);
72075
72076
72077  if (false === $n = @stream_select($r, $w, $e, 0, 0)) {
72078 return;
72079 }
72080
72081 foreach ($w as $stdin) {
72082 if (isset($this->inputBuffer[0])) {
72083 $written = fwrite($stdin, $this->inputBuffer);
72084 $this->inputBuffer = substr($this->inputBuffer, $written);
72085 if (isset($this->inputBuffer[0])) {
72086 return array($this->pipes[0]);
72087 }
72088 }
72089
72090 if ($input) {
72091 for (;;) {
72092 $data = fread($input, self::CHUNK_SIZE);
72093 if (!isset($data[0])) {
72094 break;
72095 }
72096 $written = fwrite($stdin, $data);
72097 $data = substr($data, $written);
72098 if (isset($data[0])) {
72099 $this->inputBuffer = $data;
72100
72101 return array($this->pipes[0]);
72102 }
72103 }
72104 if (feof($input)) {
72105
72106  
72107  $this->input = null;
72108 }
72109 }
72110 }
72111
72112
72113  if (null === $this->input && !isset($this->inputBuffer[0])) {
72114 fclose($this->pipes[0]);
72115 unset($this->pipes[0]);
72116 } elseif (!$w) {
72117 return array($this->pipes[0]);
72118 }
72119 }
72120 }
72121 <?php
72122
72123
72124
72125
72126
72127
72128
72129
72130
72131
72132 namespace Symfony\Component\Process\Pipes;
72133
72134
72135
72136
72137
72138
72139
72140
72141 interface PipesInterface
72142 {
72143 const CHUNK_SIZE = 16384;
72144
72145
72146
72147
72148
72149
72150 public function getDescriptors();
72151
72152
72153
72154
72155
72156
72157 public function getFiles();
72158
72159
72160
72161
72162
72163
72164
72165
72166
72167 public function readAndWrite($blocking, $close = false);
72168
72169
72170
72171
72172
72173
72174 public function areOpen();
72175
72176
72177
72178
72179 public function close();
72180 }
72181 <?php
72182
72183
72184
72185
72186
72187
72188
72189
72190
72191
72192 namespace Symfony\Component\Process\Pipes;
72193
72194 use Symfony\Component\Process\Process;
72195
72196
72197
72198
72199
72200
72201
72202
72203 class UnixPipes extends AbstractPipes
72204 {
72205
72206 private $ttyMode;
72207
72208 private $ptyMode;
72209
72210 private $disableOutput;
72211
72212 public function __construct($ttyMode, $ptyMode, $input, $disableOutput)
72213 {
72214 $this->ttyMode = (bool) $ttyMode;
72215 $this->ptyMode = (bool) $ptyMode;
72216 $this->disableOutput = (bool) $disableOutput;
72217
72218 parent::__construct($input);
72219 }
72220
72221 public function __destruct()
72222 {
72223 $this->close();
72224 }
72225
72226
72227
72228
72229 public function getDescriptors()
72230 {
72231 if ($this->disableOutput) {
72232 $nullstream = fopen('/dev/null', 'c');
72233
72234 return array(
72235 array('pipe', 'r'),
72236 $nullstream,
72237 $nullstream,
72238 );
72239 }
72240
72241 if ($this->ttyMode) {
72242 return array(
72243 array('file', '/dev/tty', 'r'),
72244 array('file', '/dev/tty', 'w'),
72245 array('file', '/dev/tty', 'w'),
72246 );
72247 }
72248
72249 if ($this->ptyMode && Process::isPtySupported()) {
72250 return array(
72251 array('pty'),
72252 array('pty'),
72253 array('pty'),
72254 );
72255 }
72256
72257 return array(
72258 array('pipe', 'r'),
72259 array('pipe', 'w'), 
72260  array('pipe', 'w'), 
72261  );
72262 }
72263
72264
72265
72266
72267 public function getFiles()
72268 {
72269 return array();
72270 }
72271
72272
72273
72274
72275 public function readAndWrite($blocking, $close = false)
72276 {
72277 $this->unblock();
72278 $w = $this->write();
72279
72280 $read = $e = array();
72281 $r = $this->pipes;
72282 unset($r[0]);
72283
72284
72285  if (($r || $w) && false === $n = @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
72286
72287  
72288  if (!$this->hasSystemCallBeenInterrupted()) {
72289 $this->pipes = array();
72290 }
72291
72292 return $read;
72293 }
72294
72295 foreach ($r as $pipe) {
72296
72297  
72298  $read[$type = array_search($pipe, $this->pipes, true)] = '';
72299
72300 do {
72301 $data = fread($pipe, self::CHUNK_SIZE);
72302 $read[$type] .= $data;
72303 } while (isset($data[0]) && ($close || isset($data[self::CHUNK_SIZE - 1])));
72304
72305 if (!isset($read[$type][0])) {
72306 unset($read[$type]);
72307 }
72308
72309 if ($close && feof($pipe)) {
72310 fclose($pipe);
72311 unset($this->pipes[$type]);
72312 }
72313 }
72314
72315 return $read;
72316 }
72317
72318
72319
72320
72321 public function areOpen()
72322 {
72323 return (bool) $this->pipes;
72324 }
72325
72326
72327
72328
72329
72330
72331
72332
72333
72334 public static function create(Process $process, $input)
72335 {
72336 return new static($process->isTty(), $process->isPty(), $input, $process->isOutputDisabled());
72337 }
72338 }
72339 <?php
72340
72341
72342
72343
72344
72345
72346
72347
72348
72349
72350 namespace Symfony\Component\Process\Pipes;
72351
72352 use Symfony\Component\Process\Process;
72353 use Symfony\Component\Process\Exception\RuntimeException;
72354
72355
72356
72357
72358
72359
72360
72361
72362
72363
72364
72365 class WindowsPipes extends AbstractPipes
72366 {
72367
72368 private $files = array();
72369
72370 private $fileHandles = array();
72371
72372 private $readBytes = array(
72373 Process::STDOUT => 0,
72374 Process::STDERR => 0,
72375 );
72376
72377 private $disableOutput;
72378
72379 public function __construct($disableOutput, $input)
72380 {
72381 $this->disableOutput = (bool) $disableOutput;
72382
72383 if (!$this->disableOutput) {
72384
72385  
72386  
72387  
72388  $pipes = array(
72389 Process::STDOUT => Process::OUT,
72390 Process::STDERR => Process::ERR,
72391 );
72392 $tmpCheck = false;
72393 $tmpDir = sys_get_temp_dir();
72394 $lastError = 'unknown reason';
72395 set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; });
72396 for ($i = 0;; ++$i) {
72397 foreach ($pipes as $pipe => $name) {
72398 $file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name);
72399 if (file_exists($file) && !unlink($file)) {
72400 continue 2;
72401 }
72402 $h = fopen($file, 'xb');
72403 if (!$h) {
72404 $error = $lastError;
72405 if ($tmpCheck || $tmpCheck = unlink(tempnam(false, 'sf_check_'))) {
72406 continue;
72407 }
72408 restore_error_handler();
72409 throw new RuntimeException(sprintf('A temporary file could not be opened to write the process output: %s', $error));
72410 }
72411 if (!$h || !$this->fileHandles[$pipe] = fopen($file, 'rb')) {
72412 continue 2;
72413 }
72414 if (isset($this->files[$pipe])) {
72415 unlink($this->files[$pipe]);
72416 }
72417 $this->files[$pipe] = $file;
72418 }
72419 break;
72420 }
72421 restore_error_handler();
72422 }
72423
72424 parent::__construct($input);
72425 }
72426
72427 public function __destruct()
72428 {
72429 $this->close();
72430 $this->removeFiles();
72431 }
72432
72433
72434
72435
72436 public function getDescriptors()
72437 {
72438 if ($this->disableOutput) {
72439 $nullstream = fopen('NUL', 'c');
72440
72441 return array(
72442 array('pipe', 'r'),
72443 $nullstream,
72444 $nullstream,
72445 );
72446 }
72447
72448
72449  
72450  
72451  return array(
72452 array('pipe', 'r'),
72453 array('file', 'NUL', 'w'),
72454 array('file', 'NUL', 'w'),
72455 );
72456 }
72457
72458
72459
72460
72461 public function getFiles()
72462 {
72463 return $this->files;
72464 }
72465
72466
72467
72468
72469 public function readAndWrite($blocking, $close = false)
72470 {
72471 $this->unblock();
72472 $w = $this->write();
72473 $read = $r = $e = array();
72474
72475 if ($blocking) {
72476 if ($w) {
72477 @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6);
72478 } elseif ($this->fileHandles) {
72479 usleep(Process::TIMEOUT_PRECISION * 1E6);
72480 }
72481 }
72482 foreach ($this->fileHandles as $type => $fileHandle) {
72483 $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]);
72484
72485 if (isset($data[0])) {
72486 $this->readBytes[$type] += strlen($data);
72487 $read[$type] = $data;
72488 }
72489 if ($close) {
72490 fclose($fileHandle);
72491 unset($this->fileHandles[$type]);
72492 }
72493 }
72494
72495 return $read;
72496 }
72497
72498
72499
72500
72501 public function areOpen()
72502 {
72503 return $this->pipes && $this->fileHandles;
72504 }
72505
72506
72507
72508
72509 public function close()
72510 {
72511 parent::close();
72512 foreach ($this->fileHandles as $handle) {
72513 fclose($handle);
72514 }
72515 $this->fileHandles = array();
72516 }
72517
72518
72519
72520
72521
72522
72523
72524
72525
72526 public static function create(Process $process, $input)
72527 {
72528 return new static($process->isOutputDisabled(), $input);
72529 }
72530
72531
72532
72533
72534 private function removeFiles()
72535 {
72536 foreach ($this->files as $filename) {
72537 if (file_exists($filename)) {
72538 @unlink($filename);
72539 }
72540 }
72541 $this->files = array();
72542 }
72543 }
72544 <?php
72545
72546
72547
72548
72549
72550
72551
72552
72553
72554
72555 namespace Symfony\Component\Process;
72556
72557 use Symfony\Component\Process\Exception\InvalidArgumentException;
72558 use Symfony\Component\Process\Exception\LogicException;
72559 use Symfony\Component\Process\Exception\ProcessFailedException;
72560 use Symfony\Component\Process\Exception\ProcessTimedOutException;
72561 use Symfony\Component\Process\Exception\RuntimeException;
72562 use Symfony\Component\Process\Pipes\PipesInterface;
72563 use Symfony\Component\Process\Pipes\UnixPipes;
72564 use Symfony\Component\Process\Pipes\WindowsPipes;
72565
72566
72567
72568
72569
72570
72571
72572
72573 class Process
72574 {
72575 const ERR = 'err';
72576 const OUT = 'out';
72577
72578 const STATUS_READY = 'ready';
72579 const STATUS_STARTED = 'started';
72580 const STATUS_TERMINATED = 'terminated';
72581
72582 const STDIN = 0;
72583 const STDOUT = 1;
72584 const STDERR = 2;
72585
72586
72587  const TIMEOUT_PRECISION = 0.2;
72588
72589 private $callback;
72590 private $commandline;
72591 private $cwd;
72592 private $env;
72593 private $input;
72594 private $starttime;
72595 private $lastOutputTime;
72596 private $timeout;
72597 private $idleTimeout;
72598 private $options;
72599 private $exitcode;
72600 private $fallbackStatus = array();
72601 private $processInformation;
72602 private $outputDisabled = false;
72603 private $stdout;
72604 private $stderr;
72605 private $enhanceWindowsCompatibility = true;
72606 private $enhanceSigchildCompatibility;
72607 private $process;
72608 private $status = self::STATUS_READY;
72609 private $incrementalOutputOffset = 0;
72610 private $incrementalErrorOutputOffset = 0;
72611 private $tty;
72612 private $pty;
72613
72614 private $useFileHandles = false;
72615
72616 private $processPipes;
72617
72618 private $latestSignal;
72619
72620 private static $sigchild;
72621
72622
72623
72624
72625
72626
72627
72628
72629 public static $exitCodes = array(
72630 0 => 'OK',
72631 1 => 'General error',
72632 2 => 'Misuse of shell builtins',
72633
72634 126 => 'Invoked command cannot execute',
72635 127 => 'Command not found',
72636 128 => 'Invalid exit argument',
72637
72638
72639  129 => 'Hangup',
72640 130 => 'Interrupt',
72641 131 => 'Quit and dump core',
72642 132 => 'Illegal instruction',
72643 133 => 'Trace/breakpoint trap',
72644 134 => 'Process aborted',
72645 135 => 'Bus error: "access to undefined portion of memory object"',
72646 136 => 'Floating point exception: "erroneous arithmetic operation"',
72647 137 => 'Kill (terminate immediately)',
72648 138 => 'User-defined 1',
72649 139 => 'Segmentation violation',
72650 140 => 'User-defined 2',
72651 141 => 'Write to pipe with no one reading',
72652 142 => 'Signal raised by alarm',
72653 143 => 'Termination (request to terminate)',
72654
72655  145 => 'Child process terminated, stopped (or continued*)',
72656 146 => 'Continue if stopped',
72657 147 => 'Stop executing temporarily',
72658 148 => 'Terminal stop signal',
72659 149 => 'Background process attempting to read from tty ("in")',
72660 150 => 'Background process attempting to write to tty ("out")',
72661 151 => 'Urgent data available on socket',
72662 152 => 'CPU time limit exceeded',
72663 153 => 'File size limit exceeded',
72664 154 => 'Signal raised by timer counting virtual time: "virtual timer expired"',
72665 155 => 'Profiling timer expired',
72666
72667  157 => 'Pollable event',
72668
72669  159 => 'Bad syscall',
72670 );
72671
72672
72673
72674
72675
72676
72677
72678
72679
72680
72681
72682
72683
72684 public function __construct($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = array())
72685 {
72686 if (!function_exists('proc_open')) {
72687 throw new RuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.');
72688 }
72689
72690 $this->commandline = $commandline;
72691 $this->cwd = $cwd;
72692
72693
72694  
72695  
72696  
72697  if (null === $this->cwd && (defined('ZEND_THREAD_SAFE') || '\\' === DIRECTORY_SEPARATOR)) {
72698 $this->cwd = getcwd();
72699 }
72700 if (null !== $env) {
72701 $this->setEnv($env);
72702 }
72703
72704 $this->setInput($input);
72705 $this->setTimeout($timeout);
72706 $this->useFileHandles = '\\' === DIRECTORY_SEPARATOR;
72707 $this->pty = false;
72708 $this->enhanceSigchildCompatibility = '\\' !== DIRECTORY_SEPARATOR && $this->isSigchildEnabled();
72709 $this->options = array_replace(array('suppress_errors' => true, 'binary_pipes' => true), $options);
72710 }
72711
72712 public function __destruct()
72713 {
72714 $this->stop(0);
72715 }
72716
72717 public function __clone()
72718 {
72719 $this->resetProcessData();
72720 }
72721
72722
72723
72724
72725
72726
72727
72728
72729
72730
72731
72732
72733
72734
72735
72736
72737
72738
72739
72740
72741 public function run($callback = null)
72742 {
72743 $this->start($callback);
72744
72745 return $this->wait();
72746 }
72747
72748
72749
72750
72751
72752
72753
72754
72755
72756
72757
72758
72759
72760
72761 public function mustRun($callback = null)
72762 {
72763 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
72764 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
72765 }
72766
72767 if (0 !== $this->run($callback)) {
72768 throw new ProcessFailedException($this);
72769 }
72770
72771 return $this;
72772 }
72773
72774
72775
72776
72777
72778
72779
72780
72781
72782
72783
72784
72785
72786
72787
72788
72789
72790
72791
72792
72793 public function start($callback = null)
72794 {
72795 if ($this->isRunning()) {
72796 throw new RuntimeException('Process is already running');
72797 }
72798 if ($this->outputDisabled && null !== $callback) {
72799 throw new LogicException('Output has been disabled, enable it to allow the use of a callback.');
72800 }
72801
72802 $this->resetProcessData();
72803 $this->starttime = $this->lastOutputTime = microtime(true);
72804 $this->callback = $this->buildCallback($callback);
72805 $descriptors = $this->getDescriptors();
72806
72807 $commandline = $this->commandline;
72808
72809 if ('\\' === DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) {
72810 $commandline = 'cmd /V:ON /E:ON /D /C "('.$commandline.')';
72811 foreach ($this->processPipes->getFiles() as $offset => $filename) {
72812 $commandline .= ' '.$offset.'>'.ProcessUtils::escapeArgument($filename);
72813 }
72814 $commandline .= '"';
72815
72816 if (!isset($this->options['bypass_shell'])) {
72817 $this->options['bypass_shell'] = true;
72818 }
72819 } elseif (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
72820
72821  $descriptors[3] = array('pipe', 'w');
72822
72823
72824  $commandline = '{ ('.$this->commandline.') <&3 3<&- 3>/dev/null & } 3<&0;';
72825 $commandline .= 'pid=$!; echo $pid >&3; wait $pid; code=$?; echo $code >&3; exit $code';
72826
72827
72828  
72829  $ptsWorkaround = fopen(__FILE__, 'r');
72830 }
72831
72832 $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $this->env, $this->options);
72833
72834 if (!is_resource($this->process)) {
72835 throw new RuntimeException('Unable to launch a new process.');
72836 }
72837 $this->status = self::STATUS_STARTED;
72838
72839 if (isset($descriptors[3])) {
72840 $this->fallbackStatus['pid'] = (int) fgets($this->processPipes->pipes[3]);
72841 }
72842
72843 if ($this->tty) {
72844 return;
72845 }
72846
72847 $this->updateStatus(false);
72848 $this->checkTimeout();
72849 }
72850
72851
72852
72853
72854
72855
72856
72857
72858
72859
72860
72861
72862
72863
72864
72865
72866 public function restart($callback = null)
72867 {
72868 if ($this->isRunning()) {
72869 throw new RuntimeException('Process is already running');
72870 }
72871
72872 $process = clone $this;
72873 $process->start($callback);
72874
72875 return $process;
72876 }
72877
72878
72879
72880
72881
72882
72883
72884
72885
72886
72887
72888
72889
72890
72891
72892
72893 public function wait($callback = null)
72894 {
72895 $this->requireProcessIsStarted(__FUNCTION__);
72896
72897 $this->updateStatus(false);
72898 if (null !== $callback) {
72899 $this->callback = $this->buildCallback($callback);
72900 }
72901
72902 do {
72903 $this->checkTimeout();
72904 $running = '\\' === DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen();
72905 $this->readPipes($running, '\\' !== DIRECTORY_SEPARATOR || !$running);
72906 } while ($running);
72907
72908 while ($this->isRunning()) {
72909 usleep(1000);
72910 }
72911
72912 if ($this->processInformation['signaled'] && $this->processInformation['termsig'] !== $this->latestSignal) {
72913 throw new RuntimeException(sprintf('The process has been signaled with signal "%s".', $this->processInformation['termsig']));
72914 }
72915
72916 return $this->exitcode;
72917 }
72918
72919
72920
72921
72922
72923
72924 public function getPid()
72925 {
72926 return $this->isRunning() ? $this->processInformation['pid'] : null;
72927 }
72928
72929
72930
72931
72932
72933
72934
72935
72936
72937
72938
72939
72940 public function signal($signal)
72941 {
72942 $this->doSignal($signal, true);
72943
72944 return $this;
72945 }
72946
72947
72948
72949
72950
72951
72952
72953
72954
72955 public function disableOutput()
72956 {
72957 if ($this->isRunning()) {
72958 throw new RuntimeException('Disabling output while the process is running is not possible.');
72959 }
72960 if (null !== $this->idleTimeout) {
72961 throw new LogicException('Output can not be disabled while an idle timeout is set.');
72962 }
72963
72964 $this->outputDisabled = true;
72965
72966 return $this;
72967 }
72968
72969
72970
72971
72972
72973
72974
72975
72976 public function enableOutput()
72977 {
72978 if ($this->isRunning()) {
72979 throw new RuntimeException('Enabling output while the process is running is not possible.');
72980 }
72981
72982 $this->outputDisabled = false;
72983
72984 return $this;
72985 }
72986
72987
72988
72989
72990
72991
72992 public function isOutputDisabled()
72993 {
72994 return $this->outputDisabled;
72995 }
72996
72997
72998
72999
73000
73001
73002
73003
73004
73005 public function getOutput()
73006 {
73007 $this->readPipesForOutput(__FUNCTION__);
73008
73009 if (false === $ret = stream_get_contents($this->stdout, -1, 0)) {
73010 return '';
73011 }
73012
73013 return $ret;
73014 }
73015
73016
73017
73018
73019
73020
73021
73022
73023
73024
73025
73026
73027 public function getIncrementalOutput()
73028 {
73029 $this->readPipesForOutput(__FUNCTION__);
73030
73031 $latest = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);
73032 $this->incrementalOutputOffset = ftell($this->stdout);
73033
73034 if (false === $latest) {
73035 return '';
73036 }
73037
73038 return $latest;
73039 }
73040
73041
73042
73043
73044
73045
73046 public function clearOutput()
73047 {
73048 ftruncate($this->stdout, 0);
73049 fseek($this->stdout, 0);
73050 $this->incrementalOutputOffset = 0;
73051
73052 return $this;
73053 }
73054
73055
73056
73057
73058
73059
73060
73061
73062
73063 public function getErrorOutput()
73064 {
73065 $this->readPipesForOutput(__FUNCTION__);
73066
73067 if (false === $ret = stream_get_contents($this->stderr, -1, 0)) {
73068 return '';
73069 }
73070
73071 return $ret;
73072 }
73073
73074
73075
73076
73077
73078
73079
73080
73081
73082
73083
73084
73085
73086 public function getIncrementalErrorOutput()
73087 {
73088 $this->readPipesForOutput(__FUNCTION__);
73089
73090 $latest = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);
73091 $this->incrementalErrorOutputOffset = ftell($this->stderr);
73092
73093 if (false === $latest) {
73094 return '';
73095 }
73096
73097 return $latest;
73098 }
73099
73100
73101
73102
73103
73104
73105 public function clearErrorOutput()
73106 {
73107 ftruncate($this->stderr, 0);
73108 fseek($this->stderr, 0);
73109 $this->incrementalErrorOutputOffset = 0;
73110
73111 return $this;
73112 }
73113
73114
73115
73116
73117
73118
73119
73120
73121 public function getExitCode()
73122 {
73123 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
73124 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
73125 }
73126
73127 $this->updateStatus(false);
73128
73129 return $this->exitcode;
73130 }
73131
73132
73133
73134
73135
73136
73137
73138
73139
73140
73141
73142
73143 public function getExitCodeText()
73144 {
73145 if (null === $exitcode = $this->getExitCode()) {
73146 return;
73147 }
73148
73149 return isset(self::$exitCodes[$exitcode]) ? self::$exitCodes[$exitcode] : 'Unknown error';
73150 }
73151
73152
73153
73154
73155
73156
73157 public function isSuccessful()
73158 {
73159 return 0 === $this->getExitCode();
73160 }
73161
73162
73163
73164
73165
73166
73167
73168
73169
73170
73171
73172 public function hasBeenSignaled()
73173 {
73174 $this->requireProcessIsTerminated(__FUNCTION__);
73175
73176 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
73177 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
73178 }
73179
73180 return $this->processInformation['signaled'];
73181 }
73182
73183
73184
73185
73186
73187
73188
73189
73190
73191
73192
73193 public function getTermSignal()
73194 {
73195 $this->requireProcessIsTerminated(__FUNCTION__);
73196
73197 if ($this->isSigchildEnabled() && (!$this->enhanceSigchildCompatibility || -1 === $this->processInformation['termsig'])) {
73198 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
73199 }
73200
73201 return $this->processInformation['termsig'];
73202 }
73203
73204
73205
73206
73207
73208
73209
73210
73211
73212
73213 public function hasBeenStopped()
73214 {
73215 $this->requireProcessIsTerminated(__FUNCTION__);
73216
73217 return $this->processInformation['stopped'];
73218 }
73219
73220
73221
73222
73223
73224
73225
73226
73227
73228
73229 public function getStopSignal()
73230 {
73231 $this->requireProcessIsTerminated(__FUNCTION__);
73232
73233 return $this->processInformation['stopsig'];
73234 }
73235
73236
73237
73238
73239
73240
73241 public function isRunning()
73242 {
73243 if (self::STATUS_STARTED !== $this->status) {
73244 return false;
73245 }
73246
73247 $this->updateStatus(false);
73248
73249 return $this->processInformation['running'];
73250 }
73251
73252
73253
73254
73255
73256
73257 public function isStarted()
73258 {
73259 return $this->status != self::STATUS_READY;
73260 }
73261
73262
73263
73264
73265
73266
73267 public function isTerminated()
73268 {
73269 $this->updateStatus(false);
73270
73271 return $this->status == self::STATUS_TERMINATED;
73272 }
73273
73274
73275
73276
73277
73278
73279
73280
73281 public function getStatus()
73282 {
73283 $this->updateStatus(false);
73284
73285 return $this->status;
73286 }
73287
73288
73289
73290
73291
73292
73293
73294
73295
73296 public function stop($timeout = 10, $signal = null)
73297 {
73298 $timeoutMicro = microtime(true) + $timeout;
73299 if ($this->isRunning()) {
73300
73301  $this->doSignal(15, false);
73302 do {
73303 usleep(1000);
73304 } while ($this->isRunning() && microtime(true) < $timeoutMicro);
73305
73306 if ($this->isRunning()) {
73307
73308  
73309  $this->doSignal($signal ?: 9, false);
73310 }
73311 }
73312
73313 if ($this->isRunning()) {
73314 if (isset($this->fallbackStatus['pid'])) {
73315 unset($this->fallbackStatus['pid']);
73316
73317 return $this->stop(0, $signal);
73318 }
73319 $this->close();
73320 }
73321
73322 return $this->exitcode;
73323 }
73324
73325
73326
73327
73328
73329
73330
73331
73332 public function addOutput($line)
73333 {
73334 $this->lastOutputTime = microtime(true);
73335
73336 fseek($this->stdout, 0, SEEK_END);
73337 fwrite($this->stdout, $line);
73338 fseek($this->stdout, $this->incrementalOutputOffset);
73339 }
73340
73341
73342
73343
73344
73345
73346
73347
73348 public function addErrorOutput($line)
73349 {
73350 $this->lastOutputTime = microtime(true);
73351
73352 fseek($this->stderr, 0, SEEK_END);
73353 fwrite($this->stderr, $line);
73354 fseek($this->stderr, $this->incrementalErrorOutputOffset);
73355 }
73356
73357
73358
73359
73360
73361
73362 public function getCommandLine()
73363 {
73364 return $this->commandline;
73365 }
73366
73367
73368
73369
73370
73371
73372
73373
73374 public function setCommandLine($commandline)
73375 {
73376 $this->commandline = $commandline;
73377
73378 return $this;
73379 }
73380
73381
73382
73383
73384
73385
73386 public function getTimeout()
73387 {
73388 return $this->timeout;
73389 }
73390
73391
73392
73393
73394
73395
73396 public function getIdleTimeout()
73397 {
73398 return $this->idleTimeout;
73399 }
73400
73401
73402
73403
73404
73405
73406
73407
73408
73409
73410
73411
73412 public function setTimeout($timeout)
73413 {
73414 $this->timeout = $this->validateTimeout($timeout);
73415
73416 return $this;
73417 }
73418
73419
73420
73421
73422
73423
73424
73425
73426
73427
73428
73429
73430
73431 public function setIdleTimeout($timeout)
73432 {
73433 if (null !== $timeout && $this->outputDisabled) {
73434 throw new LogicException('Idle timeout can not be set while the output is disabled.');
73435 }
73436
73437 $this->idleTimeout = $this->validateTimeout($timeout);
73438
73439 return $this;
73440 }
73441
73442
73443
73444
73445
73446
73447
73448
73449
73450
73451 public function setTty($tty)
73452 {
73453 if ('\\' === DIRECTORY_SEPARATOR && $tty) {
73454 throw new RuntimeException('TTY mode is not supported on Windows platform.');
73455 }
73456 if ($tty) {
73457 static $isTtySupported;
73458
73459 if (null === $isTtySupported) {
73460 $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);
73461 }
73462
73463 if (!$isTtySupported) {
73464 throw new RuntimeException('TTY mode requires /dev/tty to be read/writable.');
73465 }
73466 }
73467
73468 $this->tty = (bool) $tty;
73469
73470 return $this;
73471 }
73472
73473
73474
73475
73476
73477
73478 public function isTty()
73479 {
73480 return $this->tty;
73481 }
73482
73483
73484
73485
73486
73487
73488
73489
73490 public function setPty($bool)
73491 {
73492 $this->pty = (bool) $bool;
73493
73494 return $this;
73495 }
73496
73497
73498
73499
73500
73501
73502 public function isPty()
73503 {
73504 return $this->pty;
73505 }
73506
73507
73508
73509
73510
73511
73512 public function getWorkingDirectory()
73513 {
73514 if (null === $this->cwd) {
73515
73516  
73517  return getcwd() ?: null;
73518 }
73519
73520 return $this->cwd;
73521 }
73522
73523
73524
73525
73526
73527
73528
73529
73530 public function setWorkingDirectory($cwd)
73531 {
73532 $this->cwd = $cwd;
73533
73534 return $this;
73535 }
73536
73537
73538
73539
73540
73541
73542 public function getEnv()
73543 {
73544 return $this->env;
73545 }
73546
73547
73548
73549
73550
73551
73552
73553
73554
73555
73556
73557
73558
73559
73560 public function setEnv(array $env)
73561 {
73562
73563  $env = array_filter($env, function ($value) {
73564 return !is_array($value);
73565 });
73566
73567 $this->env = array();
73568 foreach ($env as $key => $value) {
73569 $this->env[$key] = (string) $value;
73570 }
73571
73572 return $this;
73573 }
73574
73575
73576
73577
73578
73579
73580
73581
73582
73583
73584 public function getStdin()
73585 {
73586 @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);
73587
73588 return $this->getInput();
73589 }
73590
73591
73592
73593
73594
73595
73596 public function getInput()
73597 {
73598 return $this->input;
73599 }
73600
73601
73602
73603
73604
73605
73606
73607
73608
73609
73610
73611
73612
73613
73614 public function setStdin($stdin)
73615 {
73616 @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);
73617
73618 return $this->setInput($stdin);
73619 }
73620
73621
73622
73623
73624
73625
73626
73627
73628
73629
73630
73631
73632
73633
73634 public function setInput($input)
73635 {
73636 if ($this->isRunning()) {
73637 throw new LogicException('Input can not be set while the process is running.');
73638 }
73639
73640 $this->input = ProcessUtils::validateInput(__METHOD__, $input);
73641
73642 return $this;
73643 }
73644
73645
73646
73647
73648
73649
73650 public function getOptions()
73651 {
73652 return $this->options;
73653 }
73654
73655
73656
73657
73658
73659
73660
73661
73662 public function setOptions(array $options)
73663 {
73664 $this->options = $options;
73665
73666 return $this;
73667 }
73668
73669
73670
73671
73672
73673
73674
73675
73676 public function getEnhanceWindowsCompatibility()
73677 {
73678 return $this->enhanceWindowsCompatibility;
73679 }
73680
73681
73682
73683
73684
73685
73686
73687
73688 public function setEnhanceWindowsCompatibility($enhance)
73689 {
73690 $this->enhanceWindowsCompatibility = (bool) $enhance;
73691
73692 return $this;
73693 }
73694
73695
73696
73697
73698
73699
73700 public function getEnhanceSigchildCompatibility()
73701 {
73702 return $this->enhanceSigchildCompatibility;
73703 }
73704
73705
73706
73707
73708
73709
73710
73711
73712
73713
73714
73715
73716 public function setEnhanceSigchildCompatibility($enhance)
73717 {
73718 $this->enhanceSigchildCompatibility = (bool) $enhance;
73719
73720 return $this;
73721 }
73722
73723
73724
73725
73726
73727
73728
73729
73730
73731 public function checkTimeout()
73732 {
73733 if ($this->status !== self::STATUS_STARTED) {
73734 return;
73735 }
73736
73737 if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) {
73738 $this->stop(0);
73739
73740 throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL);
73741 }
73742
73743 if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) {
73744 $this->stop(0);
73745
73746 throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE);
73747 }
73748 }
73749
73750
73751
73752
73753
73754
73755 public static function isPtySupported()
73756 {
73757 static $result;
73758
73759 if (null !== $result) {
73760 return $result;
73761 }
73762
73763 if ('\\' === DIRECTORY_SEPARATOR) {
73764 return $result = false;
73765 }
73766
73767 return $result = (bool) @proc_open('echo 1 >/dev/null', array(array('pty'), array('pty'), array('pty')), $pipes);
73768 }
73769
73770
73771
73772
73773
73774
73775 private function getDescriptors()
73776 {
73777 if ('\\' === DIRECTORY_SEPARATOR) {
73778 $this->processPipes = WindowsPipes::create($this, $this->input);
73779 } else {
73780 $this->processPipes = UnixPipes::create($this, $this->input);
73781 }
73782
73783 return $this->processPipes->getDescriptors();
73784 }
73785
73786
73787
73788
73789
73790
73791
73792
73793
73794
73795
73796 protected function buildCallback($callback)
73797 {
73798 $that = $this;
73799 $out = self::OUT;
73800 $callback = function ($type, $data) use ($that, $callback, $out) {
73801 if ($out == $type) {
73802 $that->addOutput($data);
73803 } else {
73804 $that->addErrorOutput($data);
73805 }
73806
73807 if (null !== $callback) {
73808 call_user_func($callback, $type, $data);
73809 }
73810 };
73811
73812 return $callback;
73813 }
73814
73815
73816
73817
73818
73819
73820 protected function updateStatus($blocking)
73821 {
73822 if (self::STATUS_STARTED !== $this->status) {
73823 return;
73824 }
73825
73826 $this->processInformation = proc_get_status($this->process);
73827 $running = $this->processInformation['running'];
73828
73829 $this->readPipes($running && $blocking, '\\' !== DIRECTORY_SEPARATOR || !$running);
73830
73831 if ($this->fallbackStatus && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
73832 $this->processInformation = $this->fallbackStatus + $this->processInformation;
73833 }
73834
73835 if (!$running) {
73836 $this->close();
73837 }
73838 }
73839
73840
73841
73842
73843
73844
73845 protected function isSigchildEnabled()
73846 {
73847 if (null !== self::$sigchild) {
73848 return self::$sigchild;
73849 }
73850
73851 if (!function_exists('phpinfo') || defined('HHVM_VERSION')) {
73852 return self::$sigchild = false;
73853 }
73854
73855 ob_start();
73856 phpinfo(INFO_GENERAL);
73857
73858 return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');
73859 }
73860
73861
73862
73863
73864
73865
73866
73867
73868 private function readPipesForOutput($caller)
73869 {
73870 if ($this->outputDisabled) {
73871 throw new LogicException('Output has been disabled.');
73872 }
73873
73874 $this->requireProcessIsStarted($caller);
73875
73876 $this->updateStatus(false);
73877 }
73878
73879
73880
73881
73882
73883
73884
73885
73886
73887
73888 private function validateTimeout($timeout)
73889 {
73890 $timeout = (float) $timeout;
73891
73892 if (0.0 === $timeout) {
73893 $timeout = null;
73894 } elseif ($timeout < 0) {
73895 throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
73896 }
73897
73898 return $timeout;
73899 }
73900
73901
73902
73903
73904
73905
73906
73907 private function readPipes($blocking, $close)
73908 {
73909 $result = $this->processPipes->readAndWrite($blocking, $close);
73910
73911 $callback = $this->callback;
73912 foreach ($result as $type => $data) {
73913 if (3 !== $type) {
73914 $callback($type === self::STDOUT ? self::OUT : self::ERR, $data);
73915 } elseif (!isset($this->fallbackStatus['signaled'])) {
73916 $this->fallbackStatus['exitcode'] = (int) $data;
73917 }
73918 }
73919 }
73920
73921
73922
73923
73924
73925
73926 private function close()
73927 {
73928 $this->processPipes->close();
73929 if (is_resource($this->process)) {
73930 proc_close($this->process);
73931 }
73932 $this->exitcode = $this->processInformation['exitcode'];
73933 $this->status = self::STATUS_TERMINATED;
73934
73935 if (-1 === $this->exitcode) {
73936 if ($this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) {
73937
73938  $this->exitcode = 128 + $this->processInformation['termsig'];
73939 } elseif ($this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
73940 $this->processInformation['signaled'] = true;
73941 $this->processInformation['termsig'] = -1;
73942 }
73943 }
73944
73945
73946  
73947  
73948  $this->callback = null;
73949
73950 return $this->exitcode;
73951 }
73952
73953
73954
73955
73956 private function resetProcessData()
73957 {
73958 $this->starttime = null;
73959 $this->callback = null;
73960 $this->exitcode = null;
73961 $this->fallbackStatus = array();
73962 $this->processInformation = null;
73963 $this->stdout = fopen('php://temp/maxmemory:'.(1024 * 1024), 'wb+');
73964 $this->stderr = fopen('php://temp/maxmemory:'.(1024 * 1024), 'wb+');
73965 $this->process = null;
73966 $this->latestSignal = null;
73967 $this->status = self::STATUS_READY;
73968 $this->incrementalOutputOffset = 0;
73969 $this->incrementalErrorOutputOffset = 0;
73970 }
73971
73972
73973
73974
73975
73976
73977
73978
73979
73980
73981
73982
73983
73984 private function doSignal($signal, $throwException)
73985 {
73986 if (null === $pid = $this->getPid()) {
73987 if ($throwException) {
73988 throw new LogicException('Can not send signal on a non running process.');
73989 }
73990
73991 return false;
73992 }
73993
73994 if ('\\' === DIRECTORY_SEPARATOR) {
73995 exec(sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode);
73996 if ($exitCode && $this->isRunning()) {
73997 if ($throwException) {
73998 throw new RuntimeException(sprintf('Unable to kill the process (%s).', implode(' ', $output)));
73999 }
74000
74001 return false;
74002 }
74003 } else {
74004 if (!$this->enhanceSigchildCompatibility || !$this->isSigchildEnabled()) {
74005 $ok = @proc_terminate($this->process, $signal);
74006 } elseif (function_exists('posix_kill')) {
74007 $ok = @posix_kill($pid, $signal);
74008 } elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $pid), array(2 => array('pipe', 'w')), $pipes)) {
74009 $ok = false === fgets($pipes[2]);
74010 }
74011 if (!$ok) {
74012 if ($throwException) {
74013 throw new RuntimeException(sprintf('Error while sending signal `%s`.', $signal));
74014 }
74015
74016 return false;
74017 }
74018 }
74019
74020 $this->latestSignal = (int) $signal;
74021 $this->fallbackStatus['signaled'] = true;
74022 $this->fallbackStatus['exitcode'] = -1;
74023 $this->fallbackStatus['termsig'] = $this->latestSignal;
74024
74025 return true;
74026 }
74027
74028
74029
74030
74031
74032
74033
74034
74035 private function requireProcessIsStarted($functionName)
74036 {
74037 if (!$this->isStarted()) {
74038 throw new LogicException(sprintf('Process must be started before calling %s.', $functionName));
74039 }
74040 }
74041
74042
74043
74044
74045
74046
74047
74048
74049 private function requireProcessIsTerminated($functionName)
74050 {
74051 if (!$this->isTerminated()) {
74052 throw new LogicException(sprintf('Process must be terminated before calling %s.', $functionName));
74053 }
74054 }
74055 }
74056 <?php
74057
74058
74059
74060
74061
74062
74063
74064
74065
74066
74067 namespace Symfony\Component\Process;
74068
74069 use Symfony\Component\Process\Exception\InvalidArgumentException;
74070 use Symfony\Component\Process\Exception\LogicException;
74071
74072
74073
74074
74075
74076
74077 class ProcessBuilder
74078 {
74079 private $arguments;
74080 private $cwd;
74081 private $env = array();
74082 private $input;
74083 private $timeout = 60;
74084 private $options = array();
74085 private $inheritEnv = true;
74086 private $prefix = array();
74087 private $outputDisabled = false;
74088
74089
74090
74091
74092
74093
74094 public function __construct(array $arguments = array())
74095 {
74096 $this->arguments = $arguments;
74097 }
74098
74099
74100
74101
74102
74103
74104
74105
74106 public static function create(array $arguments = array())
74107 {
74108 return new static($arguments);
74109 }
74110
74111
74112
74113
74114
74115
74116
74117
74118 public function add($argument)
74119 {
74120 $this->arguments[] = $argument;
74121
74122 return $this;
74123 }
74124
74125
74126
74127
74128
74129
74130
74131
74132
74133
74134 public function setPrefix($prefix)
74135 {
74136 $this->prefix = is_array($prefix) ? $prefix : array($prefix);
74137
74138 return $this;
74139 }
74140
74141
74142
74143
74144
74145
74146
74147
74148
74149
74150
74151 public function setArguments(array $arguments)
74152 {
74153 $this->arguments = $arguments;
74154
74155 return $this;
74156 }
74157
74158
74159
74160
74161
74162
74163
74164
74165 public function setWorkingDirectory($cwd)
74166 {
74167 $this->cwd = $cwd;
74168
74169 return $this;
74170 }
74171
74172
74173
74174
74175
74176
74177
74178
74179 public function inheritEnvironmentVariables($inheritEnv = true)
74180 {
74181 $this->inheritEnv = $inheritEnv;
74182
74183 return $this;
74184 }
74185
74186
74187
74188
74189
74190
74191
74192
74193
74194
74195
74196
74197 public function setEnv($name, $value)
74198 {
74199 $this->env[$name] = $value;
74200
74201 return $this;
74202 }
74203
74204
74205
74206
74207
74208
74209
74210
74211
74212
74213
74214
74215 public function addEnvironmentVariables(array $variables)
74216 {
74217 $this->env = array_replace($this->env, $variables);
74218
74219 return $this;
74220 }
74221
74222
74223
74224
74225
74226
74227
74228
74229
74230
74231
74232
74233 public function setInput($input)
74234 {
74235 $this->input = ProcessUtils::validateInput(__METHOD__, $input);
74236
74237 return $this;
74238 }
74239
74240
74241
74242
74243
74244
74245
74246
74247
74248
74249
74250
74251 public function setTimeout($timeout)
74252 {
74253 if (null === $timeout) {
74254 $this->timeout = null;
74255
74256 return $this;
74257 }
74258
74259 $timeout = (float) $timeout;
74260
74261 if ($timeout < 0) {
74262 throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
74263 }
74264
74265 $this->timeout = $timeout;
74266
74267 return $this;
74268 }
74269
74270
74271
74272
74273
74274
74275
74276
74277
74278 public function setOption($name, $value)
74279 {
74280 $this->options[$name] = $value;
74281
74282 return $this;
74283 }
74284
74285
74286
74287
74288
74289
74290 public function disableOutput()
74291 {
74292 $this->outputDisabled = true;
74293
74294 return $this;
74295 }
74296
74297
74298
74299
74300
74301
74302 public function enableOutput()
74303 {
74304 $this->outputDisabled = false;
74305
74306 return $this;
74307 }
74308
74309
74310
74311
74312
74313
74314
74315
74316 public function getProcess()
74317 {
74318 if (0 === count($this->prefix) && 0 === count($this->arguments)) {
74319 throw new LogicException('You must add() command arguments before calling getProcess().');
74320 }
74321
74322 $options = $this->options;
74323
74324 $arguments = array_merge($this->prefix, $this->arguments);
74325 $script = implode(' ', array_map(array(__NAMESPACE__.'\\ProcessUtils', 'escapeArgument'), $arguments));
74326
74327 if ($this->inheritEnv) {
74328
74329  $env = array_replace($_ENV, $_SERVER, $this->env);
74330 } else {
74331 $env = $this->env;
74332 }
74333
74334 $process = new Process($script, $this->cwd, $env, $this->input, $this->timeout, $options);
74335
74336 if ($this->outputDisabled) {
74337 $process->disableOutput();
74338 }
74339
74340 return $process;
74341 }
74342 }
74343 <?php
74344
74345
74346
74347
74348
74349
74350
74351
74352
74353
74354 namespace Symfony\Component\Process;
74355
74356 use Symfony\Component\Process\Exception\InvalidArgumentException;
74357
74358
74359
74360
74361
74362
74363
74364
74365 class ProcessUtils
74366 {
74367
74368
74369
74370 private function __construct()
74371 {
74372 }
74373
74374
74375
74376
74377
74378
74379
74380
74381 public static function escapeArgument($argument)
74382 {
74383
74384  
74385  
74386  
74387  if ('\\' === DIRECTORY_SEPARATOR) {
74388 if ('' === $argument) {
74389 return escapeshellarg($argument);
74390 }
74391
74392 $escapedArgument = '';
74393 $quote = false;
74394 foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
74395 if ('"' === $part) {
74396 $escapedArgument .= '\\"';
74397 } elseif (self::isSurroundedBy($part, '%')) {
74398
74399  $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
74400 } else {
74401
74402  if ('\\' === substr($part, -1)) {
74403 $part .= '\\';
74404 }
74405 $quote = true;
74406 $escapedArgument .= $part;
74407 }
74408 }
74409 if ($quote) {
74410 $escapedArgument = '"'.$escapedArgument.'"';
74411 }
74412
74413 return $escapedArgument;
74414 }
74415
74416 return "'".str_replace("'", "'\\''", $argument)."'";
74417 }
74418
74419
74420
74421
74422
74423
74424
74425
74426
74427
74428
74429
74430
74431 public static function validateInput($caller, $input)
74432 {
74433 if (null !== $input) {
74434 if (is_resource($input)) {
74435 return $input;
74436 }
74437 if (is_string($input)) {
74438 return $input;
74439 }
74440 if (is_scalar($input)) {
74441 return (string) $input;
74442 }
74443
74444  if (is_object($input) && method_exists($input, '__toString')) {
74445 @trigger_error('Passing an object as an input is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
74446
74447 return (string) $input;
74448 }
74449
74450 throw new InvalidArgumentException(sprintf('%s only accepts strings or stream resources.', $caller));
74451 }
74452
74453 return $input;
74454 }
74455
74456 private static function isSurroundedBy($arg, $char)
74457 {
74458 return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1];
74459 }
74460 }
74461 Copyright (c) 2011 Jordi Boggiano
74462
74463 Permission is hereby granted, free of charge, to any person obtaining a copy
74464 of this software and associated documentation files (the "Software"), to deal
74465 in the Software without restriction, including without limitation the rights
74466 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
74467 copies of the Software, and to permit persons to whom the Software is furnished
74468 to do so, subject to the following conditions:
74469
74470 The above copyright notice and this permission notice shall be included in all
74471 copies or substantial portions of the Software.
74472
74473 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
74474 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
74475 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
74476 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
74477 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
74478 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
74479 THE SOFTWARE.
74480 <?php
74481
74482
74483
74484
74485
74486
74487
74488
74489
74490
74491 namespace Seld\JsonLint;
74492
74493 class DuplicateKeyException extends ParsingException
74494 {
74495 public function __construct($message, $key, array $details = array())
74496 {
74497 $details['key'] = $key;
74498 parent::__construct($message, $details);
74499 }
74500
74501 public function getKey()
74502 {
74503 return $this->details['key'];
74504 }
74505 }
74506 <?php
74507
74508
74509
74510
74511
74512
74513
74514
74515
74516
74517 namespace Seld\JsonLint;
74518 use stdClass;
74519
74520
74521
74522
74523
74524
74525
74526
74527
74528
74529
74530
74531
74532
74533 class JsonParser
74534 {
74535 const DETECT_KEY_CONFLICTS = 1;
74536 const ALLOW_DUPLICATE_KEYS = 2;
74537 const PARSE_TO_ASSOC = 4;
74538
74539 private $lexer;
74540
74541 private $flags;
74542 private $stack;
74543 private $vstack; 
74544  private $lstack; 
74545
74546 private $symbols = array(
74547 'error' => 2,
74548 'JSONString' => 3,
74549 'STRING' => 4,
74550 'JSONNumber' => 5,
74551 'NUMBER' => 6,
74552 'JSONNullLiteral' => 7,
74553 'NULL' => 8,
74554 'JSONBooleanLiteral' => 9,
74555 'TRUE' => 10,
74556 'FALSE' => 11,
74557 'JSONText' => 12,
74558 'JSONValue' => 13,
74559 'EOF' => 14,
74560 'JSONObject' => 15,
74561 'JSONArray' => 16,
74562 '{' => 17,
74563 '}' => 18,
74564 'JSONMemberList' => 19,
74565 'JSONMember' => 20,
74566 ':' => 21,
74567 ',' => 22,
74568 '[' => 23,
74569 ']' => 24,
74570 'JSONElementList' => 25,
74571 '$accept' => 0,
74572 '$end' => 1,
74573 );
74574
74575 private $terminals_ = array(
74576 2 => "error",
74577 4 => "STRING",
74578 6 => "NUMBER",
74579 8 => "NULL",
74580 10 => "TRUE",
74581 11 => "FALSE",
74582 14 => "EOF",
74583 17 => "{",
74584 18 => "}",
74585 21 => ":",
74586 22 => ",",
74587 23 => "[",
74588 24 => "]",
74589 );
74590
74591 private $productions_ = array(
74592 0,
74593 array(3, 1),
74594 array(5, 1),
74595 array(7, 1),
74596 array(9, 1),
74597 array(9, 1),
74598 array(12, 2),
74599 array(13, 1),
74600 array(13, 1),
74601 array(13, 1),
74602 array(13, 1),
74603 array(13, 1),
74604 array(13, 1),
74605 array(15, 2),
74606 array(15, 3),
74607 array(20, 3),
74608 array(19, 1),
74609 array(19, 3),
74610 array(16, 2),
74611 array(16, 3),
74612 array(25, 1),
74613 array(25, 3)
74614 );
74615
74616 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)),
74617 );
74618
74619 private $defaultActions = array(
74620 16 => array(2, 6)
74621 );
74622
74623
74624
74625
74626
74627
74628 public function lint($input, $flags = 0)
74629 {
74630 try {
74631 $this->parse($input, $flags);
74632 } catch (ParsingException $e) {
74633 return $e;
74634 }
74635 }
74636
74637
74638
74639
74640
74641
74642
74643 public function parse($input, $flags = 0)
74644 {
74645 $this->failOnBOM($input);
74646
74647 $this->flags = $flags;
74648
74649 $this->stack = array(0);
74650 $this->vstack = array(null);
74651 $this->lstack = array();
74652
74653 $yytext = '';
74654 $yylineno = 0;
74655 $yyleng = 0;
74656 $recovering = 0;
74657 $TERROR = 2;
74658 $EOF = 1;
74659
74660 $this->lexer = new Lexer();
74661 $this->lexer->setInput($input);
74662
74663 $yyloc = $this->lexer->yylloc;
74664 $this->lstack[] = $yyloc;
74665
74666 $symbol = null;
74667 $preErrorSymbol = null;
74668 $state = null;
74669 $action = null;
74670 $a = null;
74671 $r = null;
74672 $yyval = new stdClass;
74673 $p = null;
74674 $len = null;
74675 $newState = null;
74676 $expected = null;
74677 $errStr = null;
74678
74679 while (true) {
74680
74681  $state = $this->stack[count($this->stack)-1];
74682
74683
74684  if (isset($this->defaultActions[$state])) {
74685 $action = $this->defaultActions[$state];
74686 } else {
74687 if ($symbol == null) {
74688 $symbol = $this->lex();
74689 }
74690
74691  $action = isset($this->table[$state][$symbol]) ? $this->table[$state][$symbol] : false;
74692 }
74693
74694
74695  if (!$action || !$action[0]) {
74696 if (!$recovering) {
74697
74698  $expected = array();
74699 foreach ($this->table[$state] as $p => $ignore) {
74700 if (isset($this->terminals_[$p]) && $p > 2) {
74701 $expected[] = "'" . $this->terminals_[$p] . "'";
74702 }
74703 }
74704
74705 $message = null;
74706 if (in_array("'STRING'", $expected) && in_array(substr($this->lexer->match, 0, 1), array('"', "'"))) {
74707 $message = "Invalid string";
74708 if ("'" === substr($this->lexer->match, 0, 1)) {
74709 $message .= ", it appears you used single quotes instead of double quotes";
74710 } elseif (preg_match('{".+?(\\\\[^"bfnrt/\\\\u])}', $this->lexer->getUpcomingInput(), $match)) {
74711 $message .= ", it appears you have an unescaped backslash at: ".$match[1];
74712 } elseif (preg_match('{"(?:[^"]+|\\\\")*$}m', $this->lexer->getUpcomingInput())) {
74713 $message .= ", it appears you forgot to terminate a string, or attempted to write a multiline string which is invalid";
74714 }
74715 }
74716
74717 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
74718 $errStr .= $this->lexer->showPosition() . "\n";
74719 if ($message) {
74720 $errStr .= $message;
74721 } else {
74722 $errStr .= (count($expected) > 1) ? "Expected one of: " : "Expected: ";
74723 $errStr .= implode(', ', $expected);
74724 }
74725
74726 if (',' === substr(trim($this->lexer->getPastInput()), -1)) {
74727 $errStr .= " - It appears you have an extra trailing comma";
74728 }
74729
74730 $this->parseError($errStr, array(
74731 'text' => $this->lexer->match,
74732 'token' => !empty($this->terminals_[$symbol]) ? $this->terminals_[$symbol] : $symbol,
74733 'line' => $this->lexer->yylineno,
74734 'loc' => $yyloc,
74735 'expected' => $expected,
74736 ));
74737 }
74738
74739
74740  if ($recovering == 3) {
74741 if ($symbol == $EOF) {
74742 throw new ParsingException($errStr ?: 'Parsing halted.');
74743 }
74744
74745
74746  $yyleng = $this->lexer->yyleng;
74747 $yytext = $this->lexer->yytext;
74748 $yylineno = $this->lexer->yylineno;
74749 $yyloc = $this->lexer->yylloc;
74750 $symbol = $this->lex();
74751 }
74752
74753
74754  while (true) {
74755
74756  if (array_key_exists($TERROR, $this->table[$state])) {
74757 break;
74758 }
74759 if ($state == 0) {
74760 throw new ParsingException($errStr ?: 'Parsing halted.');
74761 }
74762 $this->popStack(1);
74763 $state = $this->stack[count($this->stack)-1];
74764 }
74765
74766 $preErrorSymbol = $symbol; 
74767  $symbol = $TERROR; 
74768  $state = $this->stack[count($this->stack)-1];
74769 $action = isset($this->table[$state][$TERROR]) ? $this->table[$state][$TERROR] : false;
74770 $recovering = 3; 
74771  }
74772
74773
74774  if (is_array($action[0]) && count($action) > 1) {
74775 throw new ParsingException('Parse Error: multiple actions possible at state: ' . $state . ', token: ' . $symbol);
74776 }
74777
74778 switch ($action[0]) {
74779 case 1: 
74780  $this->stack[] = $symbol;
74781 $this->vstack[] = $this->lexer->yytext;
74782 $this->lstack[] = $this->lexer->yylloc;
74783 $this->stack[] = $action[1]; 
74784  $symbol = null;
74785 if (!$preErrorSymbol) { 
74786  $yyleng = $this->lexer->yyleng;
74787 $yytext = $this->lexer->yytext;
74788 $yylineno = $this->lexer->yylineno;
74789 $yyloc = $this->lexer->yylloc;
74790 if ($recovering > 0) {
74791 $recovering--;
74792 }
74793 } else { 
74794  $symbol = $preErrorSymbol;
74795 $preErrorSymbol = null;
74796 }
74797 break;
74798
74799 case 2: 
74800  $len = $this->productions_[$action[1]][1];
74801
74802
74803  $yyval->token = $this->vstack[count($this->vstack) - $len]; 
74804  
74805  $yyval->store = array( 
74806  'first_line' => $this->lstack[count($this->lstack) - ($len ?: 1)]['first_line'],
74807 'last_line' => $this->lstack[count($this->lstack) - 1]['last_line'],
74808 'first_column' => $this->lstack[count($this->lstack) - ($len ?: 1)]['first_column'],
74809 'last_column' => $this->lstack[count($this->lstack) - 1]['last_column'],
74810 );
74811 $r = $this->performAction($yyval, $yytext, $yyleng, $yylineno, $action[1], $this->vstack, $this->lstack);
74812
74813 if (!$r instanceof Undefined) {
74814 return $r;
74815 }
74816
74817 if ($len) {
74818 $this->popStack($len);
74819 }
74820
74821 $this->stack[] = $this->productions_[$action[1]][0]; 
74822  $this->vstack[] = $yyval->token;
74823 $this->lstack[] = $yyval->store;
74824 $newState = $this->table[$this->stack[count($this->stack)-2]][$this->stack[count($this->stack)-1]];
74825 $this->stack[] = $newState;
74826 break;
74827
74828 case 3: 
74829
74830 return true;
74831 }
74832 }
74833
74834 return true;
74835 }
74836
74837 protected function parseError($str, $hash)
74838 {
74839 throw new ParsingException($str, $hash);
74840 }
74841
74842
74843  
74844  
74845  private function performAction(stdClass $yyval, $yytext, $yyleng, $yylineno, $yystate, &$tokens)
74846 {
74847
74848  $len = count($tokens) - 1;
74849 switch ($yystate) {
74850 case 1:
74851 $yytext = preg_replace_callback('{(?:\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4})}', array($this, 'stringInterpolation'), $yytext);
74852 $yyval->token = $yytext;
74853 break;
74854 case 2:
74855 if (strpos($yytext, 'e') !== false || strpos($yytext, 'E') !== false) {
74856 $yyval->token = floatval($yytext);
74857 } else {
74858 $yyval->token = strpos($yytext, '.') === false ? intval($yytext) : floatval($yytext);
74859 }
74860 break;
74861 case 3:
74862 $yyval->token = null;
74863 break;
74864 case 4:
74865 $yyval->token = true;
74866 break;
74867 case 5:
74868 $yyval->token = false;
74869 break;
74870 case 6:
74871 return $yyval->token = $tokens[$len-1];
74872 case 13:
74873 if ($this->flags & self::PARSE_TO_ASSOC) {
74874 $yyval->token = array();
74875 } else {
74876 $yyval->token = new stdClass;
74877 }
74878 break;
74879 case 14:
74880 $yyval->token = $tokens[$len-1];
74881 break;
74882 case 15:
74883 $yyval->token = array($tokens[$len-2], $tokens[$len]);
74884 break;
74885 case 16:
74886 if (PHP_VERSION_ID < 70100) {
74887 $property = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
74888 } else {
74889 $property = $tokens[$len][0];
74890 }
74891 if ($this->flags & self::PARSE_TO_ASSOC) {
74892 $yyval->token = array();
74893 $yyval->token[$property] = $tokens[$len][1];
74894 } else {
74895 $yyval->token = new stdClass;
74896 $yyval->token->$property = $tokens[$len][1];
74897 }
74898 break;
74899 case 17:
74900 if ($this->flags & self::PARSE_TO_ASSOC) {
74901 $yyval->token =& $tokens[$len-2];
74902 $key = $tokens[$len][0];
74903 if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2][$key])) {
74904 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
74905 $errStr .= $this->lexer->showPosition() . "\n";
74906 $errStr .= "Duplicate key: ".$tokens[$len][0];
74907 throw new DuplicateKeyException($errStr, $tokens[$len][0], array('line' => $yylineno+1));
74908 } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2][$key])) {
74909 $duplicateCount = 1;
74910 do {
74911 $duplicateKey = $key . '.' . $duplicateCount++;
74912 } while (isset($tokens[$len-2][$duplicateKey]));
74913 $key = $duplicateKey;
74914 }
74915 $tokens[$len-2][$key] = $tokens[$len][1];
74916 } else {
74917 $yyval->token = $tokens[$len-2];
74918 if (PHP_VERSION_ID < 70100) {
74919 $key = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
74920 } else {
74921 $key = $tokens[$len][0];
74922 }
74923 if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2]->{$key})) {
74924 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
74925 $errStr .= $this->lexer->showPosition() . "\n";
74926 $errStr .= "Duplicate key: ".$tokens[$len][0];
74927 throw new DuplicateKeyException($errStr, $tokens[$len][0], array('line' => $yylineno+1));
74928 } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2]->{$key})) {
74929 $duplicateCount = 1;
74930 do {
74931 $duplicateKey = $key . '.' . $duplicateCount++;
74932 } while (isset($tokens[$len-2]->$duplicateKey));
74933 $key = $duplicateKey;
74934 }
74935 $tokens[$len-2]->$key = $tokens[$len][1];
74936 }
74937 break;
74938 case 18:
74939 $yyval->token = array();
74940 break;
74941 case 19:
74942 $yyval->token = $tokens[$len-1];
74943 break;
74944 case 20:
74945 $yyval->token = array($tokens[$len]);
74946 break;
74947 case 21:
74948 $tokens[$len-2][] = $tokens[$len];
74949 $yyval->token = $tokens[$len-2];
74950 break;
74951 }
74952
74953 return new Undefined();
74954 }
74955
74956 private function stringInterpolation($match)
74957 {
74958 switch ($match[0]) {
74959 case '\\\\':
74960 return '\\';
74961 case '\"':
74962 return '"';
74963 case '\b':
74964 return chr(8);
74965 case '\f':
74966 return chr(12);
74967 case '\n':
74968 return "\n";
74969 case '\r':
74970 return "\r";
74971 case '\t':
74972 return "\t";
74973 case '\/':
74974 return "/";
74975 default:
74976 return html_entity_decode('&#x'.ltrim(substr($match[0], 2), '0').';', 0, 'UTF-8');
74977 }
74978 }
74979
74980 private function popStack($n)
74981 {
74982 $this->stack = array_slice($this->stack, 0, - (2 * $n));
74983 $this->vstack = array_slice($this->vstack, 0, - $n);
74984 $this->lstack = array_slice($this->lstack, 0, - $n);
74985 }
74986
74987 private function lex()
74988 {
74989 $token = $this->lexer->lex() ?: 1; 
74990  
74991  if (!is_numeric($token)) {
74992 $token = isset($this->symbols[$token]) ? $this->symbols[$token] : $token;
74993 }
74994
74995 return $token;
74996 }
74997
74998 private function failOnBOM($input)
74999 {
75000
75001  $bom = "\xEF\xBB\xBF";
75002
75003 if (substr($input, 0, 3) === $bom) {
75004 $this->parseError("BOM detected, make sure your input does not include a Unicode Byte-Order-Mark", array());
75005 }
75006 }
75007 }
75008 <?php
75009
75010
75011
75012
75013
75014
75015
75016
75017
75018
75019 namespace Seld\JsonLint;
75020
75021
75022
75023
75024
75025
75026 class Lexer
75027 {
75028 private $EOF = 1;
75029 private $rules = array(
75030 0 => '/^\s+/',
75031 1 => '/^-?([0-9]|[1-9][0-9]+)(\.[0-9]+)?([eE][+-]?[0-9]+)?\b/',
75032 2 => '{^"(?>\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\0-\x1f\\\\"]++)*+"}',
75033 3 => '/^\{/',
75034 4 => '/^\}/',
75035 5 => '/^\[/',
75036 6 => '/^\]/',
75037 7 => '/^,/',
75038 8 => '/^:/',
75039 9 => '/^true\b/',
75040 10 => '/^false\b/',
75041 11 => '/^null\b/',
75042 12 => '/^$/',
75043 13 => '/^./',
75044 );
75045
75046 private $conditions = array(
75047 "INITIAL" => array(
75048 "rules" => array(0,1,2,3,4,5,6,7,8,9,10,11,12,13),
75049 "inclusive" => true,
75050 ),
75051 );
75052
75053 private $conditionStack;
75054 private $input;
75055 private $more;
75056 private $done;
75057 private $matched;
75058
75059 public $match;
75060 public $yylineno;
75061 public $yyleng;
75062 public $yytext;
75063 public $yylloc;
75064
75065 public function lex()
75066 {
75067 $r = $this->next();
75068 if (!$r instanceof Undefined) {
75069 return $r;
75070 }
75071
75072 return $this->lex();
75073 }
75074
75075 public function setInput($input)
75076 {
75077 $this->input = $input;
75078 $this->more = false;
75079 $this->done = false;
75080 $this->yylineno = $this->yyleng = 0;
75081 $this->yytext = $this->matched = $this->match = '';
75082 $this->conditionStack = array('INITIAL');
75083 $this->yylloc = array('first_line' => 1, 'first_column' => 0, 'last_line' => 1, 'last_column' => 0);
75084
75085 return $this;
75086 }
75087
75088 public function showPosition()
75089 {
75090 $pre = str_replace("\n", '', $this->getPastInput());
75091 $c = str_repeat('-', max(0, strlen($pre) - 1)); 
75092
75093 return $pre . str_replace("\n", '', $this->getUpcomingInput()) . "\n" . $c . "^";
75094 }
75095
75096 public function getPastInput()
75097 {
75098 $past = substr($this->matched, 0, strlen($this->matched) - strlen($this->match));
75099
75100 return (strlen($past) > 20 ? '...' : '') . substr($past, -20);
75101 }
75102
75103 public function getUpcomingInput()
75104 {
75105 $next = $this->match;
75106 if (strlen($next) < 20) {
75107 $next .= substr($this->input, 0, 20 - strlen($next));
75108 }
75109
75110 return substr($next, 0, 20) . (strlen($next) > 20 ? '...' : '');
75111 }
75112
75113 protected function parseError($str, $hash)
75114 {
75115 throw new \Exception($str);
75116 }
75117
75118 private function next()
75119 {
75120 if ($this->done) {
75121 return $this->EOF;
75122 }
75123 if ($this->input === '') {
75124 $this->done = true;
75125 }
75126
75127 $token = null;
75128 $match = null;
75129 $col = null;
75130 $lines = null;
75131
75132 if (!$this->more) {
75133 $this->yytext = '';
75134 $this->match = '';
75135 }
75136
75137 $rules = $this->getCurrentRules();
75138 $rulesLen = count($rules);
75139
75140 for ($i=0; $i < $rulesLen; $i++) {
75141 if (preg_match($this->rules[$rules[$i]], $this->input, $match)) {
75142 preg_match_all('/\n.*/', $match[0], $lines);
75143 $lines = $lines[0];
75144 if ($lines) {
75145 $this->yylineno += count($lines);
75146 }
75147
75148 $this->yylloc = array(
75149 'first_line' => $this->yylloc['last_line'],
75150 'last_line' => $this->yylineno+1,
75151 'first_column' => $this->yylloc['last_column'],
75152 'last_column' => $lines ? strlen($lines[count($lines) - 1]) - 1 : $this->yylloc['last_column'] + strlen($match[0]),
75153 );
75154 $this->yytext .= $match[0];
75155 $this->match .= $match[0];
75156 $this->yyleng = strlen($this->yytext);
75157 $this->more = false;
75158 $this->input = substr($this->input, strlen($match[0]));
75159 $this->matched .= $match[0];
75160 $token = $this->performAction($rules[$i], $this->conditionStack[count($this->conditionStack)-1]);
75161 if ($token) {
75162 return $token;
75163 }
75164
75165 return new Undefined();
75166 }
75167 }
75168
75169 if ($this->input === "") {
75170 return $this->EOF;
75171 }
75172
75173 $this->parseError(
75174 'Lexical error on line ' . ($this->yylineno+1) . ". Unrecognized text.\n" . $this->showPosition(),
75175 array(
75176 'text' => "",
75177 'token' => null,
75178 'line' => $this->yylineno,
75179 )
75180 );
75181 }
75182
75183 private function getCurrentRules()
75184 {
75185 return $this->conditions[$this->conditionStack[count($this->conditionStack)-1]]['rules'];
75186 }
75187
75188 private function performAction($avoiding_name_collisions, $YY_START)
75189 {
75190 switch ($avoiding_name_collisions) {
75191 case 0:
75192 break;
75193 case 1:
75194 return 6;
75195 break;
75196 case 2:
75197 $this->yytext = substr($this->yytext, 1, $this->yyleng-2);
75198
75199 return 4;
75200 case 3:
75201 return 17;
75202 case 4:
75203 return 18;
75204 case 5:
75205 return 23;
75206 case 6:
75207 return 24;
75208 case 7:
75209 return 22;
75210 case 8:
75211 return 21;
75212 case 9:
75213 return 10;
75214 case 10:
75215 return 11;
75216 case 11:
75217 return 8;
75218 case 12:
75219 return 14;
75220 case 13:
75221 return 'INVALID';
75222 }
75223 }
75224 }
75225 <?php
75226
75227
75228
75229
75230
75231
75232
75233
75234
75235
75236 namespace Seld\JsonLint;
75237
75238 class ParsingException extends \Exception
75239 {
75240 protected $details;
75241
75242 public function __construct($message, $details = array())
75243 {
75244 $this->details = $details;
75245 parent::__construct($message);
75246 }
75247
75248 public function getDetails()
75249 {
75250 return $this->details;
75251 }
75252 }
75253 <?php
75254
75255
75256
75257
75258
75259
75260
75261
75262
75263
75264 namespace Seld\JsonLint;
75265
75266 class Undefined
75267 {
75268 }
75269 Copyright (c) 2015 Jordi Boggiano
75270
75271 Permission is hereby granted, free of charge, to any person obtaining a copy
75272 of this software and associated documentation files (the "Software"), to deal
75273 in the Software without restriction, including without limitation the rights
75274 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
75275 copies of the Software, and to permit persons to whom the Software is furnished
75276 to do so, subject to the following conditions:
75277
75278 The above copyright notice and this permission notice shall be included in all
75279 copies or substantial portions of the Software.
75280
75281 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
75282 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
75283 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
75284 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
75285 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
75286 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
75287 THE SOFTWARE.
75288 <?php
75289
75290 require __DIR__.'/../vendor/autoload.php';
75291
75292 echo 'Say hello (visible): ';
75293
75294 $answer = Seld\CliPrompt\CliPrompt::prompt();
75295
75296 echo 'You answered: '.$answer . PHP_EOL;
75297
75298 echo 'Say hello (hidden): ';
75299
75300 $answer = Seld\CliPrompt\CliPrompt::hiddenPrompt();
75301
75302 echo 'You answered: '.$answer . PHP_EOL;
75303 <?php
75304
75305
75306
75307
75308
75309
75310
75311
75312
75313
75314 namespace Seld\CliPrompt;
75315
75316 class CliPrompt
75317 {
75318
75319
75320
75321
75322
75323 public static function prompt()
75324 {
75325 $stdin = fopen('php://stdin', 'r');
75326 $answer = self::trimAnswer(fgets($stdin, 4096));
75327 fclose($stdin);
75328
75329 return $answer;
75330 }
75331
75332
75333
75334
75335
75336
75337
75338
75339
75340
75341 public static function hiddenPrompt($allowFallback = false)
75342 {
75343
75344  if (defined('PHP_WINDOWS_VERSION_BUILD')) {
75345
75346  $exe = __DIR__.'\\..\\res\\hiddeninput.exe';
75347
75348
75349  if ('phar:' === substr(__FILE__, 0, 5)) {
75350 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
75351
75352
75353  
75354  $source = fopen($exe, 'r');
75355 $target = fopen($tmpExe, 'w+');
75356 stream_copy_to_stream($source, $target);
75357 fclose($source);
75358 fclose($target);
75359 unset($source, $target);
75360
75361 $exe = $tmpExe;
75362 }
75363
75364 $output = shell_exec($exe);
75365
75366
75367  if (isset($tmpExe)) {
75368 unlink($tmpExe);
75369 }
75370
75371 if ($output !== null) {
75372
75373  echo PHP_EOL;
75374
75375 return self::trimAnswer($output);
75376 }
75377 }
75378
75379 if (file_exists('/usr/bin/env')) {
75380
75381  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
75382 foreach (array('bash', 'zsh', 'ksh', 'csh', 'sh') as $sh) {
75383 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
75384 $shell = $sh;
75385 break;
75386 }
75387 }
75388
75389 if (isset($shell)) {
75390 $readCmd = ($shell === 'csh') ? 'set mypassword = $<' : 'read -r mypassword';
75391 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
75392 $output = shell_exec($command);
75393
75394 if ($output !== null) {
75395
75396  echo PHP_EOL;
75397
75398 return self::trimAnswer($output);
75399 }
75400 }
75401 }
75402
75403
75404  if (!$allowFallback) {
75405 throw new \RuntimeException('Could not prompt for input in a secure fashion, aborting');
75406 }
75407
75408 return self::prompt();
75409 }
75410
75411 private static function trimAnswer($str)
75412 {
75413 return preg_replace('{\r?\n$}D', '', $str);
75414 }
75415 }
75416 MIT License
75417
75418 Copyright (c) 2016
75419
75420 Permission is hereby granted, free of charge, to any person obtaining a copy
75421 of this software and associated documentation files (the "Software"), to deal
75422 in the Software without restriction, including without limitation the rights
75423 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
75424 copies of the Software, and to permit persons to whom the Software is
75425 furnished to do so, subject to the following conditions:
75426
75427 The above copyright notice and this permission notice shall be included in all
75428 copies or substantial portions of the Software.
75429
75430 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
75431 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
75432 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
75433 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
75434 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
75435 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
75436 SOFTWARE.
75437 <?php
75438
75439 require __DIR__ . '/../vendor/autoload.php';
75440
75441 $data = json_decode(file_get_contents('data.json'));
75442
75443
75444 $validator = new JsonSchema\Validator();
75445 $validator->check($data, (object) array('$ref' => 'file://' . realpath('schema.json')));
75446
75447 if ($validator->isValid()) {
75448 echo "The supplied JSON validates against the schema.\n";
75449 } else {
75450 echo "JSON does not validate. Violations:\n";
75451 foreach ($validator->getErrors() as $error) {
75452 echo sprintf("[%s] %s\n", $error['property'], $error['message']);
75453 }
75454 }
75455 <?php
75456
75457
75458
75459
75460
75461
75462
75463
75464 namespace JsonSchema\Constraints;
75465
75466 use JsonSchema\Entity\JsonPointer;
75467 use JsonSchema\Exception\InvalidArgumentException;
75468 use JsonSchema\Exception\ValidationException;
75469 use JsonSchema\Validator;
75470
75471
75472
75473
75474
75475 class BaseConstraint
75476 {
75477
75478
75479
75480 protected $errors = array();
75481
75482
75483
75484
75485 protected $errorMask = Validator::ERROR_NONE;
75486
75487
75488
75489
75490 protected $factory;
75491
75492
75493
75494
75495 public function __construct(Factory $factory = null)
75496 {
75497 $this->factory = $factory ?: new Factory();
75498 }
75499
75500 public function addError(JsonPointer $path = null, $message, $constraint = '', array $more = null)
75501 {
75502 $error = array(
75503 'property' => $this->convertJsonPointerIntoPropertyPath($path ?: new JsonPointer('')),
75504 'pointer' => ltrim(strval($path ?: new JsonPointer('')), '#'),
75505 'message' => $message,
75506 'constraint' => $constraint,
75507 'context' => $this->factory->getErrorContext(),
75508 );
75509
75510 if ($this->factory->getConfig(Constraint::CHECK_MODE_EXCEPTIONS)) {
75511 throw new ValidationException(sprintf('Error validating %s: %s', $error['pointer'], $error['message']));
75512 }
75513
75514 if (is_array($more) && count($more) > 0) {
75515 $error += $more;
75516 }
75517
75518 $this->errors[] = $error;
75519 $this->errorMask |= $error['context'];
75520 }
75521
75522 public function addErrors(array $errors)
75523 {
75524 if ($errors) {
75525 $this->errors = array_merge($this->errors, $errors);
75526 $errorMask = &$this->errorMask;
75527 array_walk($errors, function ($error) use (&$errorMask) {
75528 if (isset($error['context'])) {
75529 $errorMask |= $error['context'];
75530 }
75531 });
75532 }
75533 }
75534
75535 public function getErrors($errorContext = Validator::ERROR_ALL)
75536 {
75537 if ($errorContext === Validator::ERROR_ALL) {
75538 return $this->errors;
75539 }
75540
75541 return array_filter($this->errors, function ($error) use ($errorContext) {
75542 if ($errorContext & $error['context']) {
75543 return true;
75544 }
75545 });
75546 }
75547
75548 public function numErrors($errorContext = Validator::ERROR_ALL)
75549 {
75550 if ($errorContext === Validator::ERROR_ALL) {
75551 return count($this->errors);
75552 }
75553
75554 return count($this->getErrors($errorContext));
75555 }
75556
75557 public function isValid()
75558 {
75559 return !$this->getErrors();
75560 }
75561
75562
75563
75564
75565
75566 public function reset()
75567 {
75568 $this->errors = array();
75569 $this->errorMask = Validator::ERROR_NONE;
75570 }
75571
75572
75573
75574
75575
75576
75577 public function getErrorMask()
75578 {
75579 return $this->errorMask;
75580 }
75581
75582
75583
75584
75585
75586
75587
75588
75589 public static function arrayToObjectRecursive($array)
75590 {
75591 $json = json_encode($array);
75592 if (json_last_error() !== \JSON_ERROR_NONE) {
75593 $message = 'Unable to encode schema array as JSON';
75594 if (function_exists('json_last_error_msg')) {
75595 $message .= ': ' . json_last_error_msg();
75596 }
75597 throw new InvalidArgumentException($message);
75598 }
75599
75600 return (object) json_decode($json);
75601 }
75602 }
75603 <?php
75604
75605
75606
75607
75608
75609
75610
75611
75612 namespace JsonSchema\Constraints;
75613
75614 use JsonSchema\Entity\JsonPointer;
75615
75616
75617
75618
75619
75620
75621
75622 class CollectionConstraint extends Constraint
75623 {
75624
75625
75626
75627 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null)
75628 {
75629
75630  if (isset($schema->minItems) && count($value) < $schema->minItems) {
75631 $this->addError($path, 'There must be a minimum of ' . $schema->minItems . ' items in the array', 'minItems', array('minItems' => $schema->minItems));
75632 }
75633
75634
75635  if (isset($schema->maxItems) && count($value) > $schema->maxItems) {
75636 $this->addError($path, 'There must be a maximum of ' . $schema->maxItems . ' items in the array', 'maxItems', array('maxItems' => $schema->maxItems));
75637 }
75638
75639
75640  if (isset($schema->uniqueItems) && $schema->uniqueItems) {
75641 $unique = $value;
75642 if (is_array($value) && count($value)) {
75643 $unique = array_map(function ($e) {
75644 return var_export($e, true);
75645 }, $value);
75646 }
75647 if (count(array_unique($unique)) != count($value)) {
75648 $this->addError($path, 'There are no duplicates allowed in the array', 'uniqueItems');
75649 }
75650 }
75651
75652
75653  if (isset($schema->items)) {
75654 $this->validateItems($value, $schema, $path, $i);
75655 }
75656 }
75657
75658
75659
75660
75661
75662
75663
75664
75665
75666 protected function validateItems(&$value, $schema = null, JsonPointer $path = null, $i = null)
75667 {
75668 if (is_object($schema->items)) {
75669
75670
75671 if (isset($schema->items->type)
75672 && (
75673 $schema->items->type == 'string'
75674 || $schema->items->type == 'number'
75675 || $schema->items->type == 'integer'
75676 )
75677 && !isset($schema->additionalItems)
75678 ) {
75679
75680  $type = $schema->items->type;
75681 $typeValidator = $this->factory->createInstanceFor('type');
75682 $validator = $this->factory->createInstanceFor($type === 'integer' ? 'number' : $type);
75683
75684 foreach ($value as $k => &$v) {
75685 $k_path = $this->incrementPath($path, $k);
75686 $typeValidator->check($v, $schema->items, $k_path, $i);
75687
75688 $validator->check($v, $schema->items, $k_path, $i);
75689 }
75690 unset($v); 
75691  
75692  $this->addErrors($typeValidator->getErrors());
75693 $this->addErrors($validator->getErrors());
75694 } else {
75695 foreach ($value as $k => &$v) {
75696 $initErrors = $this->getErrors();
75697
75698
75699  $this->checkUndefined($v, $schema->items, $path, $k);
75700
75701
75702  if (count($initErrors) < count($this->getErrors()) && (isset($schema->additionalItems) && $schema->additionalItems !== false)) {
75703 $secondErrors = $this->getErrors();
75704 $this->checkUndefined($v, $schema->additionalItems, $path, $k);
75705 }
75706
75707
75708  if (isset($secondErrors) && count($secondErrors) < count($this->getErrors())) {
75709 $this->errors = $secondErrors;
75710 } elseif (isset($secondErrors) && count($secondErrors) === count($this->getErrors())) {
75711 $this->errors = $initErrors;
75712 }
75713 }
75714 unset($v); 
75715  
75716  }
75717 } else {
75718
75719  foreach ($value as $k => &$v) {
75720 if (array_key_exists($k, $schema->items)) {
75721 $this->checkUndefined($v, $schema->items[$k], $path, $k);
75722 } else {
75723
75724  if (property_exists($schema, 'additionalItems')) {
75725 if ($schema->additionalItems !== false) {
75726 $this->checkUndefined($v, $schema->additionalItems, $path, $k);
75727 } else {
75728 $this->addError(
75729 $path, 'The item ' . $i . '[' . $k . '] is not defined and the definition does not allow additional items', 'additionalItems', array('additionalItems' => $schema->additionalItems));
75730 }
75731 } else {
75732
75733  $this->checkUndefined($v, new \stdClass(), $path, $k);
75734 }
75735 }
75736 }
75737 unset($v); 
75738  
75739
75740
75741  if (count($value) > 0) {
75742 for ($k = count($value); $k < count($schema->items); $k++) {
75743 $undefinedInstance = $this->factory->createInstanceFor('undefined');
75744 $this->checkUndefined($undefinedInstance, $schema->items[$k], $path, $k);
75745 }
75746 }
75747 }
75748 }
75749 }
75750 <?php
75751
75752
75753
75754
75755
75756
75757
75758
75759 namespace JsonSchema\Constraints;
75760
75761 use JsonSchema\Entity\JsonPointer;
75762 use JsonSchema\SchemaStorage;
75763 use JsonSchema\Uri\UriRetriever;
75764 use JsonSchema\UriRetrieverInterface;
75765
75766
75767
75768
75769
75770
75771
75772 abstract class Constraint extends BaseConstraint implements ConstraintInterface
75773 {
75774 protected $inlineSchemaProperty = '$schema';
75775
75776 const CHECK_MODE_NONE = 0x00000000;
75777 const CHECK_MODE_NORMAL = 0x00000001;
75778 const CHECK_MODE_TYPE_CAST = 0x00000002;
75779 const CHECK_MODE_COERCE_TYPES = 0x00000004;
75780 const CHECK_MODE_APPLY_DEFAULTS = 0x00000008;
75781 const CHECK_MODE_EXCEPTIONS = 0x00000010;
75782 const CHECK_MODE_DISABLE_FORMAT = 0x00000020;
75783 const CHECK_MODE_ONLY_REQUIRED_DEFAULTS = 0x00000080;
75784 const CHECK_MODE_VALIDATE_SCHEMA = 0x00000100;
75785
75786
75787
75788
75789
75790
75791
75792
75793
75794 protected function incrementPath(JsonPointer $path = null, $i)
75795 {
75796 $path = $path ?: new JsonPointer('');
75797 $path = $path->withPropertyPaths(
75798 array_merge(
75799 $path->getPropertyPaths(),
75800 array_filter(array($i), 'strlen')
75801 )
75802 );
75803
75804 return $path;
75805 }
75806
75807
75808
75809
75810
75811
75812
75813
75814
75815 protected function checkArray(&$value, $schema = null, JsonPointer $path = null, $i = null)
75816 {
75817 $validator = $this->factory->createInstanceFor('collection');
75818 $validator->check($value, $schema, $path, $i);
75819
75820 $this->addErrors($validator->getErrors());
75821 }
75822
75823
75824
75825
75826
75827
75828
75829
75830
75831
75832
75833 protected function checkObject(&$value, $schema = null, JsonPointer $path = null, $properties = null,
75834 $additionalProperties = null, $patternProperties = null, $appliedDefaults = array())
75835 {
75836 $validator = $this->factory->createInstanceFor('object');
75837 $validator->check($value, $schema, $path, $properties, $additionalProperties, $patternProperties, $appliedDefaults);
75838
75839 $this->addErrors($validator->getErrors());
75840 }
75841
75842
75843
75844
75845
75846
75847
75848
75849
75850 protected function checkType(&$value, $schema = null, JsonPointer $path = null, $i = null)
75851 {
75852 $validator = $this->factory->createInstanceFor('type');
75853 $validator->check($value, $schema, $path, $i);
75854
75855 $this->addErrors($validator->getErrors());
75856 }
75857
75858
75859
75860
75861
75862
75863
75864
75865
75866 protected function checkUndefined(&$value, $schema = null, JsonPointer $path = null, $i = null, $fromDefault = false)
75867 {
75868 $validator = $this->factory->createInstanceFor('undefined');
75869
75870 $validator->check($value, $this->factory->getSchemaStorage()->resolveRefSchema($schema), $path, $i, $fromDefault);
75871
75872 $this->addErrors($validator->getErrors());
75873 }
75874
75875
75876
75877
75878
75879
75880
75881
75882
75883 protected function checkString($value, $schema = null, JsonPointer $path = null, $i = null)
75884 {
75885 $validator = $this->factory->createInstanceFor('string');
75886 $validator->check($value, $schema, $path, $i);
75887
75888 $this->addErrors($validator->getErrors());
75889 }
75890
75891
75892
75893
75894
75895
75896
75897
75898
75899 protected function checkNumber($value, $schema = null, JsonPointer $path = null, $i = null)
75900 {
75901 $validator = $this->factory->createInstanceFor('number');
75902 $validator->check($value, $schema, $path, $i);
75903
75904 $this->addErrors($validator->getErrors());
75905 }
75906
75907
75908
75909
75910
75911
75912
75913
75914
75915 protected function checkEnum($value, $schema = null, JsonPointer $path = null, $i = null)
75916 {
75917 $validator = $this->factory->createInstanceFor('enum');
75918 $validator->check($value, $schema, $path, $i);
75919
75920 $this->addErrors($validator->getErrors());
75921 }
75922
75923
75924
75925
75926
75927
75928
75929
75930
75931 protected function checkFormat($value, $schema = null, JsonPointer $path = null, $i = null)
75932 {
75933 $validator = $this->factory->createInstanceFor('format');
75934 $validator->check($value, $schema, $path, $i);
75935
75936 $this->addErrors($validator->getErrors());
75937 }
75938
75939
75940
75941
75942
75943
75944 protected function getTypeCheck()
75945 {
75946 return $this->factory->getTypeCheck();
75947 }
75948
75949
75950
75951
75952
75953
75954 protected function convertJsonPointerIntoPropertyPath(JsonPointer $pointer)
75955 {
75956 $result = array_map(
75957 function ($path) {
75958 return sprintf(is_numeric($path) ? '[%d]' : '.%s', $path);
75959 },
75960 $pointer->getPropertyPaths()
75961 );
75962
75963 return trim(implode('', $result), '.');
75964 }
75965 }
75966 <?php
75967
75968
75969
75970
75971
75972
75973
75974
75975 namespace JsonSchema\Constraints;
75976
75977 use JsonSchema\Entity\JsonPointer;
75978
75979
75980
75981
75982
75983
75984 interface ConstraintInterface
75985 {
75986
75987
75988
75989
75990
75991 public function getErrors();
75992
75993
75994
75995
75996
75997
75998 public function addErrors(array $errors);
75999
76000
76001
76002
76003
76004
76005
76006
76007
76008 public function addError(JsonPointer $path = null, $message, $constraint='', array $more = null);
76009
76010
76011
76012
76013
76014
76015 public function isValid();
76016
76017
76018
76019
76020
76021
76022
76023
76024
76025
76026
76027
76028
76029 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null);
76030 }
76031 <?php
76032
76033
76034
76035
76036
76037
76038
76039
76040 namespace JsonSchema\Constraints;
76041
76042 use JsonSchema\Entity\JsonPointer;
76043
76044
76045
76046
76047
76048
76049
76050 class EnumConstraint extends Constraint
76051 {
76052
76053
76054
76055 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
76056 {
76057
76058  if ($element instanceof UndefinedConstraint && (!isset($schema->required) || !$schema->required)) {
76059 return;
76060 }
76061 $type = gettype($element);
76062
76063 foreach ($schema->enum as $enum) {
76064 $enumType = gettype($enum);
76065 if ($this->factory->getConfig(self::CHECK_MODE_TYPE_CAST) && $type == 'array' && $enumType == 'object') {
76066 if ((object) $element == $enum) {
76067 return;
76068 }
76069 }
76070
76071 if ($type === gettype($enum)) {
76072 if ($type == 'object') {
76073 if ($element == $enum) {
76074 return;
76075 }
76076 } elseif ($element === $enum) {
76077 return;
76078 }
76079 }
76080 }
76081
76082 $this->addError($path, 'Does not have a value in the enumeration ' . json_encode($schema->enum), 'enum', array('enum' => $schema->enum));
76083 }
76084 }
76085 <?php
76086
76087
76088
76089
76090
76091
76092
76093
76094 namespace JsonSchema\Constraints;
76095
76096 use JsonSchema\Constraints\Constraint;
76097 use JsonSchema\Exception\InvalidArgumentException;
76098 use JsonSchema\Exception\InvalidConfigException;
76099 use JsonSchema\SchemaStorage;
76100 use JsonSchema\SchemaStorageInterface;
76101 use JsonSchema\Uri\UriRetriever;
76102 use JsonSchema\UriRetrieverInterface;
76103 use JsonSchema\Validator;
76104
76105
76106
76107
76108 class Factory
76109 {
76110
76111
76112
76113 protected $schemaStorage;
76114
76115
76116
76117
76118 protected $uriRetriever;
76119
76120
76121
76122
76123 private $checkMode = Constraint::CHECK_MODE_NORMAL;
76124
76125
76126
76127
76128 private $typeCheck = array();
76129
76130
76131
76132
76133 protected $errorContext = Validator::ERROR_DOCUMENT_VALIDATION;
76134
76135
76136
76137
76138 protected $constraintMap = array(
76139 'array' => 'JsonSchema\Constraints\CollectionConstraint',
76140 'collection' => 'JsonSchema\Constraints\CollectionConstraint',
76141 'object' => 'JsonSchema\Constraints\ObjectConstraint',
76142 'type' => 'JsonSchema\Constraints\TypeConstraint',
76143 'undefined' => 'JsonSchema\Constraints\UndefinedConstraint',
76144 'string' => 'JsonSchema\Constraints\StringConstraint',
76145 'number' => 'JsonSchema\Constraints\NumberConstraint',
76146 'enum' => 'JsonSchema\Constraints\EnumConstraint',
76147 'format' => 'JsonSchema\Constraints\FormatConstraint',
76148 'schema' => 'JsonSchema\Constraints\SchemaConstraint',
76149 'validator' => 'JsonSchema\Validator'
76150 );
76151
76152
76153
76154
76155 private $instanceCache = array();
76156
76157
76158
76159
76160
76161
76162 public function __construct(
76163 SchemaStorageInterface $schemaStorage = null,
76164 UriRetrieverInterface $uriRetriever = null,
76165 $checkMode = Constraint::CHECK_MODE_NORMAL
76166 ) {
76167
76168  $this->setConfig($checkMode);
76169
76170 $this->uriRetriever = $uriRetriever ?: new UriRetriever();
76171 $this->schemaStorage = $schemaStorage ?: new SchemaStorage($this->uriRetriever);
76172 }
76173
76174
76175
76176
76177
76178
76179 public function setConfig($checkMode = Constraint::CHECK_MODE_NORMAL)
76180 {
76181 $this->checkMode = $checkMode;
76182 }
76183
76184
76185
76186
76187
76188
76189 public function addConfig($options)
76190 {
76191 $this->checkMode |= $options;
76192 }
76193
76194
76195
76196
76197
76198
76199 public function removeConfig($options)
76200 {
76201 $this->checkMode &= ~$options;
76202 }
76203
76204
76205
76206
76207
76208
76209
76210
76211 public function getConfig($options = null)
76212 {
76213 if ($options === null) {
76214 return $this->checkMode;
76215 }
76216
76217 return $this->checkMode & $options;
76218 }
76219
76220
76221
76222
76223 public function getUriRetriever()
76224 {
76225 return $this->uriRetriever;
76226 }
76227
76228 public function getSchemaStorage()
76229 {
76230 return $this->schemaStorage;
76231 }
76232
76233 public function getTypeCheck()
76234 {
76235 if (!isset($this->typeCheck[$this->checkMode])) {
76236 $this->typeCheck[$this->checkMode] = ($this->checkMode & Constraint::CHECK_MODE_TYPE_CAST)
76237 ? new TypeCheck\LooseTypeCheck()
76238 : new TypeCheck\StrictTypeCheck();
76239 }
76240
76241 return $this->typeCheck[$this->checkMode];
76242 }
76243
76244
76245
76246
76247
76248
76249
76250 public function setConstraintClass($name, $class)
76251 {
76252
76253  if (!class_exists($class)) {
76254 throw new InvalidArgumentException('Unknown constraint ' . $name);
76255 }
76256
76257  if (!in_array('JsonSchema\Constraints\ConstraintInterface', class_implements($class))) {
76258 throw new InvalidArgumentException('Invalid class ' . $name);
76259 }
76260 $this->constraintMap[$name] = $class;
76261
76262 return $this;
76263 }
76264
76265
76266
76267
76268
76269
76270
76271
76272
76273
76274 public function createInstanceFor($constraintName)
76275 {
76276 if (!isset($this->constraintMap[$constraintName])) {
76277 throw new InvalidArgumentException('Unknown constraint ' . $constraintName);
76278 }
76279
76280 if (!isset($this->instanceCache[$constraintName])) {
76281 $this->instanceCache[$constraintName] = new $this->constraintMap[$constraintName]($this);
76282 }
76283
76284 return clone $this->instanceCache[$constraintName];
76285 }
76286
76287
76288
76289
76290
76291
76292 public function getErrorContext()
76293 {
76294 return $this->errorContext;
76295 }
76296
76297
76298
76299
76300
76301
76302 public function setErrorContext($errorContext)
76303 {
76304 $this->errorContext = $errorContext;
76305 }
76306 }
76307 <?php
76308
76309
76310
76311
76312
76313
76314
76315
76316 namespace JsonSchema\Constraints;
76317
76318 use JsonSchema\Entity\JsonPointer;
76319 use JsonSchema\Rfc3339;
76320
76321
76322
76323
76324
76325
76326
76327
76328 class FormatConstraint extends Constraint
76329 {
76330
76331
76332
76333 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
76334 {
76335 if (!isset($schema->format) || $this->factory->getConfig(self::CHECK_MODE_DISABLE_FORMAT)) {
76336 return;
76337 }
76338
76339 switch ($schema->format) {
76340 case 'date':
76341 if (!$date = $this->validateDateTime($element, 'Y-m-d')) {
76342 $this->addError($path, sprintf('Invalid date %s, expected format YYYY-MM-DD', json_encode($element)), 'format', array('format' => $schema->format));
76343 }
76344 break;
76345
76346 case 'time':
76347 if (!$this->validateDateTime($element, 'H:i:s')) {
76348 $this->addError($path, sprintf('Invalid time %s, expected format hh:mm:ss', json_encode($element)), 'format', array('format' => $schema->format));
76349 }
76350 break;
76351
76352 case 'date-time':
76353 if (null === Rfc3339::createFromString($element)) {
76354 $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));
76355 }
76356 break;
76357
76358 case 'utc-millisec':
76359 if (!$this->validateDateTime($element, 'U')) {
76360 $this->addError($path, sprintf('Invalid time %s, expected integer of milliseconds since Epoch', json_encode($element)), 'format', array('format' => $schema->format));
76361 }
76362 break;
76363
76364 case 'regex':
76365 if (!$this->validateRegex($element)) {
76366 $this->addError($path, 'Invalid regex format ' . $element, 'format', array('format' => $schema->format));
76367 }
76368 break;
76369
76370 case 'color':
76371 if (!$this->validateColor($element)) {
76372 $this->addError($path, 'Invalid color', 'format', array('format' => $schema->format));
76373 }
76374 break;
76375
76376 case 'style':
76377 if (!$this->validateStyle($element)) {
76378 $this->addError($path, 'Invalid style', 'format', array('format' => $schema->format));
76379 }
76380 break;
76381
76382 case 'phone':
76383 if (!$this->validatePhone($element)) {
76384 $this->addError($path, 'Invalid phone number', 'format', array('format' => $schema->format));
76385 }
76386 break;
76387
76388 case 'uri':
76389 if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
76390 $this->addError($path, 'Invalid URL format', 'format', array('format' => $schema->format));
76391 }
76392 break;
76393
76394 case 'uriref':
76395 case 'uri-reference':
76396 if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
76397
76398  
76399  
76400  if (substr($element, 0, 2) === '//') { 
76401  $validURL = filter_var('scheme:' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
76402 } elseif (substr($element, 0, 1) === '/') { 
76403  $validURL = filter_var('scheme://host' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
76404 } elseif (strlen($element)) { 
76405  $pathParts = explode('/', $element, 2);
76406 if (strpos($pathParts[0], ':') !== false) {
76407 $validURL = null;
76408 } else {
76409 $validURL = filter_var('scheme://host/' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
76410 }
76411 } else {
76412 $validURL = null;
76413 }
76414 if ($validURL === null) {
76415 $this->addError($path, 'Invalid URL format', 'format', array('format' => $schema->format));
76416 }
76417 }
76418 break;
76419
76420 case 'email':
76421 $filterFlags = FILTER_NULL_ON_FAILURE;
76422 if (defined('FILTER_FLAG_EMAIL_UNICODE')) {
76423
76424  $filterFlags |= constant('FILTER_FLAG_EMAIL_UNICODE'); 
76425  }
76426 if (null === filter_var($element, FILTER_VALIDATE_EMAIL, $filterFlags)) {
76427 $this->addError($path, 'Invalid email', 'format', array('format' => $schema->format));
76428 }
76429 break;
76430
76431 case 'ip-address':
76432 case 'ipv4':
76433 if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4)) {
76434 $this->addError($path, 'Invalid IP address', 'format', array('format' => $schema->format));
76435 }
76436 break;
76437
76438 case 'ipv6':
76439 if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV6)) {
76440 $this->addError($path, 'Invalid IP address', 'format', array('format' => $schema->format));
76441 }
76442 break;
76443
76444 case 'host-name':
76445 case 'hostname':
76446 if (!$this->validateHostname($element)) {
76447 $this->addError($path, 'Invalid hostname', 'format', array('format' => $schema->format));
76448 }
76449 break;
76450
76451 default:
76452
76453  
76454  
76455  
76456  
76457  
76458  break;
76459 }
76460 }
76461
76462 protected function validateDateTime($datetime, $format)
76463 {
76464 $dt = \DateTime::createFromFormat($format, $datetime);
76465
76466 if (!$dt) {
76467 return false;
76468 }
76469
76470 if ($datetime === $dt->format($format)) {
76471 return true;
76472 }
76473
76474
76475  
76476  
76477  
76478  if ((strpos('u', $format) !== -1) && (preg_match('/\.\d+Z$/', $datetime))) {
76479 return true;
76480 }
76481
76482 return false;
76483 }
76484
76485 protected function validateRegex($regex)
76486 {
76487 return false !== @preg_match('/' . $regex . '/u', '');
76488 }
76489
76490 protected function validateColor($color)
76491 {
76492 if (in_array(strtolower($color), array('aqua', 'black', 'blue', 'fuchsia',
76493 'gray', 'green', 'lime', 'maroon', 'navy', 'olive', 'orange', 'purple',
76494 'red', 'silver', 'teal', 'white', 'yellow'))) {
76495 return true;
76496 }
76497
76498 return preg_match('/^#([a-f0-9]{3}|[a-f0-9]{6})$/i', $color);
76499 }
76500
76501 protected function validateStyle($style)
76502 {
76503 $properties = explode(';', rtrim($style, ';'));
76504 $invalidEntries = preg_grep('/^\s*[-a-z]+\s*:\s*.+$/i', $properties, PREG_GREP_INVERT);
76505
76506 return empty($invalidEntries);
76507 }
76508
76509 protected function validatePhone($phone)
76510 {
76511 return preg_match('/^\+?(\(\d{3}\)|\d{3}) \d{3} \d{4}$/', $phone);
76512 }
76513
76514 protected function validateHostname($host)
76515 {
76516 $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';
76517
76518 return preg_match($hostnameRegex, $host);
76519 }
76520 }
76521 <?php
76522
76523
76524
76525
76526
76527
76528
76529
76530 namespace JsonSchema\Constraints;
76531
76532 use JsonSchema\Entity\JsonPointer;
76533
76534
76535
76536
76537
76538
76539
76540 class NumberConstraint extends Constraint
76541 {
76542
76543
76544
76545 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
76546 {
76547
76548  if (isset($schema->exclusiveMinimum)) {
76549 if (isset($schema->minimum)) {
76550 if ($schema->exclusiveMinimum && $element <= $schema->minimum) {
76551 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'exclusiveMinimum', array('minimum' => $schema->minimum));
76552 } elseif ($element < $schema->minimum) {
76553 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'minimum', array('minimum' => $schema->minimum));
76554 }
76555 } else {
76556 $this->addError($path, 'Use of exclusiveMinimum requires presence of minimum', 'missingMinimum');
76557 }
76558 } elseif (isset($schema->minimum) && $element < $schema->minimum) {
76559 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'minimum', array('minimum' => $schema->minimum));
76560 }
76561
76562
76563  if (isset($schema->exclusiveMaximum)) {
76564 if (isset($schema->maximum)) {
76565 if ($schema->exclusiveMaximum && $element >= $schema->maximum) {
76566 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'exclusiveMaximum', array('maximum' => $schema->maximum));
76567 } elseif ($element > $schema->maximum) {
76568 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'maximum', array('maximum' => $schema->maximum));
76569 }
76570 } else {
76571 $this->addError($path, 'Use of exclusiveMaximum requires presence of maximum', 'missingMaximum');
76572 }
76573 } elseif (isset($schema->maximum) && $element > $schema->maximum) {
76574 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'maximum', array('maximum' => $schema->maximum));
76575 }
76576
76577
76578  if (isset($schema->divisibleBy) && $this->fmod($element, $schema->divisibleBy) != 0) {
76579 $this->addError($path, 'Is not divisible by ' . $schema->divisibleBy, 'divisibleBy', array('divisibleBy' => $schema->divisibleBy));
76580 }
76581
76582
76583  if (isset($schema->multipleOf) && $this->fmod($element, $schema->multipleOf) != 0) {
76584 $this->addError($path, 'Must be a multiple of ' . $schema->multipleOf, 'multipleOf', array('multipleOf' => $schema->multipleOf));
76585 }
76586
76587 $this->checkFormat($element, $schema, $path, $i);
76588 }
76589
76590 private function fmod($number1, $number2)
76591 {
76592 $number1 = abs($number1);
76593 $modulus = fmod($number1, $number2);
76594 $precision = abs(0.0000000001);
76595 $diff = (float) ($modulus - $number2);
76596
76597 if (-$precision < $diff && $diff < $precision) {
76598 return 0.0;
76599 }
76600
76601 $decimals1 = mb_strpos($number1, '.') ? mb_strlen($number1) - mb_strpos($number1, '.') - 1 : 0;
76602 $decimals2 = mb_strpos($number2, '.') ? mb_strlen($number2) - mb_strpos($number2, '.') - 1 : 0;
76603
76604 return (float) round($modulus, max($decimals1, $decimals2));
76605 }
76606 }
76607 <?php
76608
76609
76610
76611
76612
76613
76614
76615
76616 namespace JsonSchema\Constraints;
76617
76618 use JsonSchema\Entity\JsonPointer;
76619
76620
76621
76622
76623
76624
76625
76626 class ObjectConstraint extends Constraint
76627 {
76628
76629
76630
76631 protected $appliedDefaults = array();
76632
76633
76634
76635
76636 public function check(&$element, $schema = null, JsonPointer $path = null, $properties = null,
76637 $additionalProp = null, $patternProperties = null, $appliedDefaults = array())
76638 {
76639 if ($element instanceof UndefinedConstraint) {
76640 return;
76641 }
76642
76643 $this->appliedDefaults = $appliedDefaults;
76644
76645 $matches = array();
76646 if ($patternProperties) {
76647
76648  $matches = $this->validatePatternProperties($element, $path, $patternProperties);
76649 }
76650
76651 if ($properties) {
76652
76653  $this->validateProperties($element, $properties, $path);
76654 }
76655
76656
76657  $this->validateElement($element, $matches, $schema, $path, $properties, $additionalProp);
76658 }
76659
76660 public function validatePatternProperties($element, JsonPointer $path = null, $patternProperties)
76661 {
76662 $try = array('/', '#', '+', '~', '%');
76663 $matches = array();
76664 foreach ($patternProperties as $pregex => $schema) {
76665 $delimiter = '/';
76666
76667  foreach ($try as $delimiter) {
76668 if (strpos($pregex, $delimiter) === false) { 
76669  break;
76670 }
76671 }
76672
76673
76674  if (@preg_match($delimiter . $pregex . $delimiter . 'u', '') === false) {
76675 $this->addError($path, 'The pattern "' . $pregex . '" is invalid', 'pregex', array('pregex' => $pregex));
76676 continue;
76677 }
76678 foreach ($element as $i => $value) {
76679 if (preg_match($delimiter . $pregex . $delimiter . 'u', $i)) {
76680 $matches[] = $i;
76681 $this->checkUndefined($value, $schema ?: new \stdClass(), $path, $i, in_array($i, $this->appliedDefaults));
76682 }
76683 }
76684 }
76685
76686 return $matches;
76687 }
76688
76689
76690
76691
76692
76693
76694
76695
76696
76697
76698
76699 public function validateElement($element, $matches, $schema = null, JsonPointer $path = null,
76700 $properties = null, $additionalProp = null)
76701 {
76702 $this->validateMinMaxConstraint($element, $schema, $path);
76703
76704 foreach ($element as $i => $value) {
76705 $definition = $this->getProperty($properties, $i);
76706
76707
76708  if (!in_array($i, $matches) && $additionalProp === false && $this->inlineSchemaProperty !== $i && !$definition) {
76709 $this->addError($path, 'The property ' . $i . ' is not defined and the definition does not allow additional properties', 'additionalProp');
76710 }
76711
76712
76713  if (!in_array($i, $matches) && $additionalProp && !$definition) {
76714 if ($additionalProp === true) {
76715 $this->checkUndefined($value, null, $path, $i, in_array($i, $this->appliedDefaults));
76716 } else {
76717 $this->checkUndefined($value, $additionalProp, $path, $i, in_array($i, $this->appliedDefaults));
76718 }
76719 }
76720
76721
76722  $require = $this->getProperty($definition, 'requires');
76723 if ($require && !$this->getProperty($element, $require)) {
76724 $this->addError($path, 'The presence of the property ' . $i . ' requires that ' . $require . ' also be present', 'requires');
76725 }
76726
76727 $property = $this->getProperty($element, $i, $this->factory->createInstanceFor('undefined'));
76728 if (is_object($property)) {
76729 $this->validateMinMaxConstraint(!($property instanceof UndefinedConstraint) ? $property : $element, $definition, $path);
76730 }
76731 }
76732 }
76733
76734
76735
76736
76737
76738
76739
76740
76741 public function validateProperties(&$element, $properties = null, JsonPointer $path = null)
76742 {
76743 $undefinedConstraint = $this->factory->createInstanceFor('undefined');
76744
76745 foreach ($properties as $i => $value) {
76746 $property = &$this->getProperty($element, $i, $undefinedConstraint);
76747 $definition = $this->getProperty($properties, $i);
76748
76749 if (is_object($definition)) {
76750
76751  $this->checkUndefined($property, $definition, $path, $i, in_array($i, $this->appliedDefaults));
76752 }
76753 }
76754 }
76755
76756
76757
76758
76759
76760
76761
76762
76763
76764
76765 protected function &getProperty(&$element, $property, $fallback = null)
76766 {
76767 if (is_array($element) && (isset($element[$property]) || array_key_exists($property, $element)) ) {
76768 return $element[$property];
76769 } elseif (is_object($element) && property_exists($element, $property)) {
76770 return $element->$property;
76771 }
76772
76773 return $fallback;
76774 }
76775
76776
76777
76778
76779
76780
76781
76782
76783 protected function validateMinMaxConstraint($element, $objectDefinition, JsonPointer $path = null)
76784 {
76785
76786  if (isset($objectDefinition->minProperties) && !is_object($objectDefinition->minProperties)) {
76787 if ($this->getTypeCheck()->propertyCount($element) < $objectDefinition->minProperties) {
76788 $this->addError($path, 'Must contain a minimum of ' . $objectDefinition->minProperties . ' properties', 'minProperties', array('minProperties' => $objectDefinition->minProperties));
76789 }
76790 }
76791
76792  if (isset($objectDefinition->maxProperties) && !is_object($objectDefinition->maxProperties)) {
76793 if ($this->getTypeCheck()->propertyCount($element) > $objectDefinition->maxProperties) {
76794 $this->addError($path, 'Must contain no more than ' . $objectDefinition->maxProperties . ' properties', 'maxProperties', array('maxProperties' => $objectDefinition->maxProperties));
76795 }
76796 }
76797 }
76798 }
76799 <?php
76800
76801
76802
76803
76804
76805
76806
76807
76808 namespace JsonSchema\Constraints;
76809
76810 use JsonSchema\Entity\JsonPointer;
76811 use JsonSchema\Exception\InvalidArgumentException;
76812 use JsonSchema\Exception\InvalidSchemaException;
76813 use JsonSchema\Exception\RuntimeException;
76814 use JsonSchema\SchemaStorage;
76815 use JsonSchema\Validator;
76816
76817
76818
76819
76820
76821
76822
76823 class SchemaConstraint extends Constraint
76824 {
76825 const DEFAULT_SCHEMA_SPEC = 'http://json-schema.org/draft-04/schema#';
76826
76827
76828
76829
76830 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
76831 {
76832 if ($schema !== null) {
76833
76834  $validationSchema = $schema;
76835 } elseif ($this->getTypeCheck()->propertyExists($element, $this->inlineSchemaProperty)) {
76836
76837  $validationSchema = $this->getTypeCheck()->propertyGet($element, $this->inlineSchemaProperty);
76838 } else {
76839 throw new InvalidArgumentException('no schema found to verify against');
76840 }
76841
76842
76843  if (is_array($validationSchema)) {
76844 $validationSchema = BaseConstraint::arrayToObjectRecursive($validationSchema);
76845 }
76846
76847
76848  
76849  if ($this->factory->getConfig(self::CHECK_MODE_VALIDATE_SCHEMA)) {
76850 if (!$this->getTypeCheck()->isObject($validationSchema)) {
76851 throw new RuntimeException('Cannot validate the schema of a non-object');
76852 }
76853 if ($this->getTypeCheck()->propertyExists($validationSchema, '$schema')) {
76854 $schemaSpec = $this->getTypeCheck()->propertyGet($validationSchema, '$schema');
76855 } else {
76856 $schemaSpec = self::DEFAULT_SCHEMA_SPEC;
76857 }
76858
76859
76860  $schemaStorage = $this->factory->getSchemaStorage();
76861 if (!$this->getTypeCheck()->isObject($schemaSpec)) {
76862 $schemaSpec = $schemaStorage->getSchema($schemaSpec);
76863 }
76864
76865
76866  $initialErrorCount = $this->numErrors();
76867 $initialConfig = $this->factory->getConfig();
76868 $initialContext = $this->factory->getErrorContext();
76869 $this->factory->removeConfig(self::CHECK_MODE_VALIDATE_SCHEMA | self::CHECK_MODE_APPLY_DEFAULTS);
76870 $this->factory->addConfig(self::CHECK_MODE_TYPE_CAST);
76871 $this->factory->setErrorContext(Validator::ERROR_SCHEMA_VALIDATION);
76872
76873
76874  try {
76875 $this->check($validationSchema, $schemaSpec);
76876 } catch (\Exception $e) {
76877 if ($this->factory->getConfig(self::CHECK_MODE_EXCEPTIONS)) {
76878 throw new InvalidSchemaException('Schema did not pass validation', 0, $e);
76879 }
76880 }
76881 if ($this->numErrors() > $initialErrorCount) {
76882 $this->addError($path, 'Schema is not valid', 'schema');
76883 }
76884
76885
76886  $this->factory->setConfig($initialConfig);
76887 $this->factory->setErrorContext($initialContext);
76888 }
76889
76890
76891  $this->checkUndefined($element, $validationSchema, $path, $i);
76892 }
76893 }
76894 <?php
76895
76896
76897
76898
76899
76900
76901
76902
76903 namespace JsonSchema\Constraints;
76904
76905 use JsonSchema\Entity\JsonPointer;
76906
76907
76908
76909
76910
76911
76912
76913 class StringConstraint extends Constraint
76914 {
76915
76916
76917
76918 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
76919 {
76920
76921  if (isset($schema->maxLength) && $this->strlen($element) > $schema->maxLength) {
76922 $this->addError($path, 'Must be at most ' . $schema->maxLength . ' characters long', 'maxLength', array(
76923 'maxLength' => $schema->maxLength,
76924 ));
76925 }
76926
76927
76928  if (isset($schema->minLength) && $this->strlen($element) < $schema->minLength) {
76929 $this->addError($path, 'Must be at least ' . $schema->minLength . ' characters long', 'minLength', array(
76930 'minLength' => $schema->minLength,
76931 ));
76932 }
76933
76934
76935  if (isset($schema->pattern) && !preg_match('#' . str_replace('#', '\\#', $schema->pattern) . '#u', $element)) {
76936 $this->addError($path, 'Does not match the regex pattern ' . $schema->pattern, 'pattern', array(
76937 'pattern' => $schema->pattern,
76938 ));
76939 }
76940
76941 $this->checkFormat($element, $schema, $path, $i);
76942 }
76943
76944 private function strlen($string)
76945 {
76946 if (extension_loaded('mbstring')) {
76947 return mb_strlen($string, mb_detect_encoding($string));
76948 }
76949
76950
76951  return strlen($string); 
76952  }
76953 }
76954 <?php
76955
76956 namespace JsonSchema\Constraints\TypeCheck;
76957
76958 class LooseTypeCheck implements TypeCheckInterface
76959 {
76960 public static function isObject($value)
76961 {
76962 return
76963 is_object($value) ||
76964 (is_array($value) && (count($value) == 0 || self::isAssociativeArray($value)));
76965 }
76966
76967 public static function isArray($value)
76968 {
76969 return
76970 is_array($value) &&
76971 (count($value) == 0 || !self::isAssociativeArray($value));
76972 }
76973
76974 public static function propertyGet($value, $property)
76975 {
76976 if (is_object($value)) {
76977 return $value->{$property};
76978 }
76979
76980 return $value[$property];
76981 }
76982
76983 public static function propertySet(&$value, $property, $data)
76984 {
76985 if (is_object($value)) {
76986 $value->{$property} = $data;
76987 } else {
76988 $value[$property] = $data;
76989 }
76990 }
76991
76992 public static function propertyExists($value, $property)
76993 {
76994 if (is_object($value)) {
76995 return property_exists($value, $property);
76996 }
76997
76998 return array_key_exists($property, $value);
76999 }
77000
77001 public static function propertyCount($value)
77002 {
77003 if (is_object($value)) {
77004 return count(get_object_vars($value));
77005 }
77006
77007 return count($value);
77008 }
77009
77010
77011
77012
77013
77014
77015
77016
77017 private static function isAssociativeArray($arr)
77018 {
77019 return array_keys($arr) !== range(0, count($arr) - 1);
77020 }
77021 }
77022 <?php
77023
77024 namespace JsonSchema\Constraints\TypeCheck;
77025
77026 class StrictTypeCheck implements TypeCheckInterface
77027 {
77028 public static function isObject($value)
77029 {
77030 return is_object($value);
77031 }
77032
77033 public static function isArray($value)
77034 {
77035 return is_array($value);
77036 }
77037
77038 public static function propertyGet($value, $property)
77039 {
77040 return $value->{$property};
77041 }
77042
77043 public static function propertySet(&$value, $property, $data)
77044 {
77045 $value->{$property} = $data;
77046 }
77047
77048 public static function propertyExists($value, $property)
77049 {
77050 return property_exists($value, $property);
77051 }
77052
77053 public static function propertyCount($value)
77054 {
77055 return count(get_object_vars($value));
77056 }
77057 }
77058 <?php
77059
77060 namespace JsonSchema\Constraints\TypeCheck;
77061
77062 interface TypeCheckInterface
77063 {
77064 public static function isObject($value);
77065
77066 public static function isArray($value);
77067
77068 public static function propertyGet($value, $property);
77069
77070 public static function propertySet(&$value, $property, $data);
77071
77072 public static function propertyExists($value, $property);
77073
77074 public static function propertyCount($value);
77075 }
77076 <?php
77077
77078
77079
77080
77081
77082
77083
77084
77085 namespace JsonSchema\Constraints;
77086
77087 use JsonSchema\Entity\JsonPointer;
77088 use JsonSchema\Exception\InvalidArgumentException;
77089 use UnexpectedValueException as StandardUnexpectedValueException;
77090
77091
77092
77093
77094
77095
77096
77097 class TypeConstraint extends Constraint
77098 {
77099
77100
77101
77102 public static $wording = array(
77103 'integer' => 'an integer',
77104 'number' => 'a number',
77105 'boolean' => 'a boolean',
77106 'object' => 'an object',
77107 'array' => 'an array',
77108 'string' => 'a string',
77109 'null' => 'a null',
77110 'any' => null, 
77111  0 => null, 
77112  );
77113
77114
77115
77116
77117 public function check(&$value = null, $schema = null, JsonPointer $path = null, $i = null)
77118 {
77119 $type = isset($schema->type) ? $schema->type : null;
77120 $isValid = false;
77121 $wording = array();
77122
77123 if (is_array($type)) {
77124 $this->validateTypesArray($value, $type, $wording, $isValid, $path);
77125 } elseif (is_object($type)) {
77126 $this->checkUndefined($value, $type, $path);
77127
77128 return;
77129 } else {
77130 $isValid = $this->validateType($value, $type);
77131 }
77132
77133 if ($isValid === false) {
77134 if (!is_array($type)) {
77135 $this->validateTypeNameWording($type);
77136 $wording[] = self::$wording[$type];
77137 }
77138 $this->addError($path, ucwords(gettype($value)) . ' value found, but ' .
77139 $this->implodeWith($wording, ', ', 'or') . ' is required', 'type');
77140 }
77141 }
77142
77143
77144
77145
77146
77147
77148
77149
77150
77151
77152
77153
77154 protected function validateTypesArray(&$value, array $type, &$validTypesWording, &$isValid, $path)
77155 {
77156 foreach ($type as $tp) {
77157
77158  
77159  if (is_object($tp)) {
77160 if (!$isValid) {
77161 $validator = $this->factory->createInstanceFor('type');
77162 $subSchema = new \stdClass();
77163 $subSchema->type = $tp;
77164 $validator->check($value, $subSchema, $path, null);
77165 $error = $validator->getErrors();
77166 $isValid = !(bool) $error;
77167 $validTypesWording[] = self::$wording['object'];
77168 }
77169 } else {
77170 $this->validateTypeNameWording($tp);
77171 $validTypesWording[] = self::$wording[$tp];
77172 if (!$isValid) {
77173 $isValid = $this->validateType($value, $tp);
77174 }
77175 }
77176 }
77177 }
77178
77179
77180
77181
77182
77183
77184
77185
77186
77187
77188
77189
77190 protected function implodeWith(array $elements, $delimiter = ', ', $listEnd = false)
77191 {
77192 if ($listEnd === false || !isset($elements[1])) {
77193 return implode($delimiter, $elements);
77194 }
77195 $lastElement = array_slice($elements, -1);
77196 $firsElements = join($delimiter, array_slice($elements, 0, -1));
77197 $implodedElements = array_merge(array($firsElements), $lastElement);
77198
77199 return join(" $listEnd ", $implodedElements);
77200 }
77201
77202
77203
77204
77205
77206
77207
77208
77209
77210 protected function validateTypeNameWording($type)
77211 {
77212 if (!isset(self::$wording[$type])) {
77213 throw new StandardUnexpectedValueException(
77214 sprintf(
77215 'No wording for %s available, expected wordings are: [%s]',
77216 var_export($type, true),
77217 implode(', ', array_filter(self::$wording)))
77218 );
77219 }
77220 }
77221
77222
77223
77224
77225
77226
77227
77228
77229
77230
77231
77232 protected function validateType(&$value, $type)
77233 {
77234
77235  if (!$type) {
77236 return true;
77237 }
77238
77239 if ('any' === $type) {
77240 return true;
77241 }
77242
77243 if ('object' === $type) {
77244 return $this->getTypeCheck()->isObject($value);
77245 }
77246
77247 if ('array' === $type) {
77248 return $this->getTypeCheck()->isArray($value);
77249 }
77250
77251 $coerce = $this->factory->getConfig(Constraint::CHECK_MODE_COERCE_TYPES);
77252
77253 if ('integer' === $type) {
77254 if ($coerce) {
77255 $value = $this->toInteger($value);
77256 }
77257
77258 return is_int($value);
77259 }
77260
77261 if ('number' === $type) {
77262 if ($coerce) {
77263 $value = $this->toNumber($value);
77264 }
77265
77266 return is_numeric($value) && !is_string($value);
77267 }
77268
77269 if ('boolean' === $type) {
77270 if ($coerce) {
77271 $value = $this->toBoolean($value);
77272 }
77273
77274 return is_bool($value);
77275 }
77276
77277 if ('string' === $type) {
77278 return is_string($value);
77279 }
77280
77281 if ('email' === $type) {
77282 return is_string($value);
77283 }
77284
77285 if ('null' === $type) {
77286 return is_null($value);
77287 }
77288
77289 throw new InvalidArgumentException((is_object($value) ? 'object' : $value) . ' is an invalid type for ' . $type);
77290 }
77291
77292
77293
77294
77295
77296
77297
77298
77299 protected function toBoolean($value)
77300 {
77301 if ($value === 'true') {
77302 return true;
77303 }
77304
77305 if ($value === 'false') {
77306 return false;
77307 }
77308
77309 return $value;
77310 }
77311
77312
77313
77314
77315
77316
77317
77318
77319 protected function toNumber($value)
77320 {
77321 if (is_numeric($value)) {
77322 return $value + 0; 
77323  }
77324
77325 return $value;
77326 }
77327
77328 protected function toInteger($value)
77329 {
77330 if (is_numeric($value) && (int) $value == $value) {
77331 return (int) $value; 
77332  }
77333
77334 return $value;
77335 }
77336 }
77337 <?php
77338
77339
77340
77341
77342
77343
77344
77345
77346 namespace JsonSchema\Constraints;
77347
77348 use JsonSchema\Constraints\TypeCheck\LooseTypeCheck;
77349 use JsonSchema\Entity\JsonPointer;
77350 use JsonSchema\Exception\ValidationException;
77351 use JsonSchema\Uri\UriResolver;
77352
77353
77354
77355
77356
77357
77358
77359 class UndefinedConstraint extends Constraint
77360 {
77361
77362
77363
77364 protected $appliedDefaults = array();
77365
77366
77367
77368
77369 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null, $fromDefault = false)
77370 {
77371 if (is_null($schema) || !is_object($schema)) {
77372 return;
77373 }
77374
77375 $path = $this->incrementPath($path ?: new JsonPointer(''), $i);
77376 if ($fromDefault) {
77377 $path->setFromDefault();
77378 }
77379
77380
77381  $this->validateCommonProperties($value, $schema, $path, $i);
77382
77383
77384  $this->validateOfProperties($value, $schema, $path, '');
77385
77386
77387  $this->validateTypes($value, $schema, $path, $i);
77388 }
77389
77390
77391
77392
77393
77394
77395
77396
77397
77398 public function validateTypes(&$value, $schema = null, JsonPointer $path, $i = null)
77399 {
77400
77401  if ($this->getTypeCheck()->isArray($value)) {
77402 $this->checkArray($value, $schema, $path, $i);
77403 }
77404
77405
77406  if (LooseTypeCheck::isObject($value)) { 
77407  
77408  
77409  $this->checkObject(
77410 $value,
77411 $schema,
77412 $path,
77413 isset($schema->properties) ? $schema->properties : null,
77414 isset($schema->additionalProperties) ? $schema->additionalProperties : null,
77415 isset($schema->patternProperties) ? $schema->patternProperties : null,
77416 $this->appliedDefaults
77417 );
77418 }
77419
77420
77421  if (is_string($value)) {
77422 $this->checkString($value, $schema, $path, $i);
77423 }
77424
77425
77426  if (is_numeric($value)) {
77427 $this->checkNumber($value, $schema, $path, $i);
77428 }
77429
77430
77431  if (isset($schema->enum)) {
77432 $this->checkEnum($value, $schema, $path, $i);
77433 }
77434 }
77435
77436
77437
77438
77439
77440
77441
77442
77443
77444 protected function validateCommonProperties(&$value, $schema = null, JsonPointer $path, $i = '')
77445 {
77446
77447  if (isset($schema->extends)) {
77448 if (is_string($schema->extends)) {
77449 $schema->extends = $this->validateUri($schema, $schema->extends);
77450 }
77451 if (is_array($schema->extends)) {
77452 foreach ($schema->extends as $extends) {
77453 $this->checkUndefined($value, $extends, $path, $i);
77454 }
77455 } else {
77456 $this->checkUndefined($value, $schema->extends, $path, $i);
77457 }
77458 }
77459
77460
77461  if (!$path->fromDefault()) {
77462 $this->applyDefaultValues($value, $schema, $path);
77463 }
77464
77465
77466  if ($this->getTypeCheck()->isObject($value)) {
77467 if (!($value instanceof self) && isset($schema->required) && is_array($schema->required)) {
77468
77469  foreach ($schema->required as $required) {
77470 if (!$this->getTypeCheck()->propertyExists($value, $required)) {
77471 $this->addError(
77472 $this->incrementPath($path ?: new JsonPointer(''), $required),
77473 'The property ' . $required . ' is required',
77474 'required'
77475 );
77476 }
77477 }
77478 } elseif (isset($schema->required) && !is_array($schema->required)) {
77479
77480  if ($schema->required && $value instanceof self) {
77481 $this->addError($path, 'Is missing and it is required', 'required');
77482 }
77483 }
77484 }
77485
77486
77487  if (!($value instanceof self)) {
77488 $this->checkType($value, $schema, $path, $i);
77489 }
77490
77491
77492  if (isset($schema->disallow)) {
77493 $initErrors = $this->getErrors();
77494
77495 $typeSchema = new \stdClass();
77496 $typeSchema->type = $schema->disallow;
77497 $this->checkType($value, $typeSchema, $path);
77498
77499
77500  if (count($this->getErrors()) == count($initErrors)) {
77501 $this->addError($path, 'Disallowed value was matched', 'disallow');
77502 } else {
77503 $this->errors = $initErrors;
77504 }
77505 }
77506
77507 if (isset($schema->not)) {
77508 $initErrors = $this->getErrors();
77509 $this->checkUndefined($value, $schema->not, $path, $i);
77510
77511
77512  if (count($this->getErrors()) == count($initErrors)) {
77513 $this->addError($path, 'Matched a schema which it should not', 'not');
77514 } else {
77515 $this->errors = $initErrors;
77516 }
77517 }
77518
77519
77520  if (isset($schema->dependencies) && $this->getTypeCheck()->isObject($value)) {
77521 $this->validateDependencies($value, $schema->dependencies, $path);
77522 }
77523 }
77524
77525
77526
77527
77528
77529
77530
77531
77532
77533
77534 private function shouldApplyDefaultValue($requiredOnly, $schema, $name = null, $parentSchema = null)
77535 {
77536
77537  if (!$requiredOnly) {
77538 return true;
77539 }
77540
77541  if (
77542 $name !== null
77543 && isset($parentSchema->required)
77544 && is_array($parentSchema->required)
77545 && in_array($name, $parentSchema->required)
77546 ) {
77547 return true;
77548 }
77549
77550  if (isset($schema->required) && !is_array($schema->required) && $schema->required) {
77551 return true;
77552 }
77553
77554  return false;
77555 }
77556
77557
77558
77559
77560
77561
77562
77563
77564 protected function applyDefaultValues(&$value, $schema, $path)
77565 {
77566
77567  if (!$this->factory->getConfig(self::CHECK_MODE_APPLY_DEFAULTS)) {
77568 return;
77569 }
77570
77571
77572  $requiredOnly = $this->factory->getConfig(self::CHECK_MODE_ONLY_REQUIRED_DEFAULTS);
77573 if (isset($schema->properties) && LooseTypeCheck::isObject($value)) {
77574
77575  foreach ($schema->properties as $currentProperty => $propertyDefinition) {
77576 if (
77577 !LooseTypeCheck::propertyExists($value, $currentProperty)
77578 && property_exists($propertyDefinition, 'default')
77579 && $this->shouldApplyDefaultValue($requiredOnly, $propertyDefinition, $currentProperty, $schema)
77580 ) {
77581
77582  if (is_object($propertyDefinition->default)) {
77583 LooseTypeCheck::propertySet($value, $currentProperty, clone $propertyDefinition->default);
77584 } else {
77585 LooseTypeCheck::propertySet($value, $currentProperty, $propertyDefinition->default);
77586 }
77587 $this->appliedDefaults[] = $currentProperty;
77588 }
77589 }
77590 } elseif (isset($schema->items) && LooseTypeCheck::isArray($value)) {
77591 $items = array();
77592 if (LooseTypeCheck::isArray($schema->items)) {
77593 $items = $schema->items;
77594 } elseif (isset($schema->minItems) && count($value) < $schema->minItems) {
77595 $items = array_fill(count($value), $schema->minItems - count($value), $schema->items);
77596 }
77597
77598  foreach ($items as $currentItem => $itemDefinition) {
77599 if (
77600 !array_key_exists($currentItem, $value)
77601 && property_exists($itemDefinition, 'default')
77602 && $this->shouldApplyDefaultValue($requiredOnly, $itemDefinition)) {
77603 if (is_object($itemDefinition->default)) {
77604 $value[$currentItem] = clone $itemDefinition->default;
77605 } else {
77606 $value[$currentItem] = $itemDefinition->default;
77607 }
77608 }
77609 $path->setFromDefault();
77610 }
77611 } elseif (
77612 $value instanceof self
77613 && property_exists($schema, 'default')
77614 && $this->shouldApplyDefaultValue($requiredOnly, $schema)) {
77615
77616  $value = is_object($schema->default) ? clone $schema->default : $schema->default;
77617 $path->setFromDefault();
77618 }
77619 }
77620
77621
77622
77623
77624
77625
77626
77627
77628
77629 protected function validateOfProperties(&$value, $schema, JsonPointer $path, $i = '')
77630 {
77631
77632  if ($value instanceof self) {
77633 return;
77634 }
77635
77636 if (isset($schema->allOf)) {
77637 $isValid = true;
77638 foreach ($schema->allOf as $allOf) {
77639 $initErrors = $this->getErrors();
77640 $this->checkUndefined($value, $allOf, $path, $i);
77641 $isValid = $isValid && (count($this->getErrors()) == count($initErrors));
77642 }
77643 if (!$isValid) {
77644 $this->addError($path, 'Failed to match all schemas', 'allOf');
77645 }
77646 }
77647
77648 if (isset($schema->anyOf)) {
77649 $isValid = false;
77650 $startErrors = $this->getErrors();
77651 $caughtException = null;
77652 foreach ($schema->anyOf as $anyOf) {
77653 $initErrors = $this->getErrors();
77654 try {
77655 $this->checkUndefined($value, $anyOf, $path, $i);
77656 if ($isValid = (count($this->getErrors()) == count($initErrors))) {
77657 break;
77658 }
77659 } catch (ValidationException $e) {
77660 $isValid = false;
77661 }
77662 }
77663 if (!$isValid) {
77664 $this->addError($path, 'Failed to match at least one schema', 'anyOf');
77665 } else {
77666 $this->errors = $startErrors;
77667 }
77668 }
77669
77670 if (isset($schema->oneOf)) {
77671 $allErrors = array();
77672 $matchedSchemas = 0;
77673 $startErrors = $this->getErrors();
77674 foreach ($schema->oneOf as $oneOf) {
77675 try {
77676 $this->errors = array();
77677 $this->checkUndefined($value, $oneOf, $path, $i);
77678 if (count($this->getErrors()) == 0) {
77679 $matchedSchemas++;
77680 }
77681 $allErrors = array_merge($allErrors, array_values($this->getErrors()));
77682 } catch (ValidationException $e) {
77683
77684  
77685  }
77686 }
77687 if ($matchedSchemas !== 1) {
77688 $this->addErrors(array_merge($allErrors, $startErrors));
77689 $this->addError($path, 'Failed to match exactly one schema', 'oneOf');
77690 } else {
77691 $this->errors = $startErrors;
77692 }
77693 }
77694 }
77695
77696
77697
77698
77699
77700
77701
77702
77703
77704 protected function validateDependencies($value, $dependencies, JsonPointer $path, $i = '')
77705 {
77706 foreach ($dependencies as $key => $dependency) {
77707 if ($this->getTypeCheck()->propertyExists($value, $key)) {
77708 if (is_string($dependency)) {
77709
77710  if (!$this->getTypeCheck()->propertyExists($value, $dependency)) {
77711 $this->addError($path, "$key depends on $dependency and $dependency is missing", 'dependencies');
77712 }
77713 } elseif (is_array($dependency)) {
77714
77715  foreach ($dependency as $d) {
77716 if (!$this->getTypeCheck()->propertyExists($value, $d)) {
77717 $this->addError($path, "$key depends on $d and $d is missing", 'dependencies');
77718 }
77719 }
77720 } elseif (is_object($dependency)) {
77721
77722  $this->checkUndefined($value, $dependency, $path, $i);
77723 }
77724 }
77725 }
77726 }
77727
77728 protected function validateUri($schema, $schemaUri = null)
77729 {
77730 $resolver = new UriResolver();
77731 $retriever = $this->factory->getUriRetriever();
77732
77733 $jsonSchema = null;
77734 if ($resolver->isValid($schemaUri)) {
77735 $schemaId = property_exists($schema, 'id') ? $schema->id : null;
77736 $jsonSchema = $retriever->retrieve($schemaId, $schemaUri);
77737 }
77738
77739 return $jsonSchema;
77740 }
77741 }
77742 <?php
77743
77744
77745
77746
77747
77748
77749
77750
77751 namespace JsonSchema\Entity;
77752
77753 use JsonSchema\Exception\InvalidArgumentException;
77754
77755
77756
77757
77758
77759
77760 class JsonPointer
77761 {
77762
77763 private $filename;
77764
77765
77766 private $propertyPaths = array();
77767
77768
77769
77770
77771 private $fromDefault = false;
77772
77773
77774
77775
77776
77777
77778 public function __construct($value)
77779 {
77780 if (!is_string($value)) {
77781 throw new InvalidArgumentException('Ref value must be a string');
77782 }
77783
77784 $splitRef = explode('#', $value, 2);
77785 $this->filename = $splitRef[0];
77786 if (array_key_exists(1, $splitRef)) {
77787 $this->propertyPaths = $this->decodePropertyPaths($splitRef[1]);
77788 }
77789 }
77790
77791
77792
77793
77794
77795
77796 private function decodePropertyPaths($propertyPathString)
77797 {
77798 $paths = array();
77799 foreach (explode('/', trim($propertyPathString, '/')) as $path) {
77800 $path = $this->decodePath($path);
77801 if (is_string($path) && '' !== $path) {
77802 $paths[] = $path;
77803 }
77804 }
77805
77806 return $paths;
77807 }
77808
77809
77810
77811
77812 private function encodePropertyPaths()
77813 {
77814 return array_map(
77815 array($this, 'encodePath'),
77816 $this->getPropertyPaths()
77817 );
77818 }
77819
77820
77821
77822
77823
77824
77825 private function decodePath($path)
77826 {
77827 return strtr($path, array('~1' => '/', '~0' => '~', '%25' => '%'));
77828 }
77829
77830
77831
77832
77833
77834
77835 private function encodePath($path)
77836 {
77837 return strtr($path, array('/' => '~1', '~' => '~0', '%' => '%25'));
77838 }
77839
77840
77841
77842
77843 public function getFilename()
77844 {
77845 return $this->filename;
77846 }
77847
77848
77849
77850
77851 public function getPropertyPaths()
77852 {
77853 return $this->propertyPaths;
77854 }
77855
77856
77857
77858
77859
77860
77861 public function withPropertyPaths(array $propertyPaths)
77862 {
77863 $new = clone $this;
77864 $new->propertyPaths = $propertyPaths;
77865
77866 return $new;
77867 }
77868
77869
77870
77871
77872 public function getPropertyPathAsString()
77873 {
77874 return rtrim('#/' . implode('/', $this->encodePropertyPaths()), '/');
77875 }
77876
77877
77878
77879
77880 public function __toString()
77881 {
77882 return $this->getFilename() . $this->getPropertyPathAsString();
77883 }
77884
77885
77886
77887
77888 public function setFromDefault()
77889 {
77890 $this->fromDefault = true;
77891 }
77892
77893
77894
77895
77896
77897
77898 public function fromDefault()
77899 {
77900 return $this->fromDefault;
77901 }
77902 }
77903 <?php
77904
77905 namespace JsonSchema\Exception;
77906
77907 interface ExceptionInterface
77908 {
77909 }
77910 <?php
77911
77912
77913
77914
77915
77916
77917
77918
77919 namespace JsonSchema\Exception;
77920
77921
77922
77923
77924 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
77925 {
77926 }
77927 <?php
77928
77929
77930
77931
77932
77933
77934
77935
77936 namespace JsonSchema\Exception;
77937
77938
77939
77940
77941 class InvalidConfigException extends RuntimeException
77942 {
77943 }
77944 <?php
77945
77946
77947
77948
77949
77950
77951
77952
77953 namespace JsonSchema\Exception;
77954
77955
77956
77957
77958 class InvalidSchemaException extends RuntimeException
77959 {
77960 }
77961 <?php
77962
77963
77964
77965
77966
77967
77968
77969
77970 namespace JsonSchema\Exception;
77971
77972
77973
77974
77975 class InvalidSchemaMediaTypeException extends RuntimeException
77976 {
77977 }
77978 <?php
77979
77980
77981
77982
77983
77984
77985
77986
77987 namespace JsonSchema\Exception;
77988
77989
77990
77991
77992 class InvalidSourceUriException extends InvalidArgumentException
77993 {
77994 }
77995 <?php
77996
77997
77998
77999
78000
78001
78002
78003
78004 namespace JsonSchema\Exception;
78005
78006
78007
78008
78009 class JsonDecodingException extends RuntimeException
78010 {
78011 public function __construct($code = JSON_ERROR_NONE, \Exception $previous = null)
78012 {
78013 switch ($code) {
78014 case JSON_ERROR_DEPTH:
78015 $message = 'The maximum stack depth has been exceeded';
78016 break;
78017 case JSON_ERROR_STATE_MISMATCH:
78018 $message = 'Invalid or malformed JSON';
78019 break;
78020 case JSON_ERROR_CTRL_CHAR:
78021 $message = 'Control character error, possibly incorrectly encoded';
78022 break;
78023 case JSON_ERROR_UTF8:
78024 $message = 'Malformed UTF-8 characters, possibly incorrectly encoded';
78025 break;
78026 case JSON_ERROR_SYNTAX:
78027 $message = 'JSON syntax is malformed';
78028 break;
78029 default:
78030 $message = 'Syntax error';
78031 }
78032 parent::__construct($message, $code, $previous);
78033 }
78034 }
78035 <?php
78036
78037
78038
78039
78040
78041
78042
78043
78044 namespace JsonSchema\Exception;
78045
78046
78047
78048
78049 class ResourceNotFoundException extends RuntimeException
78050 {
78051 }
78052 <?php
78053
78054
78055
78056
78057
78058
78059
78060
78061 namespace JsonSchema\Exception;
78062
78063
78064
78065
78066 class RuntimeException extends \RuntimeException implements ExceptionInterface
78067 {
78068 }
78069 <?php
78070
78071
78072
78073
78074
78075
78076
78077
78078 namespace JsonSchema\Exception;
78079
78080
78081
78082
78083
78084
78085 class UnresolvableJsonPointerException extends InvalidArgumentException
78086 {
78087 }
78088 <?php
78089
78090
78091
78092
78093
78094
78095
78096
78097 namespace JsonSchema\Exception;
78098
78099
78100
78101
78102 class UriResolverException extends RuntimeException
78103 {
78104 }
78105 <?php
78106
78107
78108
78109
78110
78111
78112
78113
78114 namespace JsonSchema\Exception;
78115
78116 class ValidationException extends RuntimeException
78117 {
78118 }
78119 <?php
78120
78121
78122
78123
78124
78125
78126
78127
78128 namespace JsonSchema\Iterator;
78129
78130
78131
78132
78133
78134
78135 class ObjectIterator implements \Iterator, \Countable
78136 {
78137
78138 private $object;
78139
78140
78141 private $position = 0;
78142
78143
78144 private $data = array();
78145
78146
78147 private $initialized = false;
78148
78149
78150
78151
78152 public function __construct($object)
78153 {
78154 $this->object = $object;
78155 }
78156
78157
78158
78159
78160 public function current()
78161 {
78162 $this->initialize();
78163
78164 return $this->data[$this->position];
78165 }
78166
78167
78168
78169
78170 public function next()
78171 {
78172 $this->initialize();
78173 $this->position++;
78174 }
78175
78176
78177
78178
78179 public function key()
78180 {
78181 $this->initialize();
78182
78183 return $this->position;
78184 }
78185
78186
78187
78188
78189 public function valid()
78190 {
78191 $this->initialize();
78192
78193 return isset($this->data[$this->position]);
78194 }
78195
78196
78197
78198
78199 public function rewind()
78200 {
78201 $this->initialize();
78202 $this->position = 0;
78203 }
78204
78205
78206
78207
78208 public function count()
78209 {
78210 $this->initialize();
78211
78212 return count($this->data);
78213 }
78214
78215
78216
78217
78218 private function initialize()
78219 {
78220 if (!$this->initialized) {
78221 $this->data = $this->buildDataFromObject($this->object);
78222 $this->initialized = true;
78223 }
78224 }
78225
78226
78227
78228
78229
78230
78231 private function buildDataFromObject($object)
78232 {
78233 $result = array();
78234
78235 $stack = new \SplStack();
78236 $stack->push($object);
78237
78238 while (!$stack->isEmpty()) {
78239 $current = $stack->pop();
78240 if (is_object($current)) {
78241 array_push($result, $current);
78242 }
78243
78244 foreach ($this->getDataFromItem($current) as $propertyName => $propertyValue) {
78245 if (is_object($propertyValue) || is_array($propertyValue)) {
78246 $stack->push($propertyValue);
78247 }
78248 }
78249 }
78250
78251 return $result;
78252 }
78253
78254
78255
78256
78257
78258
78259 private function getDataFromItem($item)
78260 {
78261 if (!is_object($item) && !is_array($item)) {
78262 return array();
78263 }
78264
78265 return is_object($item) ? get_object_vars($item) : $item;
78266 }
78267 }
78268 <?php
78269
78270 namespace JsonSchema;
78271
78272 class Rfc3339
78273 {
78274 const REGEX = '/^(\d{4}-\d{2}-\d{2}[T ]{1}\d{2}:\d{2}:\d{2})(\.\d+)?(Z|([+-]\d{2}):?(\d{2}))$/';
78275
78276
78277
78278
78279
78280
78281
78282
78283 public static function createFromString($string)
78284 {
78285 if (!preg_match(self::REGEX, strtoupper($string), $matches)) {
78286 return null;
78287 }
78288
78289 $dateAndTime = $matches[1];
78290 $microseconds = $matches[2] ?: '.000000';
78291 $timeZone = 'Z' !== $matches[3] ? $matches[4] . ':' . $matches[5] : '+00:00';
78292 $dateFormat = strpos($dateAndTime, 'T') === false ? 'Y-m-d H:i:s.uP' : 'Y-m-d\TH:i:s.uP';
78293 $dateTime = \DateTime::createFromFormat($dateFormat, $dateAndTime . $microseconds . $timeZone, new \DateTimeZone('UTC'));
78294
78295 return $dateTime ?: null;
78296 }
78297 }
78298 <?php
78299
78300 namespace JsonSchema;
78301
78302 use JsonSchema\Constraints\BaseConstraint;
78303 use JsonSchema\Entity\JsonPointer;
78304 use JsonSchema\Exception\UnresolvableJsonPointerException;
78305 use JsonSchema\Iterator\ObjectIterator;
78306 use JsonSchema\Uri\UriResolver;
78307 use JsonSchema\Uri\UriRetriever;
78308
78309 class SchemaStorage implements SchemaStorageInterface
78310 {
78311 const INTERNAL_PROVIDED_SCHEMA_URI = 'internal://provided-schema';
78312
78313 protected $uriRetriever;
78314 protected $uriResolver;
78315 protected $schemas = array();
78316
78317 public function __construct(
78318 UriRetrieverInterface $uriRetriever = null,
78319 UriResolverInterface $uriResolver = null
78320 ) {
78321 $this->uriRetriever = $uriRetriever ?: new UriRetriever();
78322 $this->uriResolver = $uriResolver ?: new UriResolver();
78323 }
78324
78325
78326
78327
78328 public function getUriRetriever()
78329 {
78330 return $this->uriRetriever;
78331 }
78332
78333
78334
78335
78336 public function getUriResolver()
78337 {
78338 return $this->uriResolver;
78339 }
78340
78341
78342
78343
78344 public function addSchema($id, $schema = null)
78345 {
78346 if (is_null($schema) && $id !== self::INTERNAL_PROVIDED_SCHEMA_URI) {
78347
78348  
78349  
78350  $schema = $this->uriRetriever->retrieve($id);
78351 }
78352
78353
78354  if (is_array($schema)) {
78355 $schema = BaseConstraint::arrayToObjectRecursive($schema);
78356 }
78357
78358
78359  
78360  if (is_object($schema) && property_exists($schema, 'id')) {
78361 if ($schema->id == 'http://json-schema.org/draft-04/schema#') {
78362 $schema->properties->id->format = 'uri-reference';
78363 } elseif ($schema->id == 'http://json-schema.org/draft-03/schema#') {
78364 $schema->properties->id->format = 'uri-reference';
78365 $schema->properties->{'$ref'}->format = 'uri-reference';
78366 }
78367 }
78368
78369 $objectIterator = new ObjectIterator($schema);
78370 foreach ($objectIterator as $toResolveSchema) {
78371 if (property_exists($toResolveSchema, '$ref') && is_string($toResolveSchema->{'$ref'})) {
78372 $jsonPointer = new JsonPointer($this->uriResolver->resolve($toResolveSchema->{'$ref'}, $id));
78373 $toResolveSchema->{'$ref'} = (string) $jsonPointer;
78374 }
78375 }
78376 $this->schemas[$id] = $schema;
78377 }
78378
78379
78380
78381
78382 public function getSchema($id)
78383 {
78384 if (!array_key_exists($id, $this->schemas)) {
78385 $this->addSchema($id);
78386 }
78387
78388 return $this->schemas[$id];
78389 }
78390
78391
78392
78393
78394 public function resolveRef($ref)
78395 {
78396 $jsonPointer = new JsonPointer($ref);
78397
78398
78399  $fileName = $jsonPointer->getFilename();
78400 if (!strlen($fileName)) {
78401 throw new UnresolvableJsonPointerException(sprintf(
78402 "Could not resolve fragment '%s': no file is defined",
78403 $jsonPointer->getPropertyPathAsString()
78404 ));
78405 }
78406
78407
78408  $refSchema = $this->getSchema($fileName);
78409 foreach ($jsonPointer->getPropertyPaths() as $path) {
78410 if (is_object($refSchema) && property_exists($refSchema, $path)) {
78411 $refSchema = $this->resolveRefSchema($refSchema->{$path});
78412 } elseif (is_array($refSchema) && array_key_exists($path, $refSchema)) {
78413 $refSchema = $this->resolveRefSchema($refSchema[$path]);
78414 } else {
78415 throw new UnresolvableJsonPointerException(sprintf(
78416 'File: %s is found, but could not resolve fragment: %s',
78417 $jsonPointer->getFilename(),
78418 $jsonPointer->getPropertyPathAsString()
78419 ));
78420 }
78421 }
78422
78423 return $refSchema;
78424 }
78425
78426
78427
78428
78429 public function resolveRefSchema($refSchema)
78430 {
78431 if (is_object($refSchema) && property_exists($refSchema, '$ref') && is_string($refSchema->{'$ref'})) {
78432 $newSchema = $this->resolveRef($refSchema->{'$ref'});
78433 $refSchema = (object) (get_object_vars($refSchema) + get_object_vars($newSchema));
78434 unset($refSchema->{'$ref'});
78435 }
78436
78437 return $refSchema;
78438 }
78439 }
78440 <?php
78441
78442 namespace JsonSchema;
78443
78444 interface SchemaStorageInterface
78445 {
78446
78447
78448
78449
78450
78451
78452 public function addSchema($id, $schema = null);
78453
78454
78455
78456
78457
78458
78459
78460
78461 public function getSchema($id);
78462
78463
78464
78465
78466
78467
78468
78469
78470 public function resolveRef($ref);
78471
78472
78473
78474
78475
78476
78477
78478
78479 public function resolveRefSchema($refSchema);
78480 }
78481 <?php
78482
78483
78484
78485
78486
78487
78488 namespace JsonSchema\Uri\Retrievers;
78489
78490
78491
78492
78493
78494
78495
78496 abstract class AbstractRetriever implements UriRetrieverInterface
78497 {
78498
78499
78500
78501
78502
78503 protected $contentType;
78504
78505
78506
78507
78508
78509
78510 public function getContentType()
78511 {
78512 return $this->contentType;
78513 }
78514 }
78515 <?php
78516
78517
78518
78519
78520
78521
78522
78523
78524 namespace JsonSchema\Uri\Retrievers;
78525
78526 use JsonSchema\Exception\RuntimeException;
78527 use JsonSchema\Validator;
78528
78529
78530
78531
78532
78533
78534 class Curl extends AbstractRetriever
78535 {
78536 protected $messageBody;
78537
78538 public function __construct()
78539 {
78540 if (!function_exists('curl_init')) {
78541
78542  throw new RuntimeException('cURL not installed'); 
78543  }
78544 }
78545
78546
78547
78548
78549
78550
78551 public function retrieve($uri)
78552 {
78553 $ch = curl_init();
78554
78555 curl_setopt($ch, CURLOPT_URL, $uri);
78556 curl_setopt($ch, CURLOPT_HEADER, true);
78557 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
78558 curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: ' . Validator::SCHEMA_MEDIA_TYPE));
78559
78560 $response = curl_exec($ch);
78561 if (false === $response) {
78562 throw new \JsonSchema\Exception\ResourceNotFoundException('JSON schema not found');
78563 }
78564
78565 $this->fetchMessageBody($response);
78566 $this->fetchContentType($response);
78567
78568 curl_close($ch);
78569
78570 return $this->messageBody;
78571 }
78572
78573
78574
78575
78576 private function fetchMessageBody($response)
78577 {
78578 preg_match("/(?:\r\n){2}(.*)$/ms", $response, $match);
78579 $this->messageBody = $match[1];
78580 }
78581
78582
78583
78584
78585
78586
78587 protected function fetchContentType($response)
78588 {
78589 if (0 < preg_match("/Content-Type:(\V*)/ims", $response, $match)) {
78590 $this->contentType = trim($match[1]);
78591
78592 return true;
78593 }
78594
78595 return false;
78596 }
78597 }
78598 <?php
78599
78600
78601
78602
78603
78604
78605
78606
78607 namespace JsonSchema\Uri\Retrievers;
78608
78609 use JsonSchema\Exception\ResourceNotFoundException;
78610
78611
78612
78613
78614
78615
78616 class FileGetContents extends AbstractRetriever
78617 {
78618 protected $messageBody;
78619
78620
78621
78622
78623
78624
78625 public function retrieve($uri)
78626 {
78627 $errorMessage = null;
78628 set_error_handler(function ($errno, $errstr) use (&$errorMessage) {
78629 $errorMessage = $errstr;
78630 });
78631 $response = file_get_contents($uri);
78632 restore_error_handler();
78633
78634 if ($errorMessage) {
78635 throw new ResourceNotFoundException($errorMessage);
78636 }
78637
78638 if (false === $response) {
78639 throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
78640 }
78641
78642 if ($response == ''
78643 && substr($uri, 0, 7) == 'file://' && substr($uri, -1) == '/'
78644 ) {
78645 throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
78646 }
78647
78648 $this->messageBody = $response;
78649 if (!empty($http_response_header)) {
78650
78651  
78652  $this->fetchContentType($http_response_header); 
78653  } else { 
78654  
78655  $this->contentType = null;
78656 }
78657
78658 return $this->messageBody;
78659 }
78660
78661
78662
78663
78664
78665
78666 private function fetchContentType(array $headers)
78667 {
78668 foreach ($headers as $header) {
78669 if ($this->contentType = self::getContentTypeMatchInHeader($header)) {
78670 return true;
78671 }
78672 }
78673
78674 return false;
78675 }
78676
78677
78678
78679
78680
78681
78682 protected static function getContentTypeMatchInHeader($header)
78683 {
78684 if (0 < preg_match("/Content-Type:(\V*)/ims", $header, $match)) {
78685 return trim($match[1]);
78686 }
78687
78688 return null;
78689 }
78690 }
78691 <?php
78692
78693 namespace JsonSchema\Uri\Retrievers;
78694
78695 use JsonSchema\Validator;
78696
78697
78698
78699
78700
78701
78702
78703
78704
78705
78706
78707
78708
78709 class PredefinedArray extends AbstractRetriever
78710 {
78711
78712
78713
78714
78715
78716 private $schemas;
78717
78718
78719
78720
78721
78722
78723
78724 public function __construct(array $schemas, $contentType = Validator::SCHEMA_MEDIA_TYPE)
78725 {
78726 $this->schemas = $schemas;
78727 $this->contentType = $contentType;
78728 }
78729
78730
78731
78732
78733
78734
78735 public function retrieve($uri)
78736 {
78737 if (!array_key_exists($uri, $this->schemas)) {
78738 throw new \JsonSchema\Exception\ResourceNotFoundException(sprintf(
78739 'The JSON schema "%s" was not found.',
78740 $uri
78741 ));
78742 }
78743
78744 return $this->schemas[$uri];
78745 }
78746 }
78747 <?php
78748
78749
78750
78751
78752
78753
78754
78755
78756 namespace JsonSchema\Uri\Retrievers;
78757
78758
78759
78760
78761
78762
78763 interface UriRetrieverInterface
78764 {
78765
78766
78767
78768
78769
78770
78771
78772
78773
78774 public function retrieve($uri);
78775
78776
78777
78778
78779
78780
78781 public function getContentType();
78782 }
78783 <?php
78784
78785
78786
78787
78788
78789
78790
78791
78792 namespace JsonSchema\Uri;
78793
78794 use JsonSchema\Exception\UriResolverException;
78795 use JsonSchema\UriResolverInterface;
78796
78797
78798
78799
78800
78801
78802 class UriResolver implements UriResolverInterface
78803 {
78804
78805
78806
78807
78808
78809
78810
78811 public function parse($uri)
78812 {
78813 preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
78814
78815 $components = array();
78816 if (5 < count($match)) {
78817 $components = array(
78818 'scheme' => $match[2],
78819 'authority' => $match[4],
78820 'path' => $match[5]
78821 );
78822 }
78823 if (7 < count($match)) {
78824 $components['query'] = $match[7];
78825 }
78826 if (9 < count($match)) {
78827 $components['fragment'] = $match[9];
78828 }
78829
78830 return $components;
78831 }
78832
78833
78834
78835
78836
78837
78838
78839
78840 public function generate(array $components)
78841 {
78842 $uri = $components['scheme'] . '://'
78843 . $components['authority']
78844 . $components['path'];
78845
78846 if (array_key_exists('query', $components)) {
78847 $uri .= $components['query'];
78848 }
78849 if (array_key_exists('fragment', $components)) {
78850 $uri .= '#' . $components['fragment'];
78851 }
78852
78853 return $uri;
78854 }
78855
78856
78857
78858
78859 public function resolve($uri, $baseUri = null)
78860 {
78861 if ($uri == '') {
78862 return $baseUri;
78863 }
78864
78865 $components = $this->parse($uri);
78866 $path = $components['path'];
78867
78868 if (!empty($components['scheme'])) {
78869 return $uri;
78870 }
78871 $baseComponents = $this->parse($baseUri);
78872 $basePath = $baseComponents['path'];
78873
78874 $baseComponents['path'] = self::combineRelativePathWithBasePath($path, $basePath);
78875 if (isset($components['fragment'])) {
78876 $baseComponents['fragment'] = $components['fragment'];
78877 }
78878
78879 return $this->generate($baseComponents);
78880 }
78881
78882
78883
78884
78885
78886
78887
78888
78889
78890
78891
78892 public static function combineRelativePathWithBasePath($relativePath, $basePath)
78893 {
78894 $relativePath = self::normalizePath($relativePath);
78895 if ($relativePath == '') {
78896 return $basePath;
78897 }
78898 if ($relativePath[0] == '/') {
78899 return $relativePath;
78900 }
78901
78902 $basePathSegments = explode('/', $basePath);
78903
78904 preg_match('|^/?(\.\./(?:\./)*)*|', $relativePath, $match);
78905 $numLevelUp = strlen($match[0]) /3 + 1;
78906 if ($numLevelUp >= count($basePathSegments)) {
78907 throw new UriResolverException(sprintf("Unable to resolve URI '%s' from base '%s'", $relativePath, $basePath));
78908 }
78909
78910 $basePathSegments = array_slice($basePathSegments, 0, -$numLevelUp);
78911 $path = preg_replace('|^/?(\.\./(\./)*)*|', '', $relativePath);
78912
78913 return implode('/', $basePathSegments) . '/' . $path;
78914 }
78915
78916
78917
78918
78919
78920
78921
78922
78923 private static function normalizePath($path)
78924 {
78925 $path = preg_replace('|((?<!\.)\./)*|', '', $path);
78926 $path = preg_replace('|//|', '/', $path);
78927
78928 return $path;
78929 }
78930
78931
78932
78933
78934
78935
78936 public function isValid($uri)
78937 {
78938 $components = $this->parse($uri);
78939
78940 return !empty($components);
78941 }
78942 }
78943 <?php
78944
78945
78946
78947
78948
78949
78950
78951
78952 namespace JsonSchema\Uri;
78953
78954 use JsonSchema\Exception\InvalidSchemaMediaTypeException;
78955 use JsonSchema\Exception\JsonDecodingException;
78956 use JsonSchema\Exception\ResourceNotFoundException;
78957 use JsonSchema\Uri\Retrievers\FileGetContents;
78958 use JsonSchema\Uri\Retrievers\UriRetrieverInterface;
78959 use JsonSchema\UriRetrieverInterface as BaseUriRetrieverInterface;
78960 use JsonSchema\Validator;
78961
78962
78963
78964
78965
78966
78967 class UriRetriever implements BaseUriRetrieverInterface
78968 {
78969
78970
78971
78972 protected $translationMap = array(
78973
78974  '|^https?://json-schema.org/draft-(0[34])/schema#?|' => 'package://dist/schema/json-schema-draft-$1.json'
78975 );
78976
78977
78978
78979
78980 protected $uriRetriever = null;
78981
78982
78983
78984
78985
78986
78987 private $schemaCache = array();
78988
78989
78990
78991
78992
78993
78994
78995
78996
78997 public function confirmMediaType($uriRetriever, $uri)
78998 {
78999 $contentType = $uriRetriever->getContentType();
79000
79001 if (is_null($contentType)) {
79002
79003  return;
79004 }
79005
79006 if (in_array($contentType, array(Validator::SCHEMA_MEDIA_TYPE, 'application/json'))) {
79007 return;
79008 }
79009
79010 if (substr($uri, 0, 23) == 'http://json-schema.org/') {
79011
79012  return true;
79013 }
79014
79015 throw new InvalidSchemaMediaTypeException(sprintf('Media type %s expected', Validator::SCHEMA_MEDIA_TYPE));
79016 }
79017
79018
79019
79020
79021
79022
79023
79024
79025
79026 public function getUriRetriever()
79027 {
79028 if (is_null($this->uriRetriever)) {
79029 $this->setUriRetriever(new FileGetContents());
79030 }
79031
79032 return $this->uriRetriever;
79033 }
79034
79035
79036
79037
79038
79039
79040
79041
79042
79043
79044
79045
79046
79047
79048
79049 public function resolvePointer($jsonSchema, $uri)
79050 {
79051 $resolver = new UriResolver();
79052 $parsed = $resolver->parse($uri);
79053 if (empty($parsed['fragment'])) {
79054 return $jsonSchema;
79055 }
79056
79057 $path = explode('/', $parsed['fragment']);
79058 while ($path) {
79059 $pathElement = array_shift($path);
79060 if (!empty($pathElement)) {
79061 $pathElement = str_replace('~1', '/', $pathElement);
79062 $pathElement = str_replace('~0', '~', $pathElement);
79063 if (!empty($jsonSchema->$pathElement)) {
79064 $jsonSchema = $jsonSchema->$pathElement;
79065 } else {
79066 throw new ResourceNotFoundException(
79067 'Fragment "' . $parsed['fragment'] . '" not found'
79068 . ' in ' . $uri
79069 );
79070 }
79071
79072 if (!is_object($jsonSchema)) {
79073 throw new ResourceNotFoundException(
79074 'Fragment part "' . $pathElement . '" is no object '
79075 . ' in ' . $uri
79076 );
79077 }
79078 }
79079 }
79080
79081 return $jsonSchema;
79082 }
79083
79084
79085
79086
79087 public function retrieve($uri, $baseUri = null, $translate = true)
79088 {
79089 $resolver = new UriResolver();
79090 $resolvedUri = $fetchUri = $resolver->resolve($uri, $baseUri);
79091
79092
79093  $arParts = $resolver->parse($resolvedUri);
79094 if (isset($arParts['fragment'])) {
79095 unset($arParts['fragment']);
79096 $fetchUri = $resolver->generate($arParts);
79097 }
79098
79099
79100  if ($translate) {
79101 $fetchUri = $this->translate($fetchUri);
79102 }
79103
79104 $jsonSchema = $this->loadSchema($fetchUri);
79105
79106
79107  $jsonSchema = $this->resolvePointer($jsonSchema, $resolvedUri);
79108
79109 if ($jsonSchema instanceof \stdClass) {
79110 $jsonSchema->id = $resolvedUri;
79111 }
79112
79113 return $jsonSchema;
79114 }
79115
79116
79117
79118
79119
79120
79121
79122
79123
79124 protected function loadSchema($fetchUri)
79125 {
79126 if (isset($this->schemaCache[$fetchUri])) {
79127 return $this->schemaCache[$fetchUri];
79128 }
79129
79130 $uriRetriever = $this->getUriRetriever();
79131 $contents = $this->uriRetriever->retrieve($fetchUri);
79132 $this->confirmMediaType($uriRetriever, $fetchUri);
79133 $jsonSchema = json_decode($contents);
79134
79135 if (JSON_ERROR_NONE < $error = json_last_error()) {
79136 throw new JsonDecodingException($error);
79137 }
79138
79139 $this->schemaCache[$fetchUri] = $jsonSchema;
79140
79141 return $jsonSchema;
79142 }
79143
79144
79145
79146
79147
79148
79149
79150
79151 public function setUriRetriever(UriRetrieverInterface $uriRetriever)
79152 {
79153 $this->uriRetriever = $uriRetriever;
79154
79155 return $this;
79156 }
79157
79158
79159
79160
79161
79162
79163
79164
79165 public function parse($uri)
79166 {
79167 preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
79168
79169 $components = array();
79170 if (5 < count($match)) {
79171 $components = array(
79172 'scheme' => $match[2],
79173 'authority' => $match[4],
79174 'path' => $match[5]
79175 );
79176 }
79177
79178 if (7 < count($match)) {
79179 $components['query'] = $match[7];
79180 }
79181
79182 if (9 < count($match)) {
79183 $components['fragment'] = $match[9];
79184 }
79185
79186 return $components;
79187 }
79188
79189
79190
79191
79192
79193
79194
79195
79196 public function generate(array $components)
79197 {
79198 $uri = $components['scheme'] . '://'
79199 . $components['authority']
79200 . $components['path'];
79201
79202 if (array_key_exists('query', $components)) {
79203 $uri .= $components['query'];
79204 }
79205
79206 if (array_key_exists('fragment', $components)) {
79207 $uri .= $components['fragment'];
79208 }
79209
79210 return $uri;
79211 }
79212
79213
79214
79215
79216
79217
79218
79219
79220
79221 public function resolve($uri, $baseUri = null)
79222 {
79223 $components = $this->parse($uri);
79224 $path = $components['path'];
79225
79226 if ((array_key_exists('scheme', $components)) && ('http' === $components['scheme'])) {
79227 return $uri;
79228 }
79229
79230 $baseComponents = $this->parse($baseUri);
79231 $basePath = $baseComponents['path'];
79232
79233 $baseComponents['path'] = UriResolver::combineRelativePathWithBasePath($path, $basePath);
79234
79235 return $this->generate($baseComponents);
79236 }
79237
79238
79239
79240
79241
79242
79243 public function isValid($uri)
79244 {
79245 $components = $this->parse($uri);
79246
79247 return !empty($components);
79248 }
79249
79250
79251
79252
79253 public function setTranslation($from, $to)
79254 {
79255 $this->translationMap[$from] = $to;
79256 }
79257
79258
79259
79260
79261 public function translate($uri)
79262 {
79263 foreach ($this->translationMap as $from => $to) {
79264 $uri = preg_replace($from, $to, $uri);
79265 }
79266
79267
79268  $uri = preg_replace('|^package://|', sprintf('file://%s/', realpath(__DIR__ . '/../../..')), $uri);
79269
79270 return $uri;
79271 }
79272 }
79273 <?php
79274
79275
79276
79277
79278
79279
79280
79281
79282 namespace JsonSchema;
79283
79284
79285
79286
79287 interface UriResolverInterface
79288 {
79289
79290
79291
79292
79293
79294
79295
79296
79297 public function resolve($uri, $baseUri = null);
79298 }
79299 <?php
79300
79301
79302
79303
79304
79305
79306
79307
79308 namespace JsonSchema;
79309
79310
79311
79312
79313 interface UriRetrieverInterface
79314 {
79315
79316
79317
79318
79319
79320
79321
79322
79323 public function retrieve($uri, $baseUri = null);
79324 }
79325 <?php
79326
79327
79328
79329
79330
79331
79332
79333
79334 namespace JsonSchema;
79335
79336 use JsonSchema\Constraints\BaseConstraint;
79337 use JsonSchema\Constraints\Constraint;
79338 use JsonSchema\Exception\InvalidConfigException;
79339 use JsonSchema\SchemaStorage;
79340
79341
79342
79343
79344
79345
79346
79347
79348
79349 class Validator extends BaseConstraint
79350 {
79351 const SCHEMA_MEDIA_TYPE = 'application/schema+json';
79352
79353 const ERROR_NONE = 0x00000000;
79354 const ERROR_ALL = 0xFFFFFFFF;
79355 const ERROR_DOCUMENT_VALIDATION = 0x00000001;
79356 const ERROR_SCHEMA_VALIDATION = 0x00000002;
79357
79358
79359
79360
79361
79362
79363
79364
79365
79366
79367 public function validate(&$value, $schema = null, $checkMode = null)
79368 {
79369
79370  if (is_array($schema)) {
79371 $schema = self::arrayToObjectRecursive($schema);
79372 }
79373
79374
79375  $initialCheckMode = $this->factory->getConfig();
79376 if ($checkMode !== null) {
79377 $this->factory->setConfig($checkMode);
79378 }
79379
79380
79381  $this->factory->getSchemaStorage()->addSchema(SchemaStorage::INTERNAL_PROVIDED_SCHEMA_URI, $schema);
79382
79383 $validator = $this->factory->createInstanceFor('schema');
79384 $validator->check(
79385 $value,
79386 $this->factory->getSchemaStorage()->getSchema(SchemaStorage::INTERNAL_PROVIDED_SCHEMA_URI)
79387 );
79388
79389 $this->factory->setConfig($initialCheckMode);
79390
79391 $this->addErrors(array_unique($validator->getErrors(), SORT_REGULAR));
79392
79393 return $validator->getErrorMask();
79394 }
79395
79396
79397
79398
79399 public function check($value, $schema)
79400 {
79401 return $this->validate($value, $schema);
79402 }
79403
79404
79405
79406
79407 public function coerce(&$value, $schema)
79408 {
79409 return $this->validate($value, $schema, Constraint::CHECK_MODE_COERCE_TYPES);
79410 }
79411 }
79412 Copyright (C) 2015 Composer
79413
79414 Permission is hereby granted, free of charge, to any person obtaining a copy of
79415 this software and associated documentation files (the "Software"), to deal in
79416 the Software without restriction, including without limitation the rights to
79417 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
79418 of the Software, and to permit persons to whom the Software is furnished to do
79419 so, subject to the following conditions:
79420
79421 The above copyright notice and this permission notice shall be included in all
79422 copies or substantial portions of the Software.
79423
79424 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
79425 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
79426 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
79427 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
79428 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
79429 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
79430 SOFTWARE.
79431 <?php
79432
79433
79434
79435
79436
79437
79438
79439
79440
79441
79442 namespace Composer\Spdx;
79443
79444 class SpdxLicenses
79445 {
79446
79447 const LICENSES_FILE = 'spdx-licenses.json';
79448
79449
79450 const EXCEPTIONS_FILE = 'spdx-exceptions.json';
79451
79452
79453
79454
79455
79456
79457
79458
79459
79460
79461
79462
79463
79464
79465 private $licenses;
79466
79467
79468
79469
79470 private $licensesExpression;
79471
79472
79473
79474
79475
79476
79477
79478
79479
79480
79481
79482
79483
79484
79485 private $exceptions;
79486
79487
79488
79489
79490 private $exceptionsExpression;
79491
79492 public function __construct()
79493 {
79494 $this->loadLicenses();
79495 $this->loadExceptions();
79496 }
79497
79498
79499
79500
79501
79502
79503
79504
79505
79506
79507
79508
79509
79510 public function getLicenseByIdentifier($identifier)
79511 {
79512 if (!isset($this->licenses[$identifier])) {
79513 return;
79514 }
79515
79516 $license = $this->licenses[$identifier];
79517 $license[] = 'https://spdx.org/licenses/' . $identifier . '.html#licenseText';
79518
79519 return $license;
79520 }
79521
79522
79523
79524
79525
79526
79527
79528
79529
79530
79531
79532
79533
79534 public function getExceptionByIdentifier($identifier)
79535 {
79536 if (!isset($this->exceptions[$identifier])) {
79537 return;
79538 }
79539
79540 $license = $this->exceptions[$identifier];
79541 $license[] = 'https://spdx.org/licenses/' . $identifier . '.html#licenseExceptionText';
79542
79543 return $license;
79544 }
79545
79546
79547
79548
79549
79550
79551
79552
79553 public function getIdentifierByName($name)
79554 {
79555 foreach ($this->licenses as $identifier => $licenseData) {
79556 if ($licenseData[0] === $name) {
79557 return $identifier;
79558 }
79559 }
79560
79561 foreach ($this->exceptions as $identifier => $licenseData) {
79562 if ($licenseData[0] === $name) {
79563 return $identifier;
79564 }
79565 }
79566 }
79567
79568
79569
79570
79571
79572
79573
79574
79575 public function isOsiApprovedByIdentifier($identifier)
79576 {
79577 return $this->licenses[$identifier][1];
79578 }
79579
79580
79581
79582
79583
79584
79585
79586
79587 public function validate($license)
79588 {
79589 if (is_array($license)) {
79590 $count = count($license);
79591 if ($count !== count(array_filter($license, 'is_string'))) {
79592 throw new \InvalidArgumentException('Array of strings expected.');
79593 }
79594 $license = $count > 1 ? '(' . implode(' OR ', $license) . ')' : (string) reset($license);
79595 }
79596
79597 if (!is_string($license)) {
79598 throw new \InvalidArgumentException(sprintf(
79599 'Array or String expected, %s given.',
79600 gettype($license)
79601 ));
79602 }
79603
79604 return $this->isValidLicenseString($license);
79605 }
79606
79607
79608
79609
79610 public static function getResourcesDir()
79611 {
79612 return dirname(__DIR__) . '/res';
79613 }
79614
79615 private function loadLicenses()
79616 {
79617 if (null === $this->licenses) {
79618 $json = file_get_contents(self::getResourcesDir() . '/' . self::LICENSES_FILE);
79619 $this->licenses = json_decode($json, true);
79620 }
79621 }
79622
79623 private function loadExceptions()
79624 {
79625 if (null === $this->exceptions) {
79626 $json = file_get_contents(self::getResourcesDir() . '/' . self::EXCEPTIONS_FILE);
79627 $this->exceptions = json_decode($json, true);
79628 }
79629 }
79630
79631
79632
79633
79634 private function getLicensesExpression()
79635 {
79636 if (null === $this->licensesExpression) {
79637 $licenses = array_map('preg_quote', array_keys($this->licenses));
79638 rsort($licenses);
79639 $licenses = implode('|', $licenses);
79640 $this->licensesExpression = $licenses;
79641 }
79642
79643 return $this->licensesExpression;
79644 }
79645
79646
79647
79648
79649 private function getExceptionsExpression()
79650 {
79651 if (null === $this->exceptionsExpression) {
79652 $exceptions = array_map('preg_quote', array_keys($this->exceptions));
79653 rsort($exceptions);
79654 $exceptions = implode('|', $exceptions);
79655 $this->exceptionsExpression = $exceptions;
79656 }
79657
79658 return $this->exceptionsExpression;
79659 }
79660
79661
79662
79663
79664
79665
79666
79667
79668 private function isValidLicenseString($license)
79669 {
79670 if (isset($this->licenses[$license])) {
79671 return true;
79672 }
79673
79674 $licenses = $this->getLicensesExpression();
79675 $exceptions = $this->getExceptionsExpression();
79676
79677 $regex = <<<REGEX
79678 {
79679 (?(DEFINE)
79680     # idstring: 1*( ALPHA / DIGIT / - / . )
79681     (?<idstring>[\pL\pN.-]{1,})
79682
79683     # license-id: taken from list
79684     (?<licenseid>${licenses})
79685
79686     # license-exception-id: taken from list
79687     (?<licenseexceptionid>${exceptions})
79688
79689     # license-ref: [DocumentRef-1*(idstring):]LicenseRef-1*(idstring)
79690     (?<licenseref>(?:DocumentRef-(?&idstring):)?LicenseRef-(?&idstring))
79691
79692     # simple-expresssion: license-id / license-id+ / license-ref
79693     (?<simple_expression>(?&licenseid)\+? | (?&licenseid) | (?&licenseref))
79694
79695     # compound-expression: 1*(
79696     #   simple-expression /
79697     #   simple-expression WITH license-exception-id /
79698     #   compound-expression AND compound-expression /
79699     #   compound-expression OR compound-expression
79700     # ) / ( compound-expression ) )
79701     (?<compound_head>
79702         (?&simple_expression) ( \s+ (?:with|WITH) \s+ (?&licenseexceptionid))?
79703             | \( \s* (?&compound_expression) \s* \)
79704     )
79705     (?<compound_expression>
79706         (?&compound_head) (?: \s+ (?:and|AND|or|OR) \s+ (?&compound_expression))?
79707     )
79708
79709     # license-expression: 1*1(simple-expression / compound-expression)
79710     (?<license_expression>(?&compound_expression) | (?&simple_expression))
79711 ) # end of define
79712
79713 ^(NONE | NOASSERTION | (?&license_expression))$
79714 }x
79715 REGEX;
79716
79717 $match = preg_match($regex, $license);
79718
79719 if (0 === $match) {
79720 return false;
79721 }
79722
79723 if (false === $match) {
79724 throw new \RuntimeException('Regex failed to compile/run.');
79725 }
79726
79727 return true;
79728 }
79729 }
79730 Copyright (C) 2015 Composer
79731
79732 Permission is hereby granted, free of charge, to any person obtaining a copy of
79733 this software and associated documentation files (the "Software"), to deal in
79734 the Software without restriction, including without limitation the rights to
79735 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
79736 of the Software, and to permit persons to whom the Software is furnished to do
79737 so, subject to the following conditions:
79738
79739 The above copyright notice and this permission notice shall be included in all
79740 copies or substantial portions of the Software.
79741
79742 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
79743 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
79744 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
79745 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
79746 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
79747 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
79748 SOFTWARE.
79749 <?php
79750
79751
79752
79753
79754
79755
79756
79757
79758
79759
79760 namespace Composer\Semver;
79761
79762 use Composer\Semver\Constraint\Constraint;
79763
79764 class Comparator
79765 {
79766
79767
79768
79769
79770
79771
79772
79773
79774 public static function greaterThan($version1, $version2)
79775 {
79776 return self::compare($version1, '>', $version2);
79777 }
79778
79779
79780
79781
79782
79783
79784
79785
79786
79787 public static function greaterThanOrEqualTo($version1, $version2)
79788 {
79789 return self::compare($version1, '>=', $version2);
79790 }
79791
79792
79793
79794
79795
79796
79797
79798
79799
79800 public static function lessThan($version1, $version2)
79801 {
79802 return self::compare($version1, '<', $version2);
79803 }
79804
79805
79806
79807
79808
79809
79810
79811
79812
79813 public static function lessThanOrEqualTo($version1, $version2)
79814 {
79815 return self::compare($version1, '<=', $version2);
79816 }
79817
79818
79819
79820
79821
79822
79823
79824
79825
79826 public static function equalTo($version1, $version2)
79827 {
79828 return self::compare($version1, '==', $version2);
79829 }
79830
79831
79832
79833
79834
79835
79836
79837
79838
79839 public static function notEqualTo($version1, $version2)
79840 {
79841 return self::compare($version1, '!=', $version2);
79842 }
79843
79844
79845
79846
79847
79848
79849
79850
79851
79852
79853 public static function compare($version1, $operator, $version2)
79854 {
79855 $constraint = new Constraint($operator, $version2);
79856
79857 return $constraint->matches(new Constraint('==', $version1));
79858 }
79859 }
79860 <?php
79861
79862
79863
79864
79865
79866
79867
79868
79869
79870
79871 namespace Composer\Semver\Constraint;
79872
79873 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);
79874
79875
79876
79877
79878 abstract class AbstractConstraint implements ConstraintInterface
79879 {
79880
79881 protected $prettyString;
79882
79883
79884
79885
79886
79887
79888 public function matches(ConstraintInterface $provider)
79889 {
79890 if ($provider instanceof $this) {
79891
79892  return $this->matchSpecific($provider);
79893 }
79894
79895
79896  return $provider->matches($this);
79897 }
79898
79899
79900
79901
79902 public function setPrettyString($prettyString)
79903 {
79904 $this->prettyString = $prettyString;
79905 }
79906
79907
79908
79909
79910 public function getPrettyString()
79911 {
79912 if ($this->prettyString) {
79913 return $this->prettyString;
79914 }
79915
79916 return $this->__toString();
79917 }
79918
79919
79920  
79921  
79922 }
79923 <?php
79924
79925
79926
79927
79928
79929
79930
79931
79932
79933
79934 namespace Composer\Semver\Constraint;
79935
79936
79937
79938
79939 class Constraint implements ConstraintInterface
79940 {
79941
79942 const OP_EQ = 0;
79943 const OP_LT = 1;
79944 const OP_LE = 2;
79945 const OP_GT = 3;
79946 const OP_GE = 4;
79947 const OP_NE = 5;
79948
79949
79950
79951
79952
79953
79954 private static $transOpStr = array(
79955 '=' => self::OP_EQ,
79956 '==' => self::OP_EQ,
79957 '<' => self::OP_LT,
79958 '<=' => self::OP_LE,
79959 '>' => self::OP_GT,
79960 '>=' => self::OP_GE,
79961 '<>' => self::OP_NE,
79962 '!=' => self::OP_NE,
79963 );
79964
79965
79966
79967
79968
79969
79970 private static $transOpInt = array(
79971 self::OP_EQ => '==',
79972 self::OP_LT => '<',
79973 self::OP_LE => '<=',
79974 self::OP_GT => '>',
79975 self::OP_GE => '>=',
79976 self::OP_NE => '!=',
79977 );
79978
79979
79980 protected $operator;
79981
79982
79983 protected $version;
79984
79985
79986 protected $prettyString;
79987
79988
79989
79990
79991
79992
79993 public function matches(ConstraintInterface $provider)
79994 {
79995 if ($provider instanceof $this) {
79996 return $this->matchSpecific($provider);
79997 }
79998
79999
80000  return $provider->matches($this);
80001 }
80002
80003
80004
80005
80006 public function setPrettyString($prettyString)
80007 {
80008 $this->prettyString = $prettyString;
80009 }
80010
80011
80012
80013
80014 public function getPrettyString()
80015 {
80016 if ($this->prettyString) {
80017 return $this->prettyString;
80018 }
80019
80020 return $this->__toString();
80021 }
80022
80023
80024
80025
80026
80027
80028 public static function getSupportedOperators()
80029 {
80030 return array_keys(self::$transOpStr);
80031 }
80032
80033
80034
80035
80036
80037
80038
80039
80040
80041 public function __construct($operator, $version)
80042 {
80043 if (!isset(self::$transOpStr[$operator])) {
80044 throw new \InvalidArgumentException(sprintf(
80045 'Invalid operator "%s" given, expected one of: %s',
80046 $operator,
80047 implode(', ', self::getSupportedOperators())
80048 ));
80049 }
80050
80051 $this->operator = self::$transOpStr[$operator];
80052 $this->version = $version;
80053 }
80054
80055
80056
80057
80058
80059
80060
80061
80062
80063
80064
80065 public function versionCompare($a, $b, $operator, $compareBranches = false)
80066 {
80067 if (!isset(self::$transOpStr[$operator])) {
80068 throw new \InvalidArgumentException(sprintf(
80069 'Invalid operator "%s" given, expected one of: %s',
80070 $operator,
80071 implode(', ', self::getSupportedOperators())
80072 ));
80073 }
80074
80075 $aIsBranch = 'dev-' === substr($a, 0, 4);
80076 $bIsBranch = 'dev-' === substr($b, 0, 4);
80077
80078 if ($aIsBranch && $bIsBranch) {
80079 return $operator === '==' && $a === $b;
80080 }
80081
80082
80083  if (!$compareBranches && ($aIsBranch || $bIsBranch)) {
80084 return false;
80085 }
80086
80087 return version_compare($a, $b, $operator);
80088 }
80089
80090
80091
80092
80093
80094
80095
80096 public function matchSpecific(Constraint $provider, $compareBranches = false)
80097 {
80098 $noEqualOp = str_replace('=', '', self::$transOpInt[$this->operator]);
80099 $providerNoEqualOp = str_replace('=', '', self::$transOpInt[$provider->operator]);
80100
80101 $isEqualOp = self::OP_EQ === $this->operator;
80102 $isNonEqualOp = self::OP_NE === $this->operator;
80103 $isProviderEqualOp = self::OP_EQ === $provider->operator;
80104 $isProviderNonEqualOp = self::OP_NE === $provider->operator;
80105
80106
80107  
80108  if ($isNonEqualOp || $isProviderNonEqualOp) {
80109 return !$isEqualOp && !$isProviderEqualOp
80110 || $this->versionCompare($provider->version, $this->version, '!=', $compareBranches);
80111 }
80112
80113
80114  
80115  if ($this->operator !== self::OP_EQ && $noEqualOp === $providerNoEqualOp) {
80116 return true;
80117 }
80118
80119 if ($this->versionCompare($provider->version, $this->version, self::$transOpInt[$this->operator], $compareBranches)) {
80120
80121  
80122  if ($provider->version === $this->version
80123 && self::$transOpInt[$provider->operator] === $providerNoEqualOp
80124 && self::$transOpInt[$this->operator] !== $noEqualOp) {
80125 return false;
80126 }
80127
80128 return true;
80129 }
80130
80131 return false;
80132 }
80133
80134
80135
80136
80137 public function __toString()
80138 {
80139 return self::$transOpInt[$this->operator] . ' ' . $this->version;
80140 }
80141 }
80142 <?php
80143
80144
80145
80146
80147
80148
80149
80150
80151
80152
80153 namespace Composer\Semver\Constraint;
80154
80155 interface ConstraintInterface
80156 {
80157
80158
80159
80160
80161
80162 public function matches(ConstraintInterface $provider);
80163
80164
80165
80166
80167 public function getPrettyString();
80168
80169
80170
80171
80172 public function __toString();
80173 }
80174 <?php
80175
80176
80177
80178
80179
80180
80181
80182
80183
80184
80185 namespace Composer\Semver\Constraint;
80186
80187
80188
80189
80190 class EmptyConstraint implements ConstraintInterface
80191 {
80192
80193 protected $prettyString;
80194
80195
80196
80197
80198
80199
80200 public function matches(ConstraintInterface $provider)
80201 {
80202 return true;
80203 }
80204
80205
80206
80207
80208 public function setPrettyString($prettyString)
80209 {
80210 $this->prettyString = $prettyString;
80211 }
80212
80213
80214
80215
80216 public function getPrettyString()
80217 {
80218 if ($this->prettyString) {
80219 return $this->prettyString;
80220 }
80221
80222 return $this->__toString();
80223 }
80224
80225
80226
80227
80228 public function __toString()
80229 {
80230 return '[]';
80231 }
80232 }
80233 <?php
80234
80235
80236
80237
80238
80239
80240
80241
80242
80243
80244 namespace Composer\Semver\Constraint;
80245
80246
80247
80248
80249 class MultiConstraint implements ConstraintInterface
80250 {
80251
80252 protected $constraints;
80253
80254
80255 protected $prettyString;
80256
80257
80258 protected $conjunctive;
80259
80260
80261
80262
80263
80264 public function __construct(array $constraints, $conjunctive = true)
80265 {
80266 $this->constraints = $constraints;
80267 $this->conjunctive = $conjunctive;
80268 }
80269
80270
80271
80272
80273 public function getConstraints()
80274 {
80275 return $this->constraints;
80276 }
80277
80278
80279
80280
80281 public function isConjunctive()
80282 {
80283 return $this->conjunctive;
80284 }
80285
80286
80287
80288
80289 public function isDisjunctive()
80290 {
80291 return !$this->conjunctive;
80292 }
80293
80294
80295
80296
80297
80298
80299 public function matches(ConstraintInterface $provider)
80300 {
80301 if (false === $this->conjunctive) {
80302 foreach ($this->constraints as $constraint) {
80303 if ($constraint->matches($provider)) {
80304 return true;
80305 }
80306 }
80307
80308 return false;
80309 }
80310
80311 foreach ($this->constraints as $constraint) {
80312 if (!$constraint->matches($provider)) {
80313 return false;
80314 }
80315 }
80316
80317 return true;
80318 }
80319
80320
80321
80322
80323 public function setPrettyString($prettyString)
80324 {
80325 $this->prettyString = $prettyString;
80326 }
80327
80328
80329
80330
80331 public function getPrettyString()
80332 {
80333 if ($this->prettyString) {
80334 return $this->prettyString;
80335 }
80336
80337 return $this->__toString();
80338 }
80339
80340
80341
80342
80343 public function __toString()
80344 {
80345 $constraints = array();
80346 foreach ($this->constraints as $constraint) {
80347 $constraints[] = (string) $constraint;
80348 }
80349
80350 return '[' . implode($this->conjunctive ? ' ' : ' || ', $constraints) . ']';
80351 }
80352 }
80353 <?php
80354
80355
80356
80357
80358
80359
80360
80361
80362
80363
80364 namespace Composer\Semver;
80365
80366 use Composer\Semver\Constraint\Constraint;
80367
80368 class Semver
80369 {
80370 const SORT_ASC = 1;
80371 const SORT_DESC = -1;
80372
80373
80374 private static $versionParser;
80375
80376
80377
80378
80379
80380
80381
80382
80383
80384 public static function satisfies($version, $constraints)
80385 {
80386 if (null === self::$versionParser) {
80387 self::$versionParser = new VersionParser();
80388 }
80389
80390 $versionParser = self::$versionParser;
80391 $provider = new Constraint('==', $versionParser->normalize($version));
80392 $constraints = $versionParser->parseConstraints($constraints);
80393
80394 return $constraints->matches($provider);
80395 }
80396
80397
80398
80399
80400
80401
80402
80403
80404
80405 public static function satisfiedBy(array $versions, $constraints)
80406 {
80407 $versions = array_filter($versions, function ($version) use ($constraints) {
80408 return Semver::satisfies($version, $constraints);
80409 });
80410
80411 return array_values($versions);
80412 }
80413
80414
80415
80416
80417
80418
80419
80420
80421 public static function sort(array $versions)
80422 {
80423 return self::usort($versions, self::SORT_ASC);
80424 }
80425
80426
80427
80428
80429
80430
80431
80432
80433 public static function rsort(array $versions)
80434 {
80435 return self::usort($versions, self::SORT_DESC);
80436 }
80437
80438
80439
80440
80441
80442
80443
80444 private static function usort(array $versions, $direction)
80445 {
80446 if (null === self::$versionParser) {
80447 self::$versionParser = new VersionParser();
80448 }
80449
80450 $versionParser = self::$versionParser;
80451 $normalized = array();
80452
80453
80454  
80455  foreach ($versions as $key => $version) {
80456 $normalized[] = array($versionParser->normalize($version), $key);
80457 }
80458
80459 usort($normalized, function (array $left, array $right) use ($direction) {
80460 if ($left[0] === $right[0]) {
80461 return 0;
80462 }
80463
80464 if (Comparator::lessThan($left[0], $right[0])) {
80465 return -$direction;
80466 }
80467
80468 return $direction;
80469 });
80470
80471
80472  $sorted = array();
80473 foreach ($normalized as $item) {
80474 $sorted[] = $versions[$item[1]];
80475 }
80476
80477 return $sorted;
80478 }
80479 }
80480 <?php
80481
80482
80483
80484
80485
80486
80487
80488
80489
80490
80491 namespace Composer\Semver;
80492
80493 use Composer\Semver\Constraint\ConstraintInterface;
80494 use Composer\Semver\Constraint\EmptyConstraint;
80495 use Composer\Semver\Constraint\MultiConstraint;
80496 use Composer\Semver\Constraint\Constraint;
80497
80498
80499
80500
80501
80502
80503 class VersionParser
80504 {
80505
80506
80507
80508
80509
80510
80511
80512
80513
80514
80515
80516
80517
80518 private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)((?:[.-]?\d+)*+)?)?([.-]?dev)?';
80519
80520
80521 private static $stabilities = array('stable', 'RC', 'beta', 'alpha', 'dev');
80522
80523
80524
80525
80526
80527
80528
80529
80530 public static function parseStability($version)
80531 {
80532 $version = preg_replace('{#.+$}i', '', $version);
80533
80534 if ('dev-' === substr($version, 0, 4) || '-dev' === substr($version, -4)) {
80535 return 'dev';
80536 }
80537
80538 preg_match('{' . self::$modifierRegex . '(?:\+.*)?$}i', strtolower($version), $match);
80539 if (!empty($match[3])) {
80540 return 'dev';
80541 }
80542
80543 if (!empty($match[1])) {
80544 if ('beta' === $match[1] || 'b' === $match[1]) {
80545 return 'beta';
80546 }
80547 if ('alpha' === $match[1] || 'a' === $match[1]) {
80548 return 'alpha';
80549 }
80550 if ('rc' === $match[1]) {
80551 return 'RC';
80552 }
80553 }
80554
80555 return 'stable';
80556 }
80557
80558
80559
80560
80561
80562
80563 public static function normalizeStability($stability)
80564 {
80565 $stability = strtolower($stability);
80566
80567 return $stability === 'rc' ? 'RC' : $stability;
80568 }
80569
80570
80571
80572
80573
80574
80575
80576
80577
80578
80579
80580 public function normalize($version, $fullVersion = null)
80581 {
80582 $version = trim($version);
80583 if (null === $fullVersion) {
80584 $fullVersion = $version;
80585 }
80586
80587
80588  if (preg_match('{^([^,\s]++) ++as ++([^,\s]++)$}', $version, $match)) {
80589 $version = $match[1];
80590 }
80591
80592
80593  if (preg_match('{^(?:dev-)?(?:master|trunk|default)$}i', $version)) {
80594 return '9999999-dev';
80595 }
80596
80597
80598  if ('dev-' === strtolower(substr($version, 0, 4))) {
80599 return 'dev-' . substr($version, 4);
80600 }
80601
80602
80603  if (preg_match('{^([^,\s+]++)\+[^\s]++$}', $version, $match)) {
80604 $version = $match[1];
80605 }
80606
80607
80608  if (preg_match('{^v?(\d{1,5})(\.\d++)?(\.\d++)?(\.\d++)?' . self::$modifierRegex . '$}i', $version, $matches)) {
80609 $version = $matches[1]
80610 . (!empty($matches[2]) ? $matches[2] : '.0')
80611 . (!empty($matches[3]) ? $matches[3] : '.0')
80612 . (!empty($matches[4]) ? $matches[4] : '.0');
80613 $index = 5;
80614
80615  } elseif (preg_match('{^v?(\d{4}(?:[.:-]?\d{2}){1,6}(?:[.:-]?\d{1,3})?)' . self::$modifierRegex . '$}i', $version, $matches)) {
80616 $version = preg_replace('{\D}', '.', $matches[1]);
80617 $index = 2;
80618 }
80619
80620
80621  if (isset($index)) {
80622 if (!empty($matches[$index])) {
80623 if ('stable' === $matches[$index]) {
80624 return $version;
80625 }
80626 $version .= '-' . $this->expandStability($matches[$index]) . (!empty($matches[$index + 1]) ? ltrim($matches[$index + 1], '.-') : '');
80627 }
80628
80629 if (!empty($matches[$index + 2])) {
80630 $version .= '-dev';
80631 }
80632
80633 return $version;
80634 }
80635
80636
80637  if (preg_match('{(.*?)[.-]?dev$}i', $version, $match)) {
80638 try {
80639 return $this->normalizeBranch($match[1]);
80640 } catch (\Exception $e) {
80641 }
80642 }
80643
80644 $extraMessage = '';
80645 if (preg_match('{ +as +' . preg_quote($version) . '$}', $fullVersion)) {
80646 $extraMessage = ' in "' . $fullVersion . '", the alias must be an exact version';
80647 } elseif (preg_match('{^' . preg_quote($version) . ' +as +}', $fullVersion)) {
80648 $extraMessage = ' in "' . $fullVersion . '", the alias source must be an exact version, if it is a branch name you should prefix it with dev-';
80649 }
80650
80651 throw new \UnexpectedValueException('Invalid version string "' . $version . '"' . $extraMessage);
80652 }
80653
80654
80655
80656
80657
80658
80659
80660
80661 public function parseNumericAliasPrefix($branch)
80662 {
80663 if (preg_match('{^(?P<version>(\d++\\.)*\d++)(?:\.x)?-dev$}i', $branch, $matches)) {
80664 return $matches['version'] . '.';
80665 }
80666
80667 return false;
80668 }
80669
80670
80671
80672
80673
80674
80675
80676
80677 public function normalizeBranch($name)
80678 {
80679 $name = trim($name);
80680
80681 if (in_array($name, array('master', 'trunk', 'default'))) {
80682 return $this->normalize($name);
80683 }
80684
80685 if (preg_match('{^v?(\d++)(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?$}i', $name, $matches)) {
80686 $version = '';
80687 for ($i = 1; $i < 5; ++$i) {
80688 $version .= isset($matches[$i]) ? str_replace(array('*', 'X'), 'x', $matches[$i]) : '.x';
80689 }
80690
80691 return str_replace('x', '9999999', $version) . '-dev';
80692 }
80693
80694 return 'dev-' . $name;
80695 }
80696
80697
80698
80699
80700
80701
80702
80703
80704 public function parseConstraints($constraints)
80705 {
80706 $prettyConstraint = $constraints;
80707
80708 if (preg_match('{^([^,\s]*?)@(' . implode('|', self::$stabilities) . ')$}i', $constraints, $match)) {
80709 $constraints = empty($match[1]) ? '*' : $match[1];
80710 }
80711
80712 if (preg_match('{^(dev-[^,\s@]+?|[^,\s@]+?\.x-dev)#.+$}i', $constraints, $match)) {
80713 $constraints = $match[1];
80714 }
80715
80716 $orConstraints = preg_split('{\s*\|\|?\s*}', trim($constraints));
80717 $orGroups = array();
80718 foreach ($orConstraints as $constraints) {
80719 $andConstraints = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $constraints);
80720 if (count($andConstraints) > 1) {
80721 $constraintObjects = array();
80722 foreach ($andConstraints as $constraint) {
80723 foreach ($this->parseConstraint($constraint) as $parsedConstraint) {
80724 $constraintObjects[] = $parsedConstraint;
80725 }
80726 }
80727 } else {
80728 $constraintObjects = $this->parseConstraint($andConstraints[0]);
80729 }
80730
80731 if (1 === count($constraintObjects)) {
80732 $constraint = $constraintObjects[0];
80733 } else {
80734 $constraint = new MultiConstraint($constraintObjects);
80735 }
80736
80737 $orGroups[] = $constraint;
80738 }
80739
80740 if (1 === count($orGroups)) {
80741 $constraint = $orGroups[0];
80742 } elseif (2 === count($orGroups)
80743
80744  
80745  && $orGroups[0] instanceof MultiConstraint
80746 && $orGroups[1] instanceof MultiConstraint
80747 && 2 === count($orGroups[0]->getConstraints())
80748 && 2 === count($orGroups[1]->getConstraints())
80749 && ($a = (string) $orGroups[0])
80750 && substr($a, 0, 3) === '[>=' && (false !== ($posA = strpos($a, '<', 4)))
80751 && ($b = (string) $orGroups[1])
80752 && substr($b, 0, 3) === '[>=' && (false !== ($posB = strpos($b, '<', 4)))
80753 && substr($a, $posA + 2, -1) === substr($b, 4, $posB - 5)
80754 ) {
80755 $constraint = new MultiConstraint(array(
80756 new Constraint('>=', substr($a, 4, $posA - 5)),
80757 new Constraint('<', substr($b, $posB + 2, -1)),
80758 ));
80759 } else {
80760 $constraint = new MultiConstraint($orGroups, false);
80761 }
80762
80763 $constraint->setPrettyString($prettyConstraint);
80764
80765 return $constraint;
80766 }
80767
80768
80769
80770
80771
80772
80773
80774
80775 private function parseConstraint($constraint)
80776 {
80777 if (preg_match('{^([^,\s]+?)@(' . implode('|', self::$stabilities) . ')$}i', $constraint, $match)) {
80778 $constraint = $match[1];
80779 if ($match[2] !== 'stable') {
80780 $stabilityModifier = $match[2];
80781 }
80782 }
80783
80784 if (preg_match('{^v?[xX*](\.[xX*])*$}i', $constraint)) {
80785 return array(new EmptyConstraint());
80786 }
80787
80788 $versionRegex = 'v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.(\d++))?' . self::$modifierRegex . '(?:\+[^\s]+)?';
80789
80790
80791  
80792  
80793  
80794  
80795  if (preg_match('{^~>?' . $versionRegex . '$}i', $constraint, $matches)) {
80796 if (substr($constraint, 0, 2) === '~>') {
80797 throw new \UnexpectedValueException(
80798 'Could not parse version constraint ' . $constraint . ': ' .
80799 'Invalid operator "~>", you probably meant to use the "~" operator'
80800 );
80801 }
80802
80803
80804  if (isset($matches[4]) && '' !== $matches[4]) {
80805 $position = 4;
80806 } elseif (isset($matches[3]) && '' !== $matches[3]) {
80807 $position = 3;
80808 } elseif (isset($matches[2]) && '' !== $matches[2]) {
80809 $position = 2;
80810 } else {
80811 $position = 1;
80812 }
80813
80814
80815  $stabilitySuffix = '';
80816 if (!empty($matches[5])) {
80817 $stabilitySuffix .= '-' . $this->expandStability($matches[5]) . (!empty($matches[6]) ? $matches[6] : '');
80818 }
80819
80820 if (!empty($matches[7])) {
80821 $stabilitySuffix .= '-dev';
80822 }
80823
80824 if (!$stabilitySuffix) {
80825 $stabilitySuffix = '-dev';
80826 }
80827
80828 $lowVersion = $this->manipulateVersionString($matches, $position, 0) . $stabilitySuffix;
80829 $lowerBound = new Constraint('>=', $lowVersion);
80830
80831
80832  
80833  $highPosition = max(1, $position - 1);
80834 $highVersion = $this->manipulateVersionString($matches, $highPosition, 1) . '-dev';
80835 $upperBound = new Constraint('<', $highVersion);
80836
80837 return array(
80838 $lowerBound,
80839 $upperBound,
80840 );
80841 }
80842
80843
80844  
80845  
80846  
80847  
80848  if (preg_match('{^\^' . $versionRegex . '($)}i', $constraint, $matches)) {
80849
80850  if ('0' !== $matches[1] || '' === $matches[2]) {
80851 $position = 1;
80852 } elseif ('0' !== $matches[2] || '' === $matches[3]) {
80853 $position = 2;
80854 } else {
80855 $position = 3;
80856 }
80857
80858
80859  $stabilitySuffix = '';
80860 if (empty($matches[5]) && empty($matches[7])) {
80861 $stabilitySuffix .= '-dev';
80862 }
80863
80864 $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1));
80865 $lowerBound = new Constraint('>=', $lowVersion);
80866
80867
80868  
80869  $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
80870 $upperBound = new Constraint('<', $highVersion);
80871
80872 return array(
80873 $lowerBound,
80874 $upperBound,
80875 );
80876 }
80877
80878
80879  
80880  
80881  
80882  if (preg_match('{^v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.[xX*])++$}', $constraint, $matches)) {
80883 if (isset($matches[3]) && '' !== $matches[3]) {
80884 $position = 3;
80885 } elseif (isset($matches[2]) && '' !== $matches[2]) {
80886 $position = 2;
80887 } else {
80888 $position = 1;
80889 }
80890
80891 $lowVersion = $this->manipulateVersionString($matches, $position) . '-dev';
80892 $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
80893
80894 if ($lowVersion === '0.0.0.0-dev') {
80895 return array(new Constraint('<', $highVersion));
80896 }
80897
80898 return array(
80899 new Constraint('>=', $lowVersion),
80900 new Constraint('<', $highVersion),
80901 );
80902 }
80903
80904
80905  
80906  
80907  
80908  
80909  
80910  if (preg_match('{^(?P<from>' . $versionRegex . ') +- +(?P<to>' . $versionRegex . ')($)}i', $constraint, $matches)) {
80911
80912  $lowStabilitySuffix = '';
80913 if (empty($matches[6]) && empty($matches[8])) {
80914 $lowStabilitySuffix = '-dev';
80915 }
80916
80917 $lowVersion = $this->normalize($matches['from']);
80918 $lowerBound = new Constraint('>=', $lowVersion . $lowStabilitySuffix);
80919
80920 $empty = function ($x) {
80921 return ($x === 0 || $x === '0') ? false : empty($x);
80922 };
80923
80924 if ((!$empty($matches[11]) && !$empty($matches[12])) || !empty($matches[14]) || !empty($matches[16])) {
80925 $highVersion = $this->normalize($matches['to']);
80926 $upperBound = new Constraint('<=', $highVersion);
80927 } else {
80928 $highMatch = array('', $matches[10], $matches[11], $matches[12], $matches[13]);
80929 $highVersion = $this->manipulateVersionString($highMatch, $empty($matches[11]) ? 1 : 2, 1) . '-dev';
80930 $upperBound = new Constraint('<', $highVersion);
80931 }
80932
80933 return array(
80934 $lowerBound,
80935 $upperBound,
80936 );
80937 }
80938
80939
80940  if (preg_match('{^(<>|!=|>=?|<=?|==?)?\s*(.*)}', $constraint, $matches)) {
80941 try {
80942 $version = $this->normalize($matches[2]);
80943
80944 if (!empty($stabilityModifier) && $this->parseStability($version) === 'stable') {
80945 $version .= '-' . $stabilityModifier;
80946 } elseif ('<' === $matches[1] || '>=' === $matches[1]) {
80947 if (!preg_match('/-' . self::$modifierRegex . '$/', strtolower($matches[2]))) {
80948 if (substr($matches[2], 0, 4) !== 'dev-') {
80949 $version .= '-dev';
80950 }
80951 }
80952 }
80953
80954 return array(new Constraint($matches[1] ?: '=', $version));
80955 } catch (\Exception $e) {
80956 }
80957 }
80958
80959 $message = 'Could not parse version constraint ' . $constraint;
80960 if (isset($e)) {
80961 $message .= ': ' . $e->getMessage();
80962 }
80963
80964 throw new \UnexpectedValueException($message);
80965 }
80966
80967
80968
80969
80970
80971
80972
80973
80974
80975
80976
80977
80978
80979 private function manipulateVersionString($matches, $position, $increment = 0, $pad = '0')
80980 {
80981 for ($i = 4; $i > 0; --$i) {
80982 if ($i > $position) {
80983 $matches[$i] = $pad;
80984 } elseif ($i === $position && $increment) {
80985 $matches[$i] += $increment;
80986
80987  if ($matches[$i] < 0) {
80988 $matches[$i] = $pad;
80989 --$position;
80990
80991
80992  if ($i === 1) {
80993 return;
80994 }
80995 }
80996 }
80997 }
80998
80999 return $matches[1] . '.' . $matches[2] . '.' . $matches[3] . '.' . $matches[4];
81000 }
81001
81002
81003
81004
81005
81006
81007
81008
81009 private function expandStability($stability)
81010 {
81011 $stability = strtolower($stability);
81012
81013 switch ($stability) {
81014 case 'a':
81015 return 'alpha';
81016 case 'b':
81017 return 'beta';
81018 case 'p':
81019 case 'pl':
81020 return 'patch';
81021 case 'rc':
81022 return 'RC';
81023 default:
81024 return $stability;
81025 }
81026 }
81027 }
81028 Copyright (C) 2016 Composer
81029
81030 Permission is hereby granted, free of charge, to any person obtaining a copy of
81031 this software and associated documentation files (the "Software"), to deal in
81032 the Software without restriction, including without limitation the rights to
81033 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
81034 of the Software, and to permit persons to whom the Software is furnished to do
81035 so, subject to the following conditions:
81036
81037 The above copyright notice and this permission notice shall be included in all
81038 copies or substantial portions of the Software.
81039
81040 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
81041 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
81042 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
81043 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
81044 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
81045 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
81046 SOFTWARE.
81047 <?php
81048
81049
81050
81051
81052
81053
81054
81055
81056
81057
81058 namespace Composer\CaBundle;
81059
81060 use Psr\Log\LoggerInterface;
81061 use Symfony\Component\Process\PhpProcess;
81062
81063
81064
81065
81066
81067 class CaBundle
81068 {
81069 private static $caPath;
81070 private static $caFileValidity = array();
81071 private static $useOpensslParse;
81072
81073
81074
81075
81076
81077
81078
81079
81080
81081
81082
81083
81084
81085
81086
81087
81088
81089
81090
81091
81092
81093
81094
81095
81096
81097
81098
81099
81100
81101
81102
81103
81104
81105
81106
81107
81108
81109
81110 public static function getSystemCaRootBundlePath(LoggerInterface $logger = null)
81111 {
81112 if (self::$caPath !== null) {
81113 return self::$caPath;
81114 }
81115
81116
81117  
81118  $envCertFile = getenv('SSL_CERT_FILE');
81119 if ($envCertFile && is_readable($envCertFile) && static::validateCaFile($envCertFile, $logger)) {
81120 return self::$caPath = $envCertFile;
81121 }
81122
81123
81124  
81125  $envCertDir = getenv('SSL_CERT_DIR');
81126 if ($envCertDir && is_dir($envCertDir) && is_readable($envCertDir)) {
81127 return self::$caPath = $envCertDir;
81128 }
81129
81130 $configured = ini_get('openssl.cafile');
81131 if ($configured && strlen($configured) > 0 && is_readable($configured) && static::validateCaFile($configured, $logger)) {
81132 return self::$caPath = $configured;
81133 }
81134
81135 $configured = ini_get('openssl.capath');
81136 if ($configured && is_dir($configured) && is_readable($configured)) {
81137 return self::$caPath = $configured;
81138 }
81139
81140 $caBundlePaths = array(
81141 '/etc/pki/tls/certs/ca-bundle.crt', 
81142  '/etc/ssl/certs/ca-certificates.crt', 
81143  '/etc/ssl/ca-bundle.pem', 
81144  '/usr/local/share/certs/ca-root-nss.crt', 
81145  '/usr/ssl/certs/ca-bundle.crt', 
81146  '/opt/local/share/curl/curl-ca-bundle.crt', 
81147  '/usr/local/share/curl/curl-ca-bundle.crt', 
81148  '/usr/share/ssl/certs/ca-bundle.crt', 
81149  '/etc/ssl/cert.pem', 
81150  '/usr/local/etc/ssl/cert.pem', 
81151  '/usr/local/etc/openssl/cert.pem', 
81152  );
81153
81154 foreach ($caBundlePaths as $caBundle) {
81155 if (@is_readable($caBundle) && static::validateCaFile($caBundle, $logger)) {
81156 return self::$caPath = $caBundle;
81157 }
81158 }
81159
81160 foreach ($caBundlePaths as $caBundle) {
81161 $caBundle = dirname($caBundle);
81162 if (@is_dir($caBundle) && glob($caBundle.'/*')) {
81163 return self::$caPath = $caBundle;
81164 }
81165 }
81166
81167 return self::$caPath = static::getBundledCaBundlePath(); 
81168  }
81169
81170
81171
81172
81173
81174
81175
81176
81177 public static function getBundledCaBundlePath()
81178 {
81179 return __DIR__.'/../res/cacert.pem';
81180 }
81181
81182
81183
81184
81185
81186
81187
81188
81189
81190 public static function validateCaFile($filename, LoggerInterface $logger = null)
81191 {
81192 static $warned = false;
81193
81194 if (isset(self::$caFileValidity[$filename])) {
81195 return self::$caFileValidity[$filename];
81196 }
81197
81198 $contents = file_get_contents($filename);
81199
81200
81201  
81202  if (!static::isOpensslParseSafe()) {
81203 if (!$warned && $logger) {
81204 $logger->warning(sprintf(
81205 'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.',
81206 PHP_VERSION
81207 ));
81208 $warned = true;
81209 }
81210
81211 $isValid = !empty($contents);
81212 } else {
81213 $isValid = (bool) openssl_x509_parse($contents);
81214 }
81215
81216 if ($logger) {
81217 $logger->debug('Checked CA file '.realpath($filename).': '.($isValid ? 'valid' : 'invalid'));
81218 }
81219
81220 return self::$caFileValidity[$filename] = $isValid;
81221 }
81222
81223
81224
81225
81226
81227
81228
81229
81230
81231 public static function isOpensslParseSafe()
81232 {
81233 if (null !== self::$useOpensslParse) {
81234 return self::$useOpensslParse;
81235 }
81236
81237 if (PHP_VERSION_ID >= 50600) {
81238 return self::$useOpensslParse = true;
81239 }
81240
81241
81242  
81243  
81244  
81245  if (
81246 (PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328)
81247 || (PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423)
81248 || (PHP_VERSION_ID < 50600 && PHP_VERSION_ID >= 50507)
81249 ) {
81250
81251  return self::$useOpensslParse = true;
81252 }
81253
81254 if (defined('PHP_WINDOWS_VERSION_BUILD')) {
81255
81256  return self::$useOpensslParse = false;
81257 }
81258
81259 $compareDistroVersionPrefix = function ($prefix, $fixedVersion) {
81260 $regex = '{^'.preg_quote($prefix).'([0-9]+)$}';
81261
81262 if (preg_match($regex, PHP_VERSION, $m)) {
81263 return ((int) $m[1]) >= $fixedVersion;
81264 }
81265
81266 return false;
81267 };
81268
81269
81270  if (
81271 $compareDistroVersionPrefix('5.3.3-7+squeeze', 18) 
81272  || $compareDistroVersionPrefix('5.4.4-14+deb7u', 7) 
81273  || $compareDistroVersionPrefix('5.3.10-1ubuntu3.', 9) 
81274  ) {
81275 return self::$useOpensslParse = true;
81276 }
81277
81278
81279  if (!class_exists('Symfony\Component\Process\PhpProcess')) {
81280 return self::$useOpensslParse = false;
81281 }
81282
81283
81284  
81285  
81286  
81287  
81288  
81289
81290
81291  
81292  $cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K';
81293 $script = <<<'EOT'
81294
81295 error_reporting(-1);
81296 $info = openssl_x509_parse(base64_decode('%s'));
81297 var_dump(PHP_VERSION, $info['issuer']['emailAddress'], $info['validFrom_time_t']);
81298
81299 EOT;
81300 $script = '<'."?php\n".sprintf($script, $cert);
81301
81302 try {
81303 $process = new PhpProcess($script);
81304 $process->mustRun();
81305 } catch (\Exception $e) {
81306
81307  
81308  return self::$useOpensslParse = false;
81309 }
81310
81311 $output = preg_split('{\r?\n}', trim($process->getOutput()));
81312 $errorOutput = trim($process->getErrorOutput());
81313
81314 if (
81315 count($output) === 3
81316 && $output[0] === sprintf('string(%d) "%s"', strlen(PHP_VERSION), PHP_VERSION)
81317 && $output[1] === 'string(27) "stefan.esser@sektioneins.de"'
81318 && $output[2] === 'int(-1)'
81319 && preg_match('{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput)
81320 ) {
81321
81322  return self::$useOpensslParse = true;
81323 }
81324
81325 return self::$useOpensslParse = false;
81326 }
81327
81328
81329
81330
81331 public static function reset()
81332 {
81333 self::$caFileValidity = array();
81334 self::$caPath = null;
81335 self::$useOpensslParse = null;
81336 }
81337 }
81338 Copyright (c) 2012 PHP Framework Interoperability Group
81339
81340 Permission is hereby granted, free of charge, to any person obtaining a copy 
81341 of this software and associated documentation files (the "Software"), to deal
81342 in the Software without restriction, including without limitation the rights 
81343 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
81344 copies of the Software, and to permit persons to whom the Software is 
81345 furnished to do so, subject to the following conditions:
81346
81347 The above copyright notice and this permission notice shall be included in 
81348 all copies or substantial portions of the Software.
81349
81350 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
81351 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
81352 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
81353 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
81354 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
81355 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
81356 THE SOFTWARE.
81357 <?php
81358
81359 namespace Psr\Log;
81360
81361
81362
81363
81364
81365
81366
81367
81368 abstract class AbstractLogger implements LoggerInterface
81369 {
81370
81371
81372
81373
81374
81375
81376
81377
81378 public function emergency($message, array $context = array())
81379 {
81380 $this->log(LogLevel::EMERGENCY, $message, $context);
81381 }
81382
81383
81384
81385
81386
81387
81388
81389
81390
81391
81392
81393
81394 public function alert($message, array $context = array())
81395 {
81396 $this->log(LogLevel::ALERT, $message, $context);
81397 }
81398
81399
81400
81401
81402
81403
81404
81405
81406
81407
81408
81409 public function critical($message, array $context = array())
81410 {
81411 $this->log(LogLevel::CRITICAL, $message, $context);
81412 }
81413
81414
81415
81416
81417
81418
81419
81420
81421
81422
81423 public function error($message, array $context = array())
81424 {
81425 $this->log(LogLevel::ERROR, $message, $context);
81426 }
81427
81428
81429
81430
81431
81432
81433
81434
81435
81436
81437
81438
81439 public function warning($message, array $context = array())
81440 {
81441 $this->log(LogLevel::WARNING, $message, $context);
81442 }
81443
81444
81445
81446
81447
81448
81449
81450
81451
81452 public function notice($message, array $context = array())
81453 {
81454 $this->log(LogLevel::NOTICE, $message, $context);
81455 }
81456
81457
81458
81459
81460
81461
81462
81463
81464
81465
81466
81467 public function info($message, array $context = array())
81468 {
81469 $this->log(LogLevel::INFO, $message, $context);
81470 }
81471
81472
81473
81474
81475
81476
81477
81478
81479
81480 public function debug($message, array $context = array())
81481 {
81482 $this->log(LogLevel::DEBUG, $message, $context);
81483 }
81484 }
81485 <?php
81486
81487 namespace Psr\Log;
81488
81489 class InvalidArgumentException extends \InvalidArgumentException
81490 {
81491 }
81492 <?php
81493
81494 namespace Psr\Log;
81495
81496
81497
81498
81499 class LogLevel
81500 {
81501 const EMERGENCY = 'emergency';
81502 const ALERT = 'alert';
81503 const CRITICAL = 'critical';
81504 const ERROR = 'error';
81505 const WARNING = 'warning';
81506 const NOTICE = 'notice';
81507 const INFO = 'info';
81508 const DEBUG = 'debug';
81509 }
81510 <?php
81511
81512 namespace Psr\Log;
81513
81514
81515
81516
81517 interface LoggerAwareInterface
81518 {
81519
81520
81521
81522
81523
81524
81525
81526 public function setLogger(LoggerInterface $logger);
81527 }
81528 <?php
81529
81530 namespace Psr\Log;
81531
81532
81533
81534
81535 trait LoggerAwareTrait
81536 {
81537
81538
81539
81540
81541
81542 protected $logger;
81543
81544
81545
81546
81547
81548
81549 public function setLogger(LoggerInterface $logger)
81550 {
81551 $this->logger = $logger;
81552 }
81553 }
81554 <?php
81555
81556 namespace Psr\Log;
81557
81558
81559
81560
81561
81562
81563
81564
81565
81566
81567
81568
81569
81570
81571
81572
81573 interface LoggerInterface
81574 {
81575
81576
81577
81578
81579
81580
81581
81582
81583 public function emergency($message, array $context = array());
81584
81585
81586
81587
81588
81589
81590
81591
81592
81593
81594
81595
81596 public function alert($message, array $context = array());
81597
81598
81599
81600
81601
81602
81603
81604
81605
81606
81607
81608 public function critical($message, array $context = array());
81609
81610
81611
81612
81613
81614
81615
81616
81617
81618
81619 public function error($message, array $context = array());
81620
81621
81622
81623
81624
81625
81626
81627
81628
81629
81630
81631
81632 public function warning($message, array $context = array());
81633
81634
81635
81636
81637
81638
81639
81640
81641
81642 public function notice($message, array $context = array());
81643
81644
81645
81646
81647
81648
81649
81650
81651
81652
81653
81654 public function info($message, array $context = array());
81655
81656
81657
81658
81659
81660
81661
81662
81663
81664 public function debug($message, array $context = array());
81665
81666
81667
81668
81669
81670
81671
81672
81673
81674
81675 public function log($level, $message, array $context = array());
81676 }
81677 <?php
81678
81679 namespace Psr\Log;
81680
81681
81682
81683
81684
81685
81686
81687
81688
81689 trait LoggerTrait
81690 {
81691
81692
81693
81694
81695
81696
81697
81698
81699 public function emergency($message, array $context = array())
81700 {
81701 $this->log(LogLevel::EMERGENCY, $message, $context);
81702 }
81703
81704
81705
81706
81707
81708
81709
81710
81711
81712
81713
81714
81715 public function alert($message, array $context = array())
81716 {
81717 $this->log(LogLevel::ALERT, $message, $context);
81718 }
81719
81720
81721
81722
81723
81724
81725
81726
81727
81728
81729
81730 public function critical($message, array $context = array())
81731 {
81732 $this->log(LogLevel::CRITICAL, $message, $context);
81733 }
81734
81735
81736
81737
81738
81739
81740
81741
81742
81743
81744 public function error($message, array $context = array())
81745 {
81746 $this->log(LogLevel::ERROR, $message, $context);
81747 }
81748
81749
81750
81751
81752
81753
81754
81755
81756
81757
81758
81759
81760 public function warning($message, array $context = array())
81761 {
81762 $this->log(LogLevel::WARNING, $message, $context);
81763 }
81764
81765
81766
81767
81768
81769
81770
81771
81772
81773 public function notice($message, array $context = array())
81774 {
81775 $this->log(LogLevel::NOTICE, $message, $context);
81776 }
81777
81778
81779
81780
81781
81782
81783
81784
81785
81786
81787
81788 public function info($message, array $context = array())
81789 {
81790 $this->log(LogLevel::INFO, $message, $context);
81791 }
81792
81793
81794
81795
81796
81797
81798
81799
81800
81801 public function debug($message, array $context = array())
81802 {
81803 $this->log(LogLevel::DEBUG, $message, $context);
81804 }
81805
81806
81807
81808
81809
81810
81811
81812
81813
81814
81815 abstract public function log($level, $message, array $context = array());
81816 }
81817 <?php
81818
81819 namespace Psr\Log;
81820
81821
81822
81823
81824
81825
81826
81827
81828
81829 class NullLogger extends AbstractLogger
81830 {
81831
81832
81833
81834
81835
81836
81837
81838
81839
81840 public function log($level, $message, array $context = array())
81841 {
81842
81843  }
81844 }
81845 <?php
81846
81847 namespace Psr\Log\Test;
81848
81849 use Psr\Log\LoggerInterface;
81850 use Psr\Log\LogLevel;
81851
81852
81853
81854
81855
81856
81857
81858 abstract class LoggerInterfaceTest extends \PHPUnit_Framework_TestCase
81859 {
81860
81861
81862
81863 abstract public function getLogger();
81864
81865
81866
81867
81868
81869
81870
81871
81872
81873
81874 abstract public function getLogs();
81875
81876 public function testImplements()
81877 {
81878 $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger());
81879 }
81880
81881
81882
81883
81884 public function testLogsAtAllLevels($level, $message)
81885 {
81886 $logger = $this->getLogger();
81887 $logger->{$level}($message, array('user' => 'Bob'));
81888 $logger->log($level, $message, array('user' => 'Bob'));
81889
81890 $expected = array(
81891 $level.' message of level '.$level.' with context: Bob',
81892 $level.' message of level '.$level.' with context: Bob',
81893 );
81894 $this->assertEquals($expected, $this->getLogs());
81895 }
81896
81897 public function provideLevelsAndMessages()
81898 {
81899 return array(
81900 LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'),
81901 LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'),
81902 LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'),
81903 LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'),
81904 LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'),
81905 LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'),
81906 LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'),
81907 LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'),
81908 );
81909 }
81910
81911
81912
81913
81914 public function testThrowsOnInvalidLevel()
81915 {
81916 $logger = $this->getLogger();
81917 $logger->log('invalid level', 'Foo');
81918 }
81919
81920 public function testContextReplacement()
81921 {
81922 $logger = $this->getLogger();
81923 $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));
81924
81925 $expected = array('info {Message {nothing} Bob Bar a}');
81926 $this->assertEquals($expected, $this->getLogs());
81927 }
81928
81929 public function testObjectCastToString()
81930 {
81931 if (method_exists($this, 'createPartialMock')) {
81932 $dummy = $this->createPartialMock('Psr\Log\Test\DummyTest', array('__toString'));
81933 } else {
81934 $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString'));
81935 }
81936 $dummy->expects($this->once())
81937 ->method('__toString')
81938 ->will($this->returnValue('DUMMY'));
81939
81940 $this->getLogger()->warning($dummy);
81941
81942 $expected = array('warning DUMMY');
81943 $this->assertEquals($expected, $this->getLogs());
81944 }
81945
81946 public function testContextCanContainAnything()
81947 {
81948 $context = array(
81949 'bool' => true,
81950 'null' => null,
81951 'string' => 'Foo',
81952 'int' => 0,
81953 'float' => 0.5,
81954 'nested' => array('with object' => new DummyTest),
81955 'object' => new \DateTime,
81956 'resource' => fopen('php://memory', 'r'),
81957 );
81958
81959 $this->getLogger()->warning('Crazy context data', $context);
81960
81961 $expected = array('warning Crazy context data');
81962 $this->assertEquals($expected, $this->getLogs());
81963 }
81964
81965 public function testContextExceptionKeyCanBeExceptionOrOtherValues()
81966 {
81967 $logger = $this->getLogger();
81968 $logger->warning('Random message', array('exception' => 'oops'));
81969 $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail')));
81970
81971 $expected = array(
81972 'warning Random message',
81973 'critical Uncaught Exception!'
81974 );
81975 $this->assertEquals($expected, $this->getLogs());
81976 }
81977 }
81978
81979 class DummyTest
81980 {
81981 public function __toString()
81982 {
81983 }
81984 }
81985 <?php
81986
81987
81988
81989 require_once __DIR__ . '/composer/autoload_real.php';
81990
81991 return ComposerAutoloaderInitComposerPhar1512135777::getLoader();
81992 <?php
81993
81994
81995
81996 $vendorDir = dirname(dirname(__FILE__));
81997 $baseDir = dirname($vendorDir);
81998
81999 return array(
82000 );
82001 <?php
82002
82003
82004
82005 $vendorDir = dirname(dirname(__FILE__));
82006 $baseDir = dirname($vendorDir);
82007
82008 return array(
82009 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
82010 'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
82011 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
82012 'Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'),
82013 'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'),
82014 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
82015 'Seld\\PharUtils\\' => array($vendorDir . '/seld/phar-utils/src'),
82016 'Seld\\JsonLint\\' => array($vendorDir . '/seld/jsonlint/src/Seld/JsonLint'),
82017 'Seld\\CliPrompt\\' => array($vendorDir . '/seld/cli-prompt/src'),
82018 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
82019 'JsonSchema\\' => array($vendorDir . '/justinrainbow/json-schema/src/JsonSchema'),
82020 'Composer\\Spdx\\' => array($vendorDir . '/composer/spdx-licenses/src'),
82021 'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),
82022 'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
82023 'Composer\\' => array($baseDir . '/src/Composer'),
82024 );
82025 <?php
82026
82027
82028
82029 $vendorDir = dirname(dirname(__FILE__));
82030 $baseDir = dirname($vendorDir);
82031
82032 return array(
82033 );
82034 <?php
82035
82036
82037
82038 $vendorDir = dirname(dirname(__FILE__));
82039 $baseDir = dirname($vendorDir);
82040
82041 return array(
82042 '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
82043 );
82044 <?php
82045
82046
82047
82048 class ComposerAutoloaderInitComposerPhar1512135777
82049 {
82050 private static $loader;
82051
82052 public static function loadClassLoader($class)
82053 {
82054 if ('Composer\Autoload\ClassLoader' === $class) {
82055 require __DIR__ . '/ClassLoader.php';
82056 }
82057 }
82058
82059 public static function getLoader()
82060 {
82061 if (null !== self::$loader) {
82062 return self::$loader;
82063 }
82064
82065 spl_autoload_register(array('ComposerAutoloaderInitComposerPhar1512135777', 'loadClassLoader'), true, true);
82066 self::$loader = $loader = new \Composer\Autoload\ClassLoader();
82067 spl_autoload_unregister(array('ComposerAutoloaderInitComposerPhar1512135777', 'loadClassLoader'));
82068
82069 $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
82070 if ($useStaticLoader) {
82071 require_once __DIR__ . '/autoload_static.php';
82072
82073 call_user_func(\Composer\Autoload\ComposerStaticInitComposerPhar1512135777::getInitializer($loader));
82074 } else {
82075 $map = require __DIR__ . '/autoload_namespaces.php';
82076 foreach ($map as $namespace => $path) {
82077 $loader->set($namespace, $path);
82078 }
82079
82080 $map = require __DIR__ . '/autoload_psr4.php';
82081 foreach ($map as $namespace => $path) {
82082 $loader->setPsr4($namespace, $path);
82083 }
82084
82085 $classMap = require __DIR__ . '/autoload_classmap.php';
82086 if ($classMap) {
82087 $loader->addClassMap($classMap);
82088 }
82089 }
82090
82091 $loader->register(true);
82092
82093 if ($useStaticLoader) {
82094 $includeFiles = Composer\Autoload\ComposerStaticInitComposerPhar1512135777::$files;
82095 } else {
82096 $includeFiles = require __DIR__ . '/autoload_files.php';
82097 }
82098 foreach ($includeFiles as $fileIdentifier => $file) {
82099 composerRequireComposerPhar1512135777($fileIdentifier, $file);
82100 }
82101
82102 return $loader;
82103 }
82104 }
82105
82106 function composerRequireComposerPhar1512135777($fileIdentifier, $file)
82107 {
82108 if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
82109 require $file;
82110
82111 $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
82112 }
82113 }
82114 <?php
82115
82116
82117
82118 namespace Composer\Autoload;
82119
82120 class ComposerStaticInitComposerPhar1512135777
82121 {
82122 public static $files = array (
82123 '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
82124 );
82125
82126 public static $prefixLengthsPsr4 = array (
82127 'S' => 
82128 array (
82129 'Symfony\\Polyfill\\Mbstring\\' => 26,
82130 'Symfony\\Component\\Process\\' => 26,
82131 'Symfony\\Component\\Finder\\' => 25,
82132 'Symfony\\Component\\Filesystem\\' => 29,
82133 'Symfony\\Component\\Debug\\' => 24,
82134 'Symfony\\Component\\Console\\' => 26,
82135 'Seld\\PharUtils\\' => 15,
82136 'Seld\\JsonLint\\' => 14,
82137 'Seld\\CliPrompt\\' => 15,
82138 ),
82139 'P' => 
82140 array (
82141 'Psr\\Log\\' => 8,
82142 ),
82143 'J' => 
82144 array (
82145 'JsonSchema\\' => 11,
82146 ),
82147 'C' => 
82148 array (
82149 'Composer\\Spdx\\' => 14,
82150 'Composer\\Semver\\' => 16,
82151 'Composer\\CaBundle\\' => 18,
82152 'Composer\\' => 9,
82153 ),
82154 );
82155
82156 public static $prefixDirsPsr4 = array (
82157 'Symfony\\Polyfill\\Mbstring\\' => 
82158 array (
82159 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
82160 ),
82161 'Symfony\\Component\\Process\\' => 
82162 array (
82163 0 => __DIR__ . '/..' . '/symfony/process',
82164 ),
82165 'Symfony\\Component\\Finder\\' => 
82166 array (
82167 0 => __DIR__ . '/..' . '/symfony/finder',
82168 ),
82169 'Symfony\\Component\\Filesystem\\' => 
82170 array (
82171 0 => __DIR__ . '/..' . '/symfony/filesystem',
82172 ),
82173 'Symfony\\Component\\Debug\\' => 
82174 array (
82175 0 => __DIR__ . '/..' . '/symfony/debug',
82176 ),
82177 'Symfony\\Component\\Console\\' => 
82178 array (
82179 0 => __DIR__ . '/..' . '/symfony/console',
82180 ),
82181 'Seld\\PharUtils\\' => 
82182 array (
82183 0 => __DIR__ . '/..' . '/seld/phar-utils/src',
82184 ),
82185 'Seld\\JsonLint\\' => 
82186 array (
82187 0 => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint',
82188 ),
82189 'Seld\\CliPrompt\\' => 
82190 array (
82191 0 => __DIR__ . '/..' . '/seld/cli-prompt/src',
82192 ),
82193 'Psr\\Log\\' => 
82194 array (
82195 0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
82196 ),
82197 'JsonSchema\\' => 
82198 array (
82199 0 => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema',
82200 ),
82201 'Composer\\Spdx\\' => 
82202 array (
82203 0 => __DIR__ . '/..' . '/composer/spdx-licenses/src',
82204 ),
82205 'Composer\\Semver\\' => 
82206 array (
82207 0 => __DIR__ . '/..' . '/composer/semver/src',
82208 ),
82209 'Composer\\CaBundle\\' => 
82210 array (
82211 0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
82212 ),
82213 'Composer\\' => 
82214 array (
82215 0 => __DIR__ . '/../..' . '/src/Composer',
82216 ),
82217 );
82218
82219 public static function getInitializer(ClassLoader $loader)
82220 {
82221 return \Closure::bind(function () use ($loader) {
82222 $loader->prefixLengthsPsr4 = ComposerStaticInitComposerPhar1512135777::$prefixLengthsPsr4;
82223 $loader->prefixDirsPsr4 = ComposerStaticInitComposerPhar1512135777::$prefixDirsPsr4;
82224
82225 }, null, ClassLoader::class);
82226 }
82227 }
82228 <?php
82229
82230
82231
82232
82233
82234
82235
82236
82237
82238
82239
82240 namespace Composer\Autoload;
82241
82242
82243
82244
82245
82246
82247
82248
82249
82250
82251
82252
82253
82254
82255
82256
82257
82258
82259
82260
82261
82262
82263
82264
82265
82266
82267
82268
82269
82270 class ClassLoader
82271 {
82272
82273  private $prefixLengthsPsr4 = array();
82274 private $prefixDirsPsr4 = array();
82275 private $fallbackDirsPsr4 = array();
82276
82277
82278  private $prefixesPsr0 = array();
82279 private $fallbackDirsPsr0 = array();
82280
82281 private $useIncludePath = false;
82282 private $classMap = array();
82283 private $classMapAuthoritative = false;
82284 private $missingClasses = array();
82285 private $apcuPrefix;
82286
82287 public function getPrefixes()
82288 {
82289 if (!empty($this->prefixesPsr0)) {
82290 return call_user_func_array('array_merge', $this->prefixesPsr0);
82291 }
82292
82293 return array();
82294 }
82295
82296 public function getPrefixesPsr4()
82297 {
82298 return $this->prefixDirsPsr4;
82299 }
82300
82301 public function getFallbackDirs()
82302 {
82303 return $this->fallbackDirsPsr0;
82304 }
82305
82306 public function getFallbackDirsPsr4()
82307 {
82308 return $this->fallbackDirsPsr4;
82309 }
82310
82311 public function getClassMap()
82312 {
82313 return $this->classMap;
82314 }
82315
82316
82317
82318
82319 public function addClassMap(array $classMap)
82320 {
82321 if ($this->classMap) {
82322 $this->classMap = array_merge($this->classMap, $classMap);
82323 } else {
82324 $this->classMap = $classMap;
82325 }
82326 }
82327
82328
82329
82330
82331
82332
82333
82334
82335
82336 public function add($prefix, $paths, $prepend = false)
82337 {
82338 if (!$prefix) {
82339 if ($prepend) {
82340 $this->fallbackDirsPsr0 = array_merge(
82341 (array) $paths,
82342 $this->fallbackDirsPsr0
82343 );
82344 } else {
82345 $this->fallbackDirsPsr0 = array_merge(
82346 $this->fallbackDirsPsr0,
82347 (array) $paths
82348 );
82349 }
82350
82351 return;
82352 }
82353
82354 $first = $prefix[0];
82355 if (!isset($this->prefixesPsr0[$first][$prefix])) {
82356 $this->prefixesPsr0[$first][$prefix] = (array) $paths;
82357
82358 return;
82359 }
82360 if ($prepend) {
82361 $this->prefixesPsr0[$first][$prefix] = array_merge(
82362 (array) $paths,
82363 $this->prefixesPsr0[$first][$prefix]
82364 );
82365 } else {
82366 $this->prefixesPsr0[$first][$prefix] = array_merge(
82367 $this->prefixesPsr0[$first][$prefix],
82368 (array) $paths
82369 );
82370 }
82371 }
82372
82373
82374
82375
82376
82377
82378
82379
82380
82381
82382
82383 public function addPsr4($prefix, $paths, $prepend = false)
82384 {
82385 if (!$prefix) {
82386
82387  if ($prepend) {
82388 $this->fallbackDirsPsr4 = array_merge(
82389 (array) $paths,
82390 $this->fallbackDirsPsr4
82391 );
82392 } else {
82393 $this->fallbackDirsPsr4 = array_merge(
82394 $this->fallbackDirsPsr4,
82395 (array) $paths
82396 );
82397 }
82398 } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
82399
82400  $length = strlen($prefix);
82401 if ('\\' !== $prefix[$length - 1]) {
82402 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
82403 }
82404 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
82405 $this->prefixDirsPsr4[$prefix] = (array) $paths;
82406 } elseif ($prepend) {
82407
82408  $this->prefixDirsPsr4[$prefix] = array_merge(
82409 (array) $paths,
82410 $this->prefixDirsPsr4[$prefix]
82411 );
82412 } else {
82413
82414  $this->prefixDirsPsr4[$prefix] = array_merge(
82415 $this->prefixDirsPsr4[$prefix],
82416 (array) $paths
82417 );
82418 }
82419 }
82420
82421
82422
82423
82424
82425
82426
82427
82428 public function set($prefix, $paths)
82429 {
82430 if (!$prefix) {
82431 $this->fallbackDirsPsr0 = (array) $paths;
82432 } else {
82433 $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
82434 }
82435 }
82436
82437
82438
82439
82440
82441
82442
82443
82444
82445
82446 public function setPsr4($prefix, $paths)
82447 {
82448 if (!$prefix) {
82449 $this->fallbackDirsPsr4 = (array) $paths;
82450 } else {
82451 $length = strlen($prefix);
82452 if ('\\' !== $prefix[$length - 1]) {
82453 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
82454 }
82455 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
82456 $this->prefixDirsPsr4[$prefix] = (array) $paths;
82457 }
82458 }
82459
82460
82461
82462
82463
82464
82465 public function setUseIncludePath($useIncludePath)
82466 {
82467 $this->useIncludePath = $useIncludePath;
82468 }
82469
82470
82471
82472
82473
82474
82475
82476 public function getUseIncludePath()
82477 {
82478 return $this->useIncludePath;
82479 }
82480
82481
82482
82483
82484
82485
82486
82487 public function setClassMapAuthoritative($classMapAuthoritative)
82488 {
82489 $this->classMapAuthoritative = $classMapAuthoritative;
82490 }
82491
82492
82493
82494
82495
82496
82497 public function isClassMapAuthoritative()
82498 {
82499 return $this->classMapAuthoritative;
82500 }
82501
82502
82503
82504
82505
82506
82507 public function setApcuPrefix($apcuPrefix)
82508 {
82509 $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
82510 }
82511
82512
82513
82514
82515
82516
82517 public function getApcuPrefix()
82518 {
82519 return $this->apcuPrefix;
82520 }
82521
82522
82523
82524
82525
82526
82527 public function register($prepend = false)
82528 {
82529 spl_autoload_register(array($this, 'loadClass'), true, $prepend);
82530 }
82531
82532
82533
82534
82535 public function unregister()
82536 {
82537 spl_autoload_unregister(array($this, 'loadClass'));
82538 }
82539
82540
82541
82542
82543
82544
82545
82546 public function loadClass($class)
82547 {
82548 if ($file = $this->findFile($class)) {
82549 includeFile($file);
82550
82551 return true;
82552 }
82553 }
82554
82555
82556
82557
82558
82559
82560
82561
82562 public function findFile($class)
82563 {
82564
82565  if (isset($this->classMap[$class])) {
82566 return $this->classMap[$class];
82567 }
82568 if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
82569 return false;
82570 }
82571 if (null !== $this->apcuPrefix) {
82572 $file = apcu_fetch($this->apcuPrefix.$class, $hit);
82573 if ($hit) {
82574 return $file;
82575 }
82576 }
82577
82578 $file = $this->findFileWithExtension($class, '.php');
82579
82580
82581  if (false === $file && defined('HHVM_VERSION')) {
82582 $file = $this->findFileWithExtension($class, '.hh');
82583 }
82584
82585 if (null !== $this->apcuPrefix) {
82586 apcu_add($this->apcuPrefix.$class, $file);
82587 }
82588
82589 if (false === $file) {
82590
82591  $this->missingClasses[$class] = true;
82592 }
82593
82594 return $file;
82595 }
82596
82597 private function findFileWithExtension($class, $ext)
82598 {
82599
82600  $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
82601
82602 $first = $class[0];
82603 if (isset($this->prefixLengthsPsr4[$first])) {
82604 $subPath = $class;
82605 while (false !== $lastPos = strrpos($subPath, '\\')) {
82606 $subPath = substr($subPath, 0, $lastPos);
82607 $search = $subPath.'\\';
82608 if (isset($this->prefixDirsPsr4[$search])) {
82609 foreach ($this->prefixDirsPsr4[$search] as $dir) {
82610 $length = $this->prefixLengthsPsr4[$first][$search];
82611 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
82612 return $file;
82613 }
82614 }
82615 }
82616 }
82617 }
82618
82619
82620  foreach ($this->fallbackDirsPsr4 as $dir) {
82621 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
82622 return $file;
82623 }
82624 }
82625
82626
82627  if (false !== $pos = strrpos($class, '\\')) {
82628
82629  $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
82630 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
82631 } else {
82632
82633  $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
82634 }
82635
82636 if (isset($this->prefixesPsr0[$first])) {
82637 foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
82638 if (0 === strpos($class, $prefix)) {
82639 foreach ($dirs as $dir) {
82640 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
82641 return $file;
82642 }
82643 }
82644 }
82645 }
82646 }
82647
82648
82649  foreach ($this->fallbackDirsPsr0 as $dir) {
82650 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
82651 return $file;
82652 }
82653 }
82654
82655
82656  if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
82657 return $file;
82658 }
82659
82660 return false;
82661 }
82662 }
82663
82664
82665
82666
82667
82668
82669 function includeFile($file)
82670 {
82671 include $file;
82672 }
82673 ##
82674 ## Bundle of CA Root Certificates
82675 ##
82676 ## Certificate data from Mozilla as of: Wed Jun  7 03:12:05 2017 GMT
82677 ##
82678 ## This is a bundle of X.509 certificates of public Certificate Authorities
82679 ## (CA). These were automatically extracted from Mozilla's root certificates
82680 ## file (certdata.txt).  This file can be found in the mozilla source tree:
82681 ## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt
82682 ##
82683 ## It contains the certificates in PEM format and therefore
82684 ## can be directly used with curl / libcurl / php_curl, or with
82685 ## an Apache+mod_ssl webserver for SSL client authentication.
82686 ## Just configure this file as the SSLCACertificateFile.
82687 ##
82688 ## Conversion done with mk-ca-bundle.pl version 1.27.
82689 ## SHA256: 93753268e1c596aee21893fb1c6975338389132f15c942ed65fc394a904371d7
82690 ##
82691
82692
82693 GlobalSign Root CA
82694 ==================
82695 -----BEGIN CERTIFICATE-----
82696 MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx
82697 GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds
82698 b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV
82699 BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD
82700 VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa
82701 DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc
82702 THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb
82703 Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP
82704 c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX
82705 gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
82706 HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF
82707 AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj
82708 Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG
82709 j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH
82710 hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC
82711 X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
82712 -----END CERTIFICATE-----
82713
82714 GlobalSign Root CA - R2
82715 =======================
82716 -----BEGIN CERTIFICATE-----
82717 MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv
82718 YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
82719 bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
82720 aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
82721 bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6
82722 ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp
82723 s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN
82724 S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL
82725 TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C
82726 ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
82727 FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i
82728 YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN
82729 BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp
82730 9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu
82731 01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7
82732 9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
82733 TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
82734 -----END CERTIFICATE-----
82735
82736 Verisign Class 3 Public Primary Certification Authority - G3
82737 ============================================================
82738 -----BEGIN CERTIFICATE-----
82739 MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV
82740 UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
82741 cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
82742 IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh
82743 dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw
82744 CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy
82745 dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv
82746 cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg
82747 Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
82748 ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1
82749 EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc
82750 cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw
82751 EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj
82752 055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
82753 ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f
82754 j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
82755 /Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0
82756 xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa
82757 t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
82758 -----END CERTIFICATE-----
82759
82760 Entrust.net Premium 2048 Secure Server CA
82761 =========================================
82762 -----BEGIN CERTIFICATE-----
82763 MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u
82764 ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp
82765 bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV
82766 BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx
82767 NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3
82768 d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl
82769 MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u
82770 ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
82771 MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL
82772 Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr
82773 hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW
82774 nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi
82775 VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E
82776 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ
82777 KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy
82778 T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
82779 zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT
82780 J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e
82781 nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE=
82782 -----END CERTIFICATE-----
82783
82784 Baltimore CyberTrust Root
82785 =========================
82786 -----BEGIN CERTIFICATE-----
82787 MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE
82788 ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li
82789 ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC
82790 SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs
82791 dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME
82792 uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB
82793 UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C
82794 G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9
82795 XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr
82796 l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI
82797 VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB
82798 BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh
82799 cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5
82800 hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa
82801 Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H
82802 RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
82803 -----END CERTIFICATE-----
82804
82805 AddTrust Low-Value Services Root
82806 ================================
82807 -----BEGIN CERTIFICATE-----
82808 MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
82809 QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRU
82810 cnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMwMTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQsw
82811 CQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBO
82812 ZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEB
82813 AQUAA4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ulCDtbKRY6
82814 54eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6ntGO0/7Gcrjyvd7ZWxbWr
82815 oulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyldI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1
82816 Zmne3yzxbrww2ywkEtvrNTVokMsAsJchPXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJui
82817 GMx1I4S+6+JNM3GOGvDC+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8w
82818 HQYDVR0OBBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8EBTAD
82819 AQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBlMQswCQYDVQQGEwJT
82820 RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEw
82821 HwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxt
82822 ZBsfzQ3duQH6lmM0MkhHma6X7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0Ph
82823 iVYrqW9yTkkz43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY
82824 eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJlpz/+0WatC7xr
82825 mYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOAWiFeIc9TVPC6b4nbqKqVz4vj
82826 ccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk=
82827 -----END CERTIFICATE-----
82828
82829 AddTrust External Root
82830 ======================
82831 -----BEGIN CERTIFICATE-----
82832 MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
82833 QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD
82834 VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw
82835 NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU
82836 cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg
82837 Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821
82838 +iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw
82839 Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo
82840 aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy
82841 2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7
82842 7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P
82843 BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL
82844 VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk
82845 VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB
82846 IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl
82847 j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
82848 6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355
82849 e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u
82850 G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
82851 -----END CERTIFICATE-----
82852
82853 AddTrust Public Services Root
82854 =============================
82855 -----BEGIN CERTIFICATE-----
82856 MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
82857 QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSAwHgYDVQQDExdBZGRU
82858 cnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAxMDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJ
82859 BgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5l
82860 dHdvcmsxIDAeBgNVBAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEF
82861 AAOCAQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV6tsfSlbu
82862 nyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nXGCwwfQ56HmIexkvA/X1i
82863 d9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnPdzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSG
82864 Aa2Il+tmzV7R/9x98oTaunet3IAIx6eH1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAw
82865 HM+A+WD+eeSI8t0A65RF62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0G
82866 A1UdDgQWBBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
82867 /zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDELMAkGA1UEBhMCU0Ux
82868 FDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29yazEgMB4G
82869 A1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4
82870 JNojVhaTdt02KLmuG7jD8WS6IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL
82871 +YPoRNWyQSW/iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao
82872 GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh4SINhwBk/ox9
82873 Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQmXiLsks3/QppEIW1cxeMiHV9H
82874 EufOX1362KqxMy3ZdvJOOjMMK7MtkAY=
82875 -----END CERTIFICATE-----
82876
82877 AddTrust Qualified Certificates Root
82878 ====================================
82879 -----BEGIN CERTIFICATE-----
82880 MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
82881 QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSMwIQYDVQQDExpBZGRU
82882 cnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcx
82883 CzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQ
82884 IE5ldHdvcmsxIzAhBgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG
82885 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwqxBb/4Oxx
82886 64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G87B4pfYOQnrjfxvM0PC3
82887 KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i2O+tCBGaKZnhqkRFmhJePp1tUvznoD1o
82888 L/BLcHwTOK28FSXx1s6rosAx1i+f4P8UWfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GR
82889 wVY18BTcZTYJbqukB8c10cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HU
82890 MIHRMB0GA1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/
82891 BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6FrpGkwZzELMAkGA1UE
82892 BhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29y
82893 azEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlmaWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQAD
82894 ggEBABmrder4i2VhlRO6aQTvhsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxG
82895 GuoYQ992zPlmhpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X
82896 dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3P6CxB9bpT9ze
82897 RXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9YiQBCYz95OdBEsIJuQRno3eDB
82898 iFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5noxqE=
82899 -----END CERTIFICATE-----
82900
82901 Entrust Root Certification Authority
82902 ====================================
82903 -----BEGIN CERTIFICATE-----
82904 MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV
82905 BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw
82906 b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG
82907 A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0
82908 MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu
82909 MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu
82910 Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v
82911 dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
82912 ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz
82913 A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww
82914 Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68
82915 j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN
82916 rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw
82917 DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1
82918 MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH
82919 hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
82920 A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM
82921 Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa
82922 v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS
82923 W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0
82924 tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8
82925 -----END CERTIFICATE-----
82926
82927 GeoTrust Global CA
82928 ==================
82929 -----BEGIN CERTIFICATE-----
82930 MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
82931 Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw
82932 MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
82933 LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
82934 CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo
82935 BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet
82936 8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc
82937 T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU
82938 vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD
82939 AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk
82940 DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q
82941 zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4
82942 d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2
82943 mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p
82944 XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm
82945 Mw==
82946 -----END CERTIFICATE-----
82947
82948 GeoTrust Global CA 2
82949 ====================
82950 -----BEGIN CERTIFICATE-----
82951 MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
82952 R2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwHhcNMDQwMzA0MDUw
82953 MDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
82954 LjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
82955 ggEKAoIBAQDvPE1APRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/
82956 NTL8Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hLTytCOb1k
82957 LUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL5mkWRxHCJ1kDs6ZgwiFA
82958 Vvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7S4wMcoKK+xfNAGw6EzywhIdLFnopsk/b
82959 HdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQF
82960 MAMBAf8wHQYDVR0OBBYEFHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNH
82961 K266ZUapEBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6tdEPx7
82962 srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv/NgdRN3ggX+d6Yvh
82963 ZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywNA0ZF66D0f0hExghAzN4bcLUprbqL
82964 OzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkC
82965 x1YAzUm5s2x7UwQa4qjJqhIFI8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqF
82966 H4z1Ir+rzoPz4iIprn2DQKi6bA==
82967 -----END CERTIFICATE-----
82968
82969 GeoTrust Universal CA
82970 =====================
82971 -----BEGIN CERTIFICATE-----
82972 MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
82973 R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1
82974 MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu
82975 Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
82976 ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t
82977 JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e
82978 RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs
82979 7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d
82980 8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V
82981 qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga
82982 Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB
82983 Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu
82984 KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08
82985 ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0
82986 XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB
82987 hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
82988 aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2
82989 qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL
82990 oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK
82991 xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF
82992 KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2
82993 DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK
82994 xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU
82995 p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI
82996 P/rmMuGNG2+k5o7Y+SlIis5z/iw=
82997 -----END CERTIFICATE-----
82998
82999 GeoTrust Universal CA 2
83000 =======================
83001 -----BEGIN CERTIFICATE-----
83002 MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
83003 R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0
83004 MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg
83005 SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA
83006 A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0
83007 DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17
83008 j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q
83009 JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a
83010 QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2
83011 WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP
83012 20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn
83013 ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC
83014 SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG
83015 8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2
83016 +/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E
83017 BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
83018 dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ
83019 4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+
83020 mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq
83021 A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg
83022 Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP
83023 pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d
83024 FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp
83025 gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm
83026 X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
83027 -----END CERTIFICATE-----
83028
83029 Visa eCommerce Root
83030 ===================
83031 -----BEGIN CERTIFICATE-----
83032 MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQG
83033 EwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2Ug
83034 QXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2
83035 WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMm
83036 VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv
83037 bW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfL
83038 F9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8b
83039 RaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0
83040 TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI
83041 /k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzs
83042 GHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG
83043 MB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxc
83044 CLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUW
83045 YFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pz
83046 zkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu
83047 YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt
83048 398znM/jra6O1I7mT1GvFpLgXPYHDw==
83049 -----END CERTIFICATE-----
83050
83051 Certum Root CA
83052 ==============
83053 -----BEGIN CERTIFICATE-----
83054 MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQK
83055 ExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQTAeFw0wMjA2MTExMDQ2Mzla
83056 Fw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8u
83057 by4xEjAQBgNVBAMTCUNlcnR1bSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6x
83058 wS7TT3zNJc4YPk/EjG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdL
83059 kKWoePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GIULdtlkIJ
83060 89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapuOb7kky/ZR6By6/qmW6/K
83061 Uz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUgAKpoC6EahQGcxEZjgoi2IrHu/qpGWX7P
83062 NSzVttpd90gzFFS269lvzs2I1qsb2pY7HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkq
83063 hkiG9w0BAQUFAAOCAQEAuI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+
83064 GXYkHAQaTOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTgxSvg
83065 GrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1qCjqTE5s7FCMTY5w/
83066 0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5xO/fIR/RpbxXyEV6DHpx8Uq79AtoS
83067 qFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs6GAqm4VKQPNriiTsBhYscw==
83068 -----END CERTIFICATE-----
83069
83070 Comodo AAA Services root
83071 ========================
83072 -----BEGIN CERTIFICATE-----
83073 MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
83074 R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
83075 TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw
83076 MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl
83077 c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV
83078 BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
83079 ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG
83080 C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs
83081 i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW
83082 Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH
83083 Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK
83084 Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f
83085 BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl
83086 cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz
83087 LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm
83088 7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
83089 Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z
83090 8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C
83091 12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
83092 -----END CERTIFICATE-----
83093
83094 Comodo Secure Services root
83095 ===========================
83096 -----BEGIN CERTIFICATE-----
83097 MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
83098 R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
83099 TGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAw
83100 MDAwMFoXDTI4MTIzMTIzNTk1OVowfjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFu
83101 Y2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAi
83102 BgNVBAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
83103 ADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPMcm3ye5drswfxdySRXyWP
83104 9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3SHpR7LZQdqnXXs5jLrLxkU0C8j6ysNstc
83105 rbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rC
83106 oznl2yY4rYsK7hljxxwk3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3V
83107 p6ea5EQz6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNVHQ4E
83108 FgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w
83109 gYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1NlY3VyZUNlcnRpZmlj
83110 YXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRwOi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlm
83111 aWNhdGVTZXJ2aWNlcy5jcmwwDQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm
83112 4J4oqF7Tt/Q05qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj
83113 Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtIgKvcnDe4IRRL
83114 DXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJaD61JlfutuC23bkpgHl9j6Pw
83115 pCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDlizeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1H
83116 RR3B7Hzs/Sk=
83117 -----END CERTIFICATE-----
83118
83119 Comodo Trusted Services root
83120 ============================
83121 -----BEGIN CERTIFICATE-----
83122 MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
83123 R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
83124 TGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEw
83125 MDAwMDBaFw0yODEyMzEyMzU5NTlaMH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1h
83126 bmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUw
83127 IwYDVQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0BAQEFAAOC
83128 AQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWWfnJSoBVC21ndZHoa0Lh7
83129 3TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMtTGo87IvDktJTdyR0nAducPy9C1t2ul/y
83130 /9c3S0pgePfw+spwtOpZqqPOSC+pw7ILfhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6
83131 juljatEPmsbS9Is6FARW1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsS
83132 ivnkBbA7kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0GA1Ud
83133 DgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
83134 /zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21vZG9jYS5jb20vVHJ1c3RlZENlcnRp
83135 ZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRodHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENl
83136 cnRpZmljYXRlU2VydmljZXMuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8Ntw
83137 uleGFTQQuS9/HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32
83138 pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxISjBc/lDb+XbDA
83139 BHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+xqFx7D+gIIxmOom0jtTYsU0l
83140 R+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/AtyjcndBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O
83141 9y5Xt5hwXsjEeLBi
83142 -----END CERTIFICATE-----
83143
83144 QuoVadis Root CA
83145 ================
83146 -----BEGIN CERTIFICATE-----
83147 MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE
83148 ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
83149 eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz
83150 MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp
83151 cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD
83152 EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
83153 AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk
83154 J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL
83155 F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL
83156 YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen
83157 AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w
83158 PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y
83159 ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7
83160 MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj
83161 YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs
83162 ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh
83163 Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW
83164 Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu
83165 BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw
83166 FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0
83167 aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6
83168 tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo
83169 fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul
83170 LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x
83171 gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi
83172 5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi
83173 5nrQNiOKSnQ2+Q==
83174 -----END CERTIFICATE-----
83175
83176 QuoVadis Root CA 2
83177 ==================
83178 -----BEGIN CERTIFICATE-----
83179 MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
83180 EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx
83181 ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
83182 aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC
83183 DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6
83184 XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk
83185 lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB
83186 lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy
83187 lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt
83188 66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn
83189 wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh
83190 D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy
83191 BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie
83192 J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud
83193 DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU
83194 a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
83195 ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv
83196 Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3
83197 UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm
83198 VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK
83199 +JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW
83200 IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1
83201 WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X
83202 f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II
83203 4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8
83204 VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
83205 -----END CERTIFICATE-----
83206
83207 QuoVadis Root CA 3
83208 ==================
83209 -----BEGIN CERTIFICATE-----
83210 MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
83211 EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx
83212 OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
83213 aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
83214 DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg
83215 DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij
83216 KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K
83217 DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv
83218 BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp
83219 p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8
83220 nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX
83221 MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM
83222 Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz
83223 uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT
83224 BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj
83225 YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
83226 aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB
83227 BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD
83228 VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4
83229 ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE
83230 AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV
83231 qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s
83232 hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z
83233 POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2
83234 Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp
83235 8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC
83236 bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu
83237 g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p
83238 vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr
83239 qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=
83240 -----END CERTIFICATE-----
83241
83242 Security Communication Root CA
83243 ==============================
83244 -----BEGIN CERTIFICATE-----
83245 MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
83246 U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
83247 HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
83248 U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
83249 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw
83250 8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM
83251 DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX
83252 5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd
83253 DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2
83254 JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw
83255 DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g
83256 0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a
83257 mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ
83258 s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ
83259 6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi
83260 FL39vmwLAw==
83261 -----END CERTIFICATE-----
83262
83263 Sonera Class 2 Root CA
83264 ======================
83265 -----BEGIN CERTIFICATE-----
83266 MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG
83267 U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw
83268 NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh
83269 IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3
83270 /Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT
83271 dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG
83272 f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P
83273 tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH
83274 nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT
83275 XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt
83276 0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI
83277 cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph
83278 Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx
83279 EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH
83280 llpwrN9M
83281 -----END CERTIFICATE-----
83282
83283 UTN USERFirst Hardware Root CA
83284 ==============================
83285 -----BEGIN CERTIFICATE-----
83286 MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UE
83287 BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl
83288 IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAd
83289 BgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgx
83290 OTIyWjCBlzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0
83291 eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVz
83292 ZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwggEiMA0GCSqGSIb3
83293 DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlI
83294 wrthdBKWHTxqctU8EGc6Oe0rE81m65UJM6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFd
83295 tqdt++BxF2uiiPsA3/4aMXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8
83296 i4fDidNdoI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqIDsjf
83297 Pe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9KsyoUhbAgMBAAGjgbkw
83298 gbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKFyXyYbKJhDlV0HN9WF
83299 lp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNF
83300 UkZpcnN0LUhhcmR3YXJlLmNybDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUF
83301 BwMGBggrBgEFBQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM
83302 //bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28GpgoiskliCE7/yMgUsogW
83303 XecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gECJChicsZUN/KHAG8HQQZexB2
83304 lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kn
83305 iCrVWFCVH/A7HFe7fRQ5YiuayZSSKqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67
83306 nfhmqA==
83307 -----END CERTIFICATE-----
83308
83309 Camerfirma Chambers of Commerce Root
83310 ====================================
83311 -----BEGIN CERTIFICATE-----
83312 MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe
83313 QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i
83314 ZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAx
83315 NjEzNDNaFw0zNzA5MzAxNjEzNDRaMH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZp
83316 cm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3Jn
83317 MSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0BAQEFAAOC
83318 AQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtbunXF/KGIJPov7coISjlU
83319 xFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0dBmpAPrMMhe5cG3nCYsS4No41XQEMIwRH
83320 NaqbYE6gZj3LJgqcQKH0XZi/caulAGgq7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jW
83321 DA+wWFjbw2Y3npuRVDM30pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFV
83322 d9oKDMyXroDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIGA1Ud
83323 EwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5jaGFtYmVyc2lnbi5v
83324 cmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p26EpW1eLTXYGduHRooowDgYDVR0P
83325 AQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hh
83326 bWJlcnNpZ24ub3JnMCcGA1UdEgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYD
83327 VR0gBFEwTzBNBgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz
83328 aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAAxBl8IahsAi
83329 fJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZdp0AJPaxJRUXcLo0waLIJuvvD
83330 L8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wN
83331 UPf6s+xCX6ndbcj0dc97wXImsQEcXCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/n
83332 ADydb47kMgkdTXg0eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1
83333 erfutGWaIZDgqtCYvDi1czyL+Nw=
83334 -----END CERTIFICATE-----
83335
83336 Camerfirma Global Chambersign Root
83337 ==================================
83338 -----BEGIN CERTIFICATE-----
83339 MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe
83340 QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i
83341 ZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYx
83342 NDE4WhcNMzcwOTMwMTYxNDE4WjB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJt
83343 YSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEg
83344 MB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAw
83345 ggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0Mi+ITaFgCPS3CU6gSS9J
83346 1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/sQJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8O
83347 by4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpVeAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl
83348 6DJWk0aJqCWKZQbua795B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c
83349 8lCrEqWhz0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0TAQH/
83350 BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1iZXJzaWduLm9yZy9j
83351 aGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4wTcbOX60Qq+UDpfqpFDAOBgNVHQ8B
83352 Af8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAHMCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBj
83353 aGFtYmVyc2lnbi5vcmcwKgYDVR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9y
83354 ZzBbBgNVHSAEVDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh
83355 bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEA
83356 PDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUMbKGKfKX0j//U2K0X1S0E0T9Y
83357 gOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXiryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJ
83358 PJ7oKXqJ1/6v/2j1pReQvayZzKWGVwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4
83359 IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes
83360 t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A==
83361 -----END CERTIFICATE-----
83362
83363 XRamp Global CA Root
83364 ====================
83365 -----BEGIN CERTIFICATE-----
83366 MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE
83367 BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj
83368 dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
83369 dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx
83370 HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg
83371 U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
83372 dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu
83373 IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx
83374 foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE
83375 zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs
83376 AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry
83377 xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
83378 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap
83379 oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC
83380 AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc
83381 /Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
83382 qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n
83383 nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz
83384 8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw=
83385 -----END CERTIFICATE-----
83386
83387 Go Daddy Class 2 CA
83388 ===================
83389 -----BEGIN CERTIFICATE-----
83390 MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY
83391 VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp
83392 ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG
83393 A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
83394 RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD
83395 ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
83396 2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32
83397 qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j
83398 YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY
83399 vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O
83400 BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o
83401 atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu
83402 MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG
83403 A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim
83404 PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt
83405 I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
83406 HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI
83407 Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b
83408 vZ8=
83409 -----END CERTIFICATE-----
83410
83411 Starfield Class 2 CA
83412 ====================
83413 -----BEGIN CERTIFICATE-----
83414 MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc
83415 U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg
83416 Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo
83417 MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG
83418 A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG
83419 SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY
83420 bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ
83421 JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm
83422 epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN
83423 F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF
83424 MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f
83425 hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo
83426 bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g
83427 QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs
83428 afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM
83429 PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
83430 xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD
83431 KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3
83432 QBFGmh95DmK/D5fs4C8fF5Q=
83433 -----END CERTIFICATE-----
83434
83435 StartCom Certification Authority
83436 ================================
83437 -----BEGIN CERTIFICATE-----
83438 MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
83439 U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu
83440 ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0
83441 NjM2WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk
83442 LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg
83443 U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
83444 ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y
83445 o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/
83446 Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d
83447 eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt
83448 2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z
83449 6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ
83450 osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/
83451 untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc
83452 UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT
83453 37uMdBNSSwIDAQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
83454 FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9jZXJ0LnN0YXJ0
83455 Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3JsLnN0YXJ0Y29tLm9yZy9zZnNj
83456 YS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFMBgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUH
83457 AgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRw
83458 Oi8vY2VydC5zdGFydGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYg
83459 U3RhcnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlhYmlsaXR5
83460 LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2YgdGhlIFN0YXJ0Q29tIENl
83461 cnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFpbGFibGUgYXQgaHR0cDovL2NlcnQuc3Rh
83462 cnRjb20ub3JnL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilT
83463 dGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOC
83464 AgEAFmyZ9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8jhvh
83465 3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUWFjgKXlf2Ysd6AgXm
83466 vB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJzewT4F+irsfMuXGRuczE6Eri8sxHk
83467 fY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3
83468 fsNrarnDy0RLrHiQi+fHLB5LEUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZ
83469 EoalHmdkrQYuL6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
83470 yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuCO3NJo2pXh5Tl
83471 1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6Vum0ABj6y6koQOdjQK/W/7HW/
83472 lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkyShNOsF/5oirpt9P/FlUQqmMGqz9IgcgA38coro
83473 g14=
83474 -----END CERTIFICATE-----
83475
83476 Taiwan GRCA
83477 ===========
83478 -----BEGIN CERTIFICATE-----
83479 MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG
83480 EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X
83481 DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv
83482 dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD
83483 ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN
83484 w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5
83485 BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O
83486 1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO
83487 htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov
83488 J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7
83489 Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t
83490 B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB
83491 O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8
83492 lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV
83493 HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2
83494 09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ
83495 TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj
83496 Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2
83497 Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU
83498 D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz
83499 DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk
83500 Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk
83501 7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ
83502 CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy
83503 +fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS
83504 -----END CERTIFICATE-----
83505
83506 Swisscom Root CA 1
83507 ==================
83508 -----BEGIN CERTIFICATE-----
83509 MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQG
83510 EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy
83511 dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4
83512 MTgyMjA2MjBaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln
83513 aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIIC
83514 IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9m2BtRsiM
83515 MW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdihFvkcxC7mlSpnzNApbjyF
83516 NDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/TilftKaNXXsLmREDA/7n29uj/x2lzZAe
83517 AR81sH8A25Bvxn570e56eqeqDFdvpG3FEzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkC
83518 b6dJtDZd0KTeByy2dbcokdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn
83519 7uHbHaBuHYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNFvJbN
83520 cA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo19AOeCMgkckkKmUp
83521 WyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjCL3UcPX7ape8eYIVpQtPM+GP+HkM5
83522 haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJWbjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNY
83523 MUJDLXT5xp6mig/p/r+D5kNXJLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw
83524 HQYDVR0hBBYwFDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j
83525 BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzcK6FptWfUjNP9
83526 MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzfky9NfEBWMXrrpA9gzXrzvsMn
83527 jgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7IkVh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQ
83528 MbFamIp1TpBcahQq4FJHgmDmHtqBsfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4H
83529 VtA4oJVwIHaM190e3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtl
83530 vrsRls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ipmXeascCl
83531 OS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HHb6D0jqTsNFFbjCYDcKF3
83532 1QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksfrK/7DZBaZmBwXarNeNQk7shBoJMBkpxq
83533 nvy5JMWzFYJ+vq6VK+uxwNrjAWALXmmshFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCy
83534 x/yP2FS1k2Kdzs9Z+z0YzirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMW
83535 NY6E0F/6MBr1mmz0DlP5OlvRHA==
83536 -----END CERTIFICATE-----
83537
83538 DigiCert Assured ID Root CA
83539 ===========================
83540 -----BEGIN CERTIFICATE-----
83541 MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG
83542 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
83543 IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx
83544 MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
83545 ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew
83546 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO
83547 9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy
83548 UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW
83549 /lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy
83550 oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf
83551 GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF
83552 66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq
83553 hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc
83554 EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn
83555 SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i
83556 8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
83557 +o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
83558 -----END CERTIFICATE-----
83559
83560 DigiCert Global Root CA
83561 =======================
83562 -----BEGIN CERTIFICATE-----
83563 MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG
83564 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
83565 HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw
83566 MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
83567 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq
83568 hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn
83569 TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5
83570 BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H
83571 4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y
83572 7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB
83573 o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm
83574 8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF
83575 BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr
83576 EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt
83577 tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886
83578 UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
83579 CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
83580 -----END CERTIFICATE-----
83581
83582 DigiCert High Assurance EV Root CA
83583 ==================================
83584 -----BEGIN CERTIFICATE-----
83585 MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG
83586 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw
83587 KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw
83588 MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ
83589 MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu
83590 Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t
83591 Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS
83592 OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3
83593 MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ
83594 NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe
83595 h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB
83596 Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY
83597 JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ
83598 V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp
83599 myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK
83600 mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
83601 vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K
83602 -----END CERTIFICATE-----
83603
83604 Certplus Class 2 Primary CA
83605 ===========================
83606 -----BEGIN CERTIFICATE-----
83607 MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkGA1UE
83608 BhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkgQ0EwHhcN
83609 OTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2Vy
83610 dHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
83611 ADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR
83612 5aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyLkcAbmXuZ
83613 Vg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCdEgETjdyAYveVqUSISnFO
83614 YFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yasH7WLO7dDWWuwJKZtkIvEcupdM5i3y95e
83615 e++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRME
83616 CDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJ
83617 YIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29t
83618 L0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvD
83619 P9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1R
83620 TtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+
83621 7UCmnYR0ObncHoUW2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW
83622 //1IMwrh3KWBkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7
83623 l7+ijrRU
83624 -----END CERTIFICATE-----
83625
83626 DST Root CA X3
83627 ==============
83628 -----BEGIN CERTIFICATE-----
83629 MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK
83630 ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X
83631 DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1
83632 cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD
83633 ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT
83634 rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9
83635 UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy
83636 xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d
83637 utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T
83638 AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ
83639 MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug
83640 dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE
83641 GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw
83642 RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS
83643 fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
83644 -----END CERTIFICATE-----
83645
83646 DST ACES CA X6
83647 ==============
83648 -----BEGIN CERTIFICATE-----
83649 MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQG
83650 EwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QxETAPBgNVBAsTCERTVCBBQ0VT
83651 MRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0wMzExMjAyMTE5NThaFw0xNzExMjAyMTE5NTha
83652 MFsxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UE
83653 CxMIRFNUIEFDRVMxFzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOC
83654 AQ8AMIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPuktKe1jzI
83655 DZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7gLFViYsx+tC3dr5BPTCa
83656 pCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZHfAjIgrrep4c9oW24MFbCswKBXy314pow
83657 GCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4aahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPy
83658 MjwmR/onJALJfh1biEITajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1Ud
83659 EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rkc3Qu
83660 Y29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnRy
83661 dXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMtaW5kZXguaHRtbDAdBgNVHQ4EFgQU
83662 CXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZIhvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V2
83663 5FYrnJmQ6AgwbN99Pe7lv7UkQIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6t
83664 Fr8hlxCBPeP/h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq
83665 nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpRrscL9yuwNwXs
83666 vFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf29w4LTJxoeHtxMcfrHuBnQfO3
83667 oKfN5XozNmr6mis=
83668 -----END CERTIFICATE-----
83669
83670 SwissSign Gold CA - G2
83671 ======================
83672 -----BEGIN CERTIFICATE-----
83673 MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw
83674 EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN
83675 MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp
83676 c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B
83677 AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq
83678 t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C
83679 jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg
83680 vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF
83681 ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR
83682 AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend
83683 jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO
83684 peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR
83685 7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi
83686 GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw
83687 AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64
83688 OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
83689 L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm
83690 5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr
83691 44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf
83692 Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m
83693 Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp
83694 mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk
83695 vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf
83696 KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br
83697 NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj
83698 viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
83699 -----END CERTIFICATE-----
83700
83701 SwissSign Silver CA - G2
83702 ========================
83703 -----BEGIN CERTIFICATE-----
83704 MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT
83705 BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X
83706 DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3
83707 aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG
83708 9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644
83709 N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm
83710 +/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH
83711 6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu
83712 MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h
83713 qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5
83714 FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs
83715 ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc
83716 celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X
83717 CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
83718 BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB
83719 tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0
83720 cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P
83721 4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F
83722 kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L
83723 3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx
83724 /uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa
83725 DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP
83726 e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu
83727 WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ
83728 DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub
83729 DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
83730 -----END CERTIFICATE-----
83731
83732 GeoTrust Primary Certification Authority
83733 ========================================
83734 -----BEGIN CERTIFICATE-----
83735 MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG
83736 EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD
83737 ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx
83738 CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ
83739 cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
83740 CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN
83741 b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9
83742 nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge
83743 RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt
83744 tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
83745 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI
83746 hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K
83747 Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN
83748 NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa
83749 Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG
83750 1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
83751 -----END CERTIFICATE-----
83752
83753 thawte Primary Root CA
83754 ======================
83755 -----BEGIN CERTIFICATE-----
83756 MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE
83757 BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
83758 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
83759 cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3
83760 MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg
83761 SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv
83762 KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT
83763 FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs
83764 oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ
83765 1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc
83766 q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K
83767 aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p
83768 afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
83769 VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF
83770 AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE
83771 uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
83772 xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89
83773 jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH
83774 z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA==
83775 -----END CERTIFICATE-----
83776
83777 VeriSign Class 3 Public Primary Certification Authority - G5
83778 ============================================================
83779 -----BEGIN CERTIFICATE-----
83780 MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
83781 BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
83782 ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
83783 IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp
83784 ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB
83785 yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln
83786 biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh
83787 dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt
83788 YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
83789 ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz
83790 j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD
83791 Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/
83792 Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r
83793 fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/
83794 BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv
83795 Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
83796 aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
83797 SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+
83798 X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE
83799 KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC
83800 Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE
83801 ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
83802 -----END CERTIFICATE-----
83803
83804 SecureTrust CA
83805 ==============
83806 -----BEGIN CERTIFICATE-----
83807 MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG
83808 EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy
83809 dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe
83810 BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC
83811 ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX
83812 OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t
83813 DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH
83814 GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b
83815 01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH
83816 ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/
83817 BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj
83818 aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
83819 KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu
83820 SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf
83821 mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ
83822 nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
83823 3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
83824 -----END CERTIFICATE-----
83825
83826 Secure Global CA
83827 ================
83828 -----BEGIN CERTIFICATE-----
83829 MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG
83830 EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH
83831 bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg
83832 MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg
83833 Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx
83834 YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ
83835 bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g
83836 8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV
83837 HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi
83838 0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
83839 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn
83840 oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA
83841 MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+
83842 OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn
83843 CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5
83844 3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
83845 f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
83846 -----END CERTIFICATE-----
83847
83848 COMODO Certification Authority
83849 ==============================
83850 -----BEGIN CERTIFICATE-----
83851 MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE
83852 BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
83853 A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1
83854 dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb
83855 MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD
83856 T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
83857 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH
83858 +7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww
83859 xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV
83860 4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA
83861 1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI
83862 rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E
83863 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k
83864 b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC
83865 AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP
83866 OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
83867 RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc
83868 IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN
83869 +8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ==
83870 -----END CERTIFICATE-----
83871
83872 Network Solutions Certificate Authority
83873 =======================================
83874 -----BEGIN CERTIFICATE-----
83875 MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG
83876 EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr
83877 IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx
83878 MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
83879 MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G
83880 CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx
83881 jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT
83882 aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT
83883 crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc
83884 /Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB
83885 AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP
83886 BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv
83887 bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA
83888 A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q
83889 4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/
83890 GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
83891 wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD
83892 ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
83893 -----END CERTIFICATE-----
83894
83895 COMODO ECC Certification Authority
83896 ==================================
83897 -----BEGIN CERTIFICATE-----
83898 MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC
83899 R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
83900 ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB
83901 dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix
83902 GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
83903 Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo
83904 b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X
83905 4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni
83906 wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E
83907 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG
83908 FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA
83909 U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
83910 -----END CERTIFICATE-----
83911
83912 Security Communication EV RootCA1
83913 =================================
83914 -----BEGIN CERTIFICATE-----
83915 MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
83916 U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMhU2VjdXJpdHkgQ29tbXVuaWNh
83917 dGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIzMloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UE
83918 BhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNl
83919 Y3VyaXR5IENvbW11bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
83920 AQoCggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSERMqm4miO
83921 /VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gOzXppFodEtZDkBp2uoQSX
83922 WHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4z
83923 ZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDFMxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4
83924 bepJz11sS6/vmsJWXMY1VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK
83925 9U2vP9eCOKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
83926 SIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HWtWS3irO4G8za+6xm
83927 iEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZq51ihPZRwSzJIxXYKLerJRO1RuGG
83928 Av8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDbEJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnW
83929 mHyojf6GPgcWkuF75x3sM3Z+Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEW
83930 T1MKZPlO9L9OVL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490
83931 -----END CERTIFICATE-----
83932
83933 OISTE WISeKey Global Root GA CA
83934 ===============================
83935 -----BEGIN CERTIFICATE-----
83936 MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE
83937 BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG
83938 A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH
83939 bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD
83940 VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw
83941 IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5
83942 IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9
83943 Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg
83944 Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD
83945 d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ
83946 /yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R
83947 LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw
83948 AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
83949 KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm
83950 MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4
83951 +vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa
83952 hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY
83953 okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0=
83954 -----END CERTIFICATE-----
83955
83956 Certigna
83957 ========
83958 -----BEGIN CERTIFICATE-----
83959 MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw
83960 EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3
83961 MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI
83962 Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q
83963 XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH
83964 GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p
83965 ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg
83966 DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf
83967 Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ
83968 tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ
83969 BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J
83970 SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA
83971 hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+
83972 ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu
83973 PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY
83974 1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
83975 WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
83976 -----END CERTIFICATE-----
83977
83978 Deutsche Telekom Root CA 2
83979 ==========================
83980 -----BEGIN CERTIFICATE-----
83981 MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT
83982 RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG
83983 A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5
83984 MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G
83985 A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS
83986 b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5
83987 bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI
83988 KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY
83989 AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK
83990 Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV
83991 jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV
83992 HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr
83993 E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy
83994 zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8
83995 rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G
83996 dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU
83997 Cm26OWMohpLzGITY+9HPBVZkVw==
83998 -----END CERTIFICATE-----
83999
84000 Cybertrust Global Root
84001 ======================
84002 -----BEGIN CERTIFICATE-----
84003 MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li
84004 ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4
84005 MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD
84006 ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
84007 +Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW
84008 0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL
84009 AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin
84010 89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT
84011 8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP
84012 BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2
84013 MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G
84014 A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO
84015 lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi
84016 5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2
84017 hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T
84018 X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
84019 WL1WMRJOEcgh4LMRkWXbtKaIOM5V
84020 -----END CERTIFICATE-----
84021
84022 ePKI Root Certification Authority
84023 =================================
84024 -----BEGIN CERTIFICATE-----
84025 MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG
84026 EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg
84027 Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx
84028 MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq
84029 MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B
84030 AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs
84031 IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi
84032 lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv
84033 qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX
84034 12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O
84035 WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+
84036 ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao
84037 lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/
84038 vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi
84039 Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi
84040 MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
84041 ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0
84042 1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq
84043 KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV
84044 xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP
84045 NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r
84046 GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE
84047 xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx
84048 gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy
84049 sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD
84050 BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw=
84051 -----END CERTIFICATE-----
84052
84053 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
84054 =============================================================================================================================
84055 -----BEGIN CERTIFICATE-----
84056 MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRSMRgwFgYDVQQH
84057 DA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJpbGltc2VsIHZlIFRla25vbG9q
84058 aWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSwVEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ry
84059 b25payB2ZSBLcmlwdG9sb2ppIEFyYcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNV
84060 BAsMGkthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUg
84061 S8O2ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAeFw0wNzA4
84062 MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIxGDAWBgNVBAcMD0dlYnpl
84063 IC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmlsaW1zZWwgdmUgVGVrbm9sb2ppayBBcmHF
84064 n3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBUQUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZl
84065 IEtyaXB0b2xvamkgQXJhxZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2Ft
84066 dSBTZXJ0aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7ZrIFNl
84067 cnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIBIjANBgkqhkiG9w0B
84068 AQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4hgb46ezzb8R1Sf1n68yJMlaCQvEhO
84069 Eav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yKO7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1
84070 xnnRFDDtG1hba+818qEhTsXOfJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR
84071 6Oqeyjh1jmKwlZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL
84072 hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQIDAQABo0IwQDAd
84073 BgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
84074 MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmPNOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4
84075 N5EY3ATIZJkrGG2AA1nJrvhY0D7twyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLT
84076 y9LQQfMmNkqblWwM7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYh
84077 LBOhgLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5noN+J1q2M
84078 dqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUsyZyQ2uypQjyttgI=
84079 -----END CERTIFICATE-----
84080
84081 certSIGN ROOT CA
84082 ================
84083 -----BEGIN CERTIFICATE-----
84084 MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD
84085 VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa
84086 Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE
84087 CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I
84088 JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH
84089 rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2
84090 ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD
84091 0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943
84092 AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B
84093 Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB
84094 AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8
84095 SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0
84096 x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt
84097 vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz
84098 TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD
84099 -----END CERTIFICATE-----
84100
84101 CNNIC ROOT
84102 ==========
84103 -----BEGIN CERTIFICATE-----
84104 MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJDTjEOMAwGA1UE
84105 ChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2MDcwOTE0WhcNMjcwNDE2MDcw
84106 OTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1Qw
84107 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzD
84108 o+/hn7E7SIX1mlwhIhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tiz
84109 VHa6dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZOV/kbZKKT
84110 VrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrCGHn2emU1z5DrvTOTn1Or
84111 czvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gNv7Sg2Ca+I19zN38m5pIEo3/PIKe38zrK
84112 y5nLAgMBAAGjczBxMBEGCWCGSAGG+EIBAQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscC
84113 wQ7vptU7ETAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991S
84114 lgrHAsEO76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnKOOK5
84115 Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvHugDnuL8BV8F3RTIM
84116 O/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7HgviyJA/qIYM/PmLXoXLT1tLYhFHxUV8
84117 BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fLbuXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2
84118 G8kS1sHNzYDzAgE8yGnLRUhj2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5m
84119 mxE=
84120 -----END CERTIFICATE-----
84121
84122 GeoTrust Primary Certification Authority - G3
84123 =============================================
84124 -----BEGIN CERTIFICATE-----
84125 MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE
84126 BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0
84127 IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy
84128 eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz
84129 NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo
84130 YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT
84131 LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI
84132 hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j
84133 K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE
84134 c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C
84135 IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu
84136 dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC
84137 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr
84138 2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9
84139 cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE
84140 Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
84141 AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s
84142 t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt
84143 -----END CERTIFICATE-----
84144
84145 thawte Primary Root CA - G2
84146 ===========================
84147 -----BEGIN CERTIFICATE-----
84148 MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC
84149 VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu
84150 IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg
84151 Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV
84152 MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG
84153 b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt
84154 IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS
84155 LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5
84156 8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU
84157 mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN
84158 G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K
84159 rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
84160 -----END CERTIFICATE-----
84161
84162 thawte Primary Root CA - G3
84163 ===========================
84164 -----BEGIN CERTIFICATE-----
84165 MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE
84166 BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
84167 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
84168 cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w
84169 ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
84170 d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD
84171 VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG
84172 A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
84173 MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At
84174 P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC
84175 +BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY
84176 7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW
84177 vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E
84178 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ
84179 KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK
84180 A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu
84181 t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC
84182 8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm
84183 er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A=
84184 -----END CERTIFICATE-----
84185
84186 GeoTrust Primary Certification Authority - G2
84187 =============================================
84188 -----BEGIN CERTIFICATE-----
84189 MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC
84190 VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu
84191 Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD
84192 ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1
84193 OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
84194 MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl
84195 b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG
84196 BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc
84197 KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD
84198 VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+
84199 EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m
84200 ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2
84201 npaqBA+K
84202 -----END CERTIFICATE-----
84203
84204 VeriSign Universal Root Certification Authority
84205 ===============================================
84206 -----BEGIN CERTIFICATE-----
84207 MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE
84208 BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
84209 ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
84210 IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u
84211 IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV
84212 UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
84213 cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
84214 IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0
84215 aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj
84216 1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP
84217 MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72
84218 9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I
84219 AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR
84220 tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G
84221 CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O
84222 a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
84223 DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3
84224 Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx
84225 Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx
84226 P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P
84227 wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4
84228 mJO37M2CYfE45k+XmCpajQ==
84229 -----END CERTIFICATE-----
84230
84231 VeriSign Class 3 Public Primary Certification Authority - G4
84232 ============================================================
84233 -----BEGIN CERTIFICATE-----
84234 MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC
84235 VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3
84236 b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz
84237 ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj
84238 YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL
84239 MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU
84240 cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo
84241 b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5
84242 IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8
84243 Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz
84244 rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB
84245 /zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw
84246 HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u
84247 Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD
84248 A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx
84249 AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
84250 -----END CERTIFICATE-----
84251
84252 NetLock Arany (Class Gold) Főtanúsítvány
84253 ========================================
84254 -----BEGIN CERTIFICATE-----
84255 MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G
84256 A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610
84257 dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB
84258 cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx
84259 MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO
84260 ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv
84261 biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6
84262 c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu
84263 0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw
84264 /HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk
84265 H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw
84266 fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1
84267 neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB
84268 BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW
84269 qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta
84270 YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
84271 bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna
84272 NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu
84273 dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
84274 -----END CERTIFICATE-----
84275
84276 Staat der Nederlanden Root CA - G2
84277 ==================================
84278 -----BEGIN CERTIFICATE-----
84279 MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
84280 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
84281 Um9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oXDTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMC
84282 TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
84283 ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ
84284 5291qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8SpuOUfiUtn
84285 vWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPUZ5uW6M7XxgpT0GtJlvOj
84286 CwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvEpMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiil
84287 e7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCR
84288 OME4HYYEhLoaJXhena/MUGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpI
84289 CT0ugpTNGmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy5V65
84290 48r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv6q012iDTiIJh8BIi
84291 trzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEKeN5KzlW/HdXZt1bv8Hb/C3m1r737
84292 qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMB
84293 AAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcC
84294 ARYxaHR0cDovL3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV
84295 HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqGSIb3DQEBCwUA
84296 A4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLySCZa59sCrI2AGeYwRTlHSeYAz
84297 +51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwj
84298 f/ST7ZwaUb7dRUG/kSS0H4zpX897IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaN
84299 kqbG9AclVMwWVxJKgnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfk
84300 CpYL+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxLvJxxcypF
84301 URmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkmbEgeqmiSBeGCc1qb3Adb
84302 CG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvkN1trSt8sV4pAWja63XVECDdCcAz+3F4h
84303 oKOKwJCcaNpQ5kUQR3i2TtJlycM33+FCY7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoV
84304 IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm
84305 66+KAQ==
84306 -----END CERTIFICATE-----
84307
84308 Hongkong Post Root CA 1
84309 =======================
84310 -----BEGIN CERTIFICATE-----
84311 MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT
84312 DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx
84313 NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n
84314 IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF
84315 AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1
84316 ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr
84317 auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh
84318 qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY
84319 V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV
84320 HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i
84321 h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio
84322 l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei
84323 IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps
84324 T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT
84325 c4afU9hDDl3WY4JxHYB0yvbiAmvZWg==
84326 -----END CERTIFICATE-----
84327
84328 SecureSign RootCA11
84329 ===================
84330 -----BEGIN CERTIFICATE-----
84331 MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi
84332 SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS
84333 b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw
84334 KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1
84335 cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL
84336 TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO
84337 wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq
84338 g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP
84339 O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA
84340 bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX
84341 t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh
84342 OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r
84343 bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ
84344 Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01
84345 y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061
84346 lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I=
84347 -----END CERTIFICATE-----
84348
84349 ACEDICOM Root
84350 =============
84351 -----BEGIN CERTIFICATE-----
84352 MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UEAwwNQUNFRElD
84353 T00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMB4XDTA4
84354 MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEWMBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoG
84355 A1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEF
84356 AAOCAg8AMIICCgKCAgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHk
84357 WLn709gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7XBZXehuD
84358 YAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5PGrjm6gSSrj0RuVFCPYew
84359 MYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAKt0SdE3QrwqXrIhWYENiLxQSfHY9g5QYb
84360 m8+5eaA9oiM/Qj9r+hwDezCNzmzAv+YbX79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbk
84361 HQl/Sog4P75n/TSW9R28MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTT
84362 xKJxqvQUfecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI2Sf2
84363 3EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyHK9caUPgn6C9D4zq9
84364 2Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEaeZAwUswdbxcJzbPEHXEUkFDWug/Fq
84365 TYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz
84366 4SsrSbbXc6GqlPUB53NlTKxQMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU
84367 9QHnc2VMrFAwRAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv
84368 bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWImfQwng4/F9tqg
84369 aHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3gvoFNTPhNahXwOf9jU8/kzJP
84370 eGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKeI6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1Pwk
84371 zQSulgUV1qzOMPPKC8W64iLgpq0i5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1
84372 ThCojz2GuHURwCRiipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oI
84373 KiMnMCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZo5NjEFIq
84374 nxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6zqylfDJKZ0DcMDQj3dcE
84375 I2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacNGHk0vFQYXlPKNFHtRQrmjseCNj6nOGOp
84376 MCwXEGCSn1WHElkQwg9naRHMTh5+Spqtr0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3o
84377 tkYNbn5XOmeUwssfnHdKZ05phkOTOPu220+DkdRgfks+KzgHVZhepA==
84378 -----END CERTIFICATE-----
84379
84380 Microsec e-Szigno Root CA 2009
84381 ==============================
84382 -----BEGIN CERTIFICATE-----
84383 MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER
84384 MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv
84385 c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
84386 dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE
84387 BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt
84388 U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw
84389 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA
84390 fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG
84391 0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA
84392 pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm
84393 1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC
84394 AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf
84395 QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE
84396 FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o
84397 lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX
84398 I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
84399 tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02
84400 yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi
84401 LXpUq3DDfSJlgnCW
84402 -----END CERTIFICATE-----
84403
84404 GlobalSign Root CA - R3
84405 =======================
84406 -----BEGIN CERTIFICATE-----
84407 MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv
84408 YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
84409 bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
84410 aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
84411 bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt
84412 iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ
84413 0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3
84414 rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl
84415 OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2
84416 xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
84417 FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7
84418 lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8
84419 EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E
84420 bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18
84421 YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r
84422 kpeDMdmztcpHWD9f
84423 -----END CERTIFICATE-----
84424
84425 Autoridad de Certificacion Firmaprofesional CIF A62634068
84426 =========================================================
84427 -----BEGIN CERTIFICATE-----
84428 MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA
84429 BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
84430 MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw
84431 QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB
84432 NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD
84433 Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P
84434 B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY
84435 7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH
84436 ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI
84437 plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX
84438 MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX
84439 LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK
84440 bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU
84441 vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud
84442 EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH
84443 DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
84444 cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA
84445 bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx
84446 ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx
84447 51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk
84448 R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP
84449 T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f
84450 Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl
84451 osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR
84452 crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR
84453 saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD
84454 KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi
84455 6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
84456 -----END CERTIFICATE-----
84457
84458 Izenpe.com
84459 ==========
84460 -----BEGIN CERTIFICATE-----
84461 MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG
84462 EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz
84463 MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu
84464 QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ
84465 03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK
84466 ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU
84467 +zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC
84468 PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT
84469 OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK
84470 F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK
84471 0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+
84472 0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB
84473 leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID
84474 AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+
84475 SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG
84476 NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
84477 MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
84478 BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l
84479 Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga
84480 kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q
84481 hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs
84482 g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5
84483 aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5
84484 nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC
84485 ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo
84486 Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z
84487 WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
84488 -----END CERTIFICATE-----
84489
84490 Chambers of Commerce Root - 2008
84491 ================================
84492 -----BEGIN CERTIFICATE-----
84493 MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD
84494 MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
84495 bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
84496 QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy
84497 Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl
84498 ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF
84499 EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl
84500 cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
84501 AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA
84502 XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj
84503 h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/
84504 ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk
84505 NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g
84506 D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331
84507 lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ
84508 0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj
84509 ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2
84510 EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI
84511 G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ
84512 BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh
84513 bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh
84514 bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC
84515 CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH
84516 AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1
84517 wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH
84518 3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU
84519 RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6
84520 M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1
84521 YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF
84522 9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK
84523 zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG
84524 nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg
84525 OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ
84526 -----END CERTIFICATE-----
84527
84528 Global Chambersign Root - 2008
84529 ==============================
84530 -----BEGIN CERTIFICATE-----
84531 MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD
84532 MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
84533 bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
84534 QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx
84535 NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg
84536 Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ
84537 QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD
84538 aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf
84539 VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf
84540 XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0
84541 ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB
84542 /gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA
84543 TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M
84544 H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe
84545 Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF
84546 HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh
84547 wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB
84548 AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT
84549 BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE
84550 BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm
84551 aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm
84552 aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp
84553 1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0
84554 dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG
84555 /5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6
84556 ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s
84557 dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg
84558 9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH
84559 foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du
84560 qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr
84561 P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq
84562 c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z
84563 09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B
84564 -----END CERTIFICATE-----
84565
84566 Go Daddy Root Certificate Authority - G2
84567 ========================================
84568 -----BEGIN CERTIFICATE-----
84569 MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
84570 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu
84571 MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
84572 MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
84573 b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G
84574 A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
84575 hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq
84576 9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD
84577 +qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd
84578 fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl
84579 NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC
84580 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9
84581 BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac
84582 vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r
84583 5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV
84584 N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
84585 LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1
84586 -----END CERTIFICATE-----
84587
84588 Starfield Root Certificate Authority - G2
84589 =========================================
84590 -----BEGIN CERTIFICATE-----
84591 MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
84592 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
84593 b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0
84594 eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw
84595 DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg
84596 VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB
84597 dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv
84598 W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs
84599 bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk
84600 N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf
84601 ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU
84602 JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
84603 AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol
84604 TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx
84605 4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw
84606 F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
84607 pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ
84608 c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
84609 -----END CERTIFICATE-----
84610
84611 Starfield Services Root Certificate Authority - G2
84612 ==================================================
84613 -----BEGIN CERTIFICATE-----
84614 MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
84615 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
84616 b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl
84617 IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV
84618 BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT
84619 dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg
84620 Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
84621 AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2
84622 h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa
84623 hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP
84624 LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB
84625 rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
84626 AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG
84627 SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP
84628 E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy
84629 xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
84630 iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza
84631 YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6
84632 -----END CERTIFICATE-----
84633
84634 AffirmTrust Commercial
84635 ======================
84636 -----BEGIN CERTIFICATE-----
84637 MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS
84638 BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw
84639 MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
84640 bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF
84641 AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb
84642 DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV
84643 C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6
84644 BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww
84645 MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV
84646 HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
84647 AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG
84648 hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi
84649 qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv
84650 0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh
84651 sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
84652 -----END CERTIFICATE-----
84653
84654 AffirmTrust Networking
84655 ======================
84656 -----BEGIN CERTIFICATE-----
84657 MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS
84658 BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw
84659 MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
84660 bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF
84661 AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE
84662 Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI
84663 dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24
84664 /PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb
84665 h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV
84666 HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
84667 AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu
84668 UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6
84669 12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23
84670 WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9
84671 /ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
84672 -----END CERTIFICATE-----
84673
84674 AffirmTrust Premium
84675 ===================
84676 -----BEGIN CERTIFICATE-----
84677 MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS
84678 BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy
84679 OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy
84680 dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
84681 MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn
84682 BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV
84683 5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs
84684 +7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd
84685 GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R
84686 p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI
84687 S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04
84688 6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5
84689 /bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo
84690 +Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB
84691 /wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv
84692 MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
84693 Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC
84694 6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S
84695 L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK
84696 +4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV
84697 BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg
84698 IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60
84699 g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb
84700 zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw==
84701 -----END CERTIFICATE-----
84702
84703 AffirmTrust Premium ECC
84704 =======================
84705 -----BEGIN CERTIFICATE-----
84706 MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV
84707 BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx
84708 MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U
84709 cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA
84710 IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ
84711 N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW
84712 BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK
84713 BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X
84714 57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM
84715 eQ==
84716 -----END CERTIFICATE-----
84717
84718 Certum Trusted Network CA
84719 =========================
84720 -----BEGIN CERTIFICATE-----
84721 MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK
84722 ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv
84723 biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy
84724 MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU
84725 ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
84726 MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
84727 AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC
84728 l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J
84729 J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4
84730 fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0
84731 cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB
84732 Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw
84733 DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj
84734 jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1
84735 mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj
84736 Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
84737 03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
84738 -----END CERTIFICATE-----
84739
84740 Certinomis - Autorité Racine
84741 ============================
84742 -----BEGIN CERTIFICATE-----
84743 MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjETMBEGA1UEChMK
84744 Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAkBgNVBAMMHUNlcnRpbm9taXMg
84745 LSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkG
84746 A1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYw
84747 JAYDVQQDDB1DZXJ0aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQAD
84748 ggIPADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jYF1AMnmHa
84749 wE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N8y4oH3DfVS9O7cdxbwly
84750 Lu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWerP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw
84751 2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92N
84752 jMD2AR5vpTESOH2VwnHu7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9q
84753 c1pkIuVC28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6lSTC
84754 lrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1Enn1So2+WLhl+HPNb
84755 xxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB0iSVL1N6aaLwD4ZFjliCK0wi1F6g
84756 530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql095gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna
84757 4NH4+ej9Uji29YnfAgMBAAGjWzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
84758 A1UdDgQWBBQNjLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ
84759 KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9sov3/4gbIOZ/x
84760 WqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZMOH8oMDX/nyNTt7buFHAAQCva
84761 R6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40
84762 nJ+U8/aGH88bc62UeYdocMMzpXDn2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1B
84763 CxMjidPJC+iKunqjo3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjv
84764 JL1vnxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG5ERQL1TE
84765 qkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWqpdEdnV1j6CTmNhTih60b
84766 WfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZbdsLLO7XSAPCjDuGtbkD326C00EauFddE
84767 wk01+dIL8hf2rGbVJLJP0RyZwG71fet0BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/
84768 vgt2Fl43N+bYdJeimUV5
84769 -----END CERTIFICATE-----
84770
84771 TWCA Root Certification Authority
84772 =================================
84773 -----BEGIN CERTIFICATE-----
84774 MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ
84775 VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh
84776 dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG
84777 EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB
84778 IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
84779 AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx
84780 QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC
84781 oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP
84782 4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r
84783 y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB
84784 BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG
84785 9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC
84786 mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW
84787 QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY
84788 T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny
84789 Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
84790 -----END CERTIFICATE-----
84791
84792 Security Communication RootCA2
84793 ==============================
84794 -----BEGIN CERTIFICATE-----
84795 MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
84796 U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh
84797 dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC
84798 SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy
84799 aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
84800 ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++
84801 +T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R
84802 3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV
84803 spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K
84804 EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8
84805 QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
84806 CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj
84807 u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk
84808 3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q
84809 tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29
84810 mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
84811 -----END CERTIFICATE-----
84812
84813 EC-ACC
84814 ======
84815 -----BEGIN CERTIFICATE-----
84816 MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE
84817 BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w
84818 ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD
84819 VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE
84820 CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT
84821 BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7
84822 MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt
84823 SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl
84824 Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh
84825 cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND
84826 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK
84827 w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT
84828 ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4
84829 HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a
84830 E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw
84831 0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E
84832 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD
84833 VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0
84834 Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l
84835 dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ
84836 lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa
84837 Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe
84838 l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2
84839 E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D
84840 5EI=
84841 -----END CERTIFICATE-----
84842
84843 Hellenic Academic and Research Institutions RootCA 2011
84844 =======================================================
84845 -----BEGIN CERTIFICATE-----
84846 MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT
84847 O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y
84848 aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
84849 IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT
84850 AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
84851 IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo
84852 IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
84853 AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI
84854 1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa
84855 71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u
84856 8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH
84857 3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/
84858 MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8
84859 MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu
84860 b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt
84861 XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
84862 TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD
84863 /md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N
84864 7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4
84865 -----END CERTIFICATE-----
84866
84867 Actalis Authentication Root CA
84868 ==============================
84869 -----BEGIN CERTIFICATE-----
84870 MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM
84871 BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE
84872 AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky
84873 MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz
84874 IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
84875 IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ
84876 wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa
84877 by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6
84878 zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f
84879 YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2
84880 oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l
84881 EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7
84882 hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8
84883 EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5
84884 jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY
84885 iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
84886 ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI
84887 WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0
84888 JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx
84889 K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+
84890 Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC
84891 4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo
84892 2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz
84893 lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem
84894 OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9
84895 vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
84896 -----END CERTIFICATE-----
84897
84898 Trustis FPS Root CA
84899 ===================
84900 -----BEGIN CERTIFICATE-----
84901 MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG
84902 EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290
84903 IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV
84904 BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ
84905 KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ
84906 RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk
84907 H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa
84908 cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt
84909 o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA
84910 AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd
84911 BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c
84912 GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC
84913 yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P
84914 8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV
84915 l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl
84916 iB6XzCGcKQENZetX2fNXlrtIzYE=
84917 -----END CERTIFICATE-----
84918
84919 StartCom Certification Authority
84920 ================================
84921 -----BEGIN CERTIFICATE-----
84922 MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
84923 U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu
84924 ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0
84925 NjM3WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk
84926 LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg
84927 U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
84928 ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y
84929 o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/
84930 Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d
84931 eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt
84932 2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z
84933 6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ
84934 osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/
84935 untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc
84936 UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT
84937 37uMdBNSSwIDAQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
84938 VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFulF2mHMMo0aEPQ
84939 Qa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCCATgwLgYIKwYBBQUHAgEWImh0
84940 dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cu
84941 c3RhcnRzc2wuY29tL2ludGVybWVkaWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENv
84942 bW1lcmNpYWwgKFN0YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0
84943 aGUgc2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0aWZpY2F0
84944 aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t
84945 L3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBG
84946 cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5
84947 fPGFf59Jb2vKXfuM/gTFwWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWm
84948 N3PH/UvSTa0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst0OcN
84949 Org+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNcpRJvkrKTlMeIFw6T
84950 tn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKlCcWw0bdT82AUuoVpaiF8H3VhFyAX
84951 e2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVFP0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA
84952 2MFrLH9ZXF2RsXAiV+uKa0hK1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBs
84953 HvUwyKMQ5bLmKhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE
84954 JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ8dCAWZvLMdib
84955 D4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnmfyWl8kgAwKQB2j8=
84956 -----END CERTIFICATE-----
84957
84958 StartCom Certification Authority G2
84959 ===================================
84960 -----BEGIN CERTIFICATE-----
84961 MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
84962 U3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
84963 RzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UE
84964 ChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3Jp
84965 dHkgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8O
84966 o1XJJZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsDvfOpL9HG
84967 4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnooD/Uefyf3lLE3PbfHkffi
84968 Aez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/Q0kGi4xDuFby2X8hQxfqp0iVAXV16iul
84969 Q5XqFYSdCI0mblWbq9zSOdIxHWDirMxWRST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbs
84970 O+wmETRIjfaAKxojAuuKHDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8H
84971 vKTlXcxNnw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM0D4L
84972 nMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/iUUjXuG+v+E5+M5iS
84973 FGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9Ha90OrInwMEePnWjFqmveiJdnxMa
84974 z6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHgTuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8E
84975 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJ
84976 KoZIhvcNAQELBQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K
84977 2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfXUfEpY9Z1zRbk
84978 J4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl6/2o1PXWT6RbdejF0mCy2wl+
84979 JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG
84980 /+gyRr61M3Z3qAFdlsHB1b6uJcDJHgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTc
84981 nIhT76IxW1hPkWLIwpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/Xld
84982 blhYXzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5lIxKVCCIc
84983 l85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoohdVddLHRDiBYmxOlsGOm
84984 7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulrso8uBtjRkcfGEvRM/TAXw8HaOFvjqerm
84985 obp573PYtlNXLfbQ4ddI
84986 -----END CERTIFICATE-----
84987
84988 Buypass Class 2 Root CA
84989 =======================
84990 -----BEGIN CERTIFICATE-----
84991 MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
84992 QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X
84993 DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
84994 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw
84995 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1
84996 g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn
84997 9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b
84998 /+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU
84999 CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff
85000 awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI
85001 zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn
85002 Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX
85003 Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs
85004 M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
85005 VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
85006 AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s
85007 A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI
85008 osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S
85009 aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd
85010 DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD
85011 LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0
85012 oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC
85013 wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS
85014 CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN
85015 rJgWVqA=
85016 -----END CERTIFICATE-----
85017
85018 Buypass Class 3 Root CA
85019 =======================
85020 -----BEGIN CERTIFICATE-----
85021 MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
85022 QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X
85023 DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
85024 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw
85025 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH
85026 sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR
85027 5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh
85028 7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ
85029 ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH
85030 2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV
85031 /afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ
85032 RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA
85033 Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq
85034 j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
85035 VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
85036 AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV
85037 cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G
85038 uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG
85039 Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8
85040 ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2
85041 KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz
85042 6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug
85043 UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe
85044 eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi
85045 Cp/HuZc=
85046 -----END CERTIFICATE-----
85047
85048 T-TeleSec GlobalRoot Class 3
85049 ============================
85050 -----BEGIN CERTIFICATE-----
85051 MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
85052 IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
85053 cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx
85054 MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
85055 dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
85056 ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3
85057 DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK
85058 9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU
85059 NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF
85060 iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W
85061 0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA
85062 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr
85063 AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb
85064 fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT
85065 ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h
85066 P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
85067 e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw==
85068 -----END CERTIFICATE-----
85069
85070 EE Certification Centre Root CA
85071 ===============================
85072 -----BEGIN CERTIFICATE-----
85073 MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG
85074 EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy
85075 dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw
85076 MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB
85077 UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy
85078 ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB
85079 DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM
85080 TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2
85081 rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw
85082 93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN
85083 P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T
85084 AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ
85085 MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF
85086 BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj
85087 xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM
85088 lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u
85089 uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU
85090 3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM
85091 dcGWxZ0=
85092 -----END CERTIFICATE-----
85093
85094 TURKTRUST Certificate Services Provider Root 2007
85095 =================================================
85096 -----BEGIN CERTIFICATE-----
85097 MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOcUktUUlVTVCBF
85098 bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP
85099 MA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg
85100 QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4X
85101 DTA3MTIyNTE4MzcxOVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxl
85102 a3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMCVFIxDzAN
85103 BgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp
85104 bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4gKGMpIEFyYWzEsWsgMjAwNzCCASIw
85105 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9N
85106 YvDdE3ePYakqtdTyuTFYKTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQv
85107 KUmi8wUG+7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveGHtya
85108 KhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6PIzdezKKqdfcYbwnT
85109 rqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M733WB2+Y8a+xwXrXgTW4qhe04MsC
85110 AwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHkYb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAP
85111 BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/s
85112 Px+EnWVUXKgWAkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I
85113 aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5mxRZNTZPz/OO
85114 Xl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsaXRik7r4EW5nVcV9VZWRi1aKb
85115 BFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZqxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAK
85116 poRq0Tl9
85117 -----END CERTIFICATE-----
85118
85119 D-TRUST Root Class 3 CA 2 2009
85120 ==============================
85121 -----BEGIN CERTIFICATE-----
85122 MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK
85123 DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe
85124 Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE
85125 LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw
85126 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD
85127 ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA
85128 BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv
85129 KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z
85130 p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC
85131 AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ
85132 4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y
85133 eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw
85134 MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G
85135 PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw
85136 OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm
85137 2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
85138 o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV
85139 dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph
85140 X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I=
85141 -----END CERTIFICATE-----
85142
85143 D-TRUST Root Class 3 CA 2 EV 2009
85144 =================================
85145 -----BEGIN CERTIFICATE-----
85146 MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
85147 DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
85148 OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
85149 DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
85150 OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS
85151 egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh
85152 zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T
85153 7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60
85154 sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35
85155 11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv
85156 cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v
85157 ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El
85158 MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp
85159 b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh
85160 c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+
85161 PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05
85162 nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX
85163 ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA
85164 NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv
85165 w9y4AyHqnxbxLFS1
85166 -----END CERTIFICATE-----
85167
85168 PSCProcert
85169 ==========
85170 -----BEGIN CERTIFICATE-----
85171 MIIJhjCCB26gAwIBAgIBCzANBgkqhkiG9w0BAQsFADCCAR4xPjA8BgNVBAMTNUF1dG9yaWRhZCBk
85172 ZSBDZXJ0aWZpY2FjaW9uIFJhaXogZGVsIEVzdGFkbyBWZW5lem9sYW5vMQswCQYDVQQGEwJWRTEQ
85173 MA4GA1UEBxMHQ2FyYWNhczEZMBcGA1UECBMQRGlzdHJpdG8gQ2FwaXRhbDE2MDQGA1UEChMtU2lz
85174 dGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMUMwQQYDVQQLEzpTdXBl
85175 cmludGVuZGVuY2lhIGRlIFNlcnZpY2lvcyBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMSUw
85176 IwYJKoZIhvcNAQkBFhZhY3JhaXpAc3VzY2VydGUuZ29iLnZlMB4XDTEwMTIyODE2NTEwMFoXDTIw
85177 MTIyNTIzNTk1OVowgdExJjAkBgkqhkiG9w0BCQEWF2NvbnRhY3RvQHByb2NlcnQubmV0LnZlMQ8w
85178 DQYDVQQHEwZDaGFjYW8xEDAOBgNVBAgTB01pcmFuZGExKjAoBgNVBAsTIVByb3ZlZWRvciBkZSBD
85179 ZXJ0aWZpY2Fkb3MgUFJPQ0VSVDE2MDQGA1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZp
85180 Y2FjaW9uIEVsZWN0cm9uaWNhMQswCQYDVQQGEwJWRTETMBEGA1UEAxMKUFNDUHJvY2VydDCCAiIw
85181 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANW39KOUM6FGqVVhSQ2oh3NekS1wwQYalNo97BVC
85182 wfWMrmoX8Yqt/ICV6oNEolt6Vc5Pp6XVurgfoCfAUFM+jbnADrgV3NZs+J74BCXfgI8Qhd19L3uA
85183 3VcAZCP4bsm+lU/hdezgfl6VzbHvvnpC2Mks0+saGiKLt38GieU89RLAu9MLmV+QfI4tL3czkkoh
85184 RqipCKzx9hEC2ZUWno0vluYC3XXCFCpa1sl9JcLB/KpnheLsvtF8PPqv1W7/U0HU9TI4seJfxPmO
85185 EO8GqQKJ/+MMbpfg353bIdD0PghpbNjU5Db4g7ayNo+c7zo3Fn2/omnXO1ty0K+qP1xmk6wKImG2
85186 0qCZyFSTXai20b1dCl53lKItwIKOvMoDKjSuc/HUtQy9vmebVOvh+qBa7Dh+PsHMosdEMXXqP+UH
85187 0quhJZb25uSgXTcYOWEAM11G1ADEtMo88aKjPvM6/2kwLkDd9p+cJsmWN63nOaK/6mnbVSKVUyqU
85188 td+tFjiBdWbjxywbk5yqjKPK2Ww8F22c3HxT4CAnQzb5EuE8XL1mv6JpIzi4mWCZDlZTOpx+FIyw
85189 Bm/xhnaQr/2v/pDGj59/i5IjnOcVdo/Vi5QTcmn7K2FjiO/mpF7moxdqWEfLcU8UC17IAggmosvp
85190 r2uKGcfLFFb14dq12fy/czja+eevbqQ34gcnAgMBAAGjggMXMIIDEzASBgNVHRMBAf8ECDAGAQH/
85191 AgEBMDcGA1UdEgQwMC6CD3N1c2NlcnRlLmdvYi52ZaAbBgVghl4CAqASDBBSSUYtRy0yMDAwNDAz
85192 Ni0wMB0GA1UdDgQWBBRBDxk4qpl/Qguk1yeYVKIXTC1RVDCCAVAGA1UdIwSCAUcwggFDgBStuyId
85193 xuDSAaj9dlBSk+2YwU2u06GCASakggEiMIIBHjE+MDwGA1UEAxM1QXV0b3JpZGFkIGRlIENlcnRp
85194 ZmljYWNpb24gUmFpeiBkZWwgRXN0YWRvIFZlbmV6b2xhbm8xCzAJBgNVBAYTAlZFMRAwDgYDVQQH
85195 EwdDYXJhY2FzMRkwFwYDVQQIExBEaXN0cml0byBDYXBpdGFsMTYwNAYDVQQKEy1TaXN0ZW1hIE5h
85196 Y2lvbmFsIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExQzBBBgNVBAsTOlN1cGVyaW50ZW5k
85197 ZW5jaWEgZGUgU2VydmljaW9zIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExJTAjBgkqhkiG
85198 9w0BCQEWFmFjcmFpekBzdXNjZXJ0ZS5nb2IudmWCAQowDgYDVR0PAQH/BAQDAgEGME0GA1UdEQRG
85199 MESCDnByb2NlcnQubmV0LnZloBUGBWCGXgIBoAwMClBTQy0wMDAwMDKgGwYFYIZeAgKgEgwQUklG
85200 LUotMzE2MzUzNzMtNzB2BgNVHR8EbzBtMEagRKBChkBodHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52
85201 ZS9sY3IvQ0VSVElGSUNBRE8tUkFJWi1TSEEzODRDUkxERVIuY3JsMCOgIaAfhh1sZGFwOi8vYWNy
85202 YWl6LnN1c2NlcnRlLmdvYi52ZTA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHA6Ly9v
85203 Y3NwLnN1c2NlcnRlLmdvYi52ZTBBBgNVHSAEOjA4MDYGBmCGXgMBAjAsMCoGCCsGAQUFBwIBFh5o
85204 dHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52ZS9kcGMwDQYJKoZIhvcNAQELBQADggIBACtZ6yKZu4Sq
85205 T96QxtGGcSOeSwORR3C7wJJg7ODU523G0+1ng3dS1fLld6c2suNUvtm7CpsR72H0xpkzmfWvADmN
85206 g7+mvTV+LFwxNG9s2/NkAZiqlCxB3RWGymspThbASfzXg0gTB1GEMVKIu4YXx2sviiCtxQuPcD4q
85207 uxtxj7mkoP3YldmvWb8lK5jpY5MvYB7Eqvh39YtsL+1+LrVPQA3uvFd359m21D+VJzog1eWuq2w1
85208 n8GhHVnchIHuTQfiSLaeS5UtQbHh6N5+LwUeaO6/u5BlOsju6rEYNxxik6SgMexxbJHmpHmJWhSn
85209 FFAFTKQAVzAswbVhltw+HoSvOULP5dAssSS830DD7X9jSr3hTxJkhpXzsOfIt+FTvZLm8wyWuevo
85210 5pLtp4EJFAv8lXrPj9Y0TzYS3F7RNHXGRoAvlQSMx4bEqCaJqD8Zm4G7UaRKhqsLEQ+xrmNTbSjq
85211 3TNWOByyrYDT13K9mmyZY+gAu0F2BbdbmRiKw7gSXFbPVgx96OLP7bx0R/vu0xdOIk9W/1DzLuY5
85212 poLWccret9W6aAjtmcz9opLLabid+Qqkpj5PkygqYWwHJgD/ll9ohri4zspV4KuxPX+Y1zMOWj3Y
85213 eMLEYC/HYvBhkdI4sPaeVdtAgAUSM84dkpvRabP/v/GSCmE1P93+hvS84Bpxs2Km
85214 -----END CERTIFICATE-----
85215
85216 China Internet Network Information Center EV Certificates Root
85217 ==============================================================
85218 -----BEGIN CERTIFICATE-----
85219 MIID9zCCAt+gAwIBAgIESJ8AATANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCQ04xMjAwBgNV
85220 BAoMKUNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyMUcwRQYDVQQDDD5D
85221 aGluYSBJbnRlcm5ldCBOZXR3b3JrIEluZm9ybWF0aW9uIENlbnRlciBFViBDZXJ0aWZpY2F0ZXMg
85222 Um9vdDAeFw0xMDA4MzEwNzExMjVaFw0zMDA4MzEwNzExMjVaMIGKMQswCQYDVQQGEwJDTjEyMDAG
85223 A1UECgwpQ2hpbmEgSW50ZXJuZXQgTmV0d29yayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMM
85224 PkNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRpZmljYXRl
85225 cyBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm35z7r07eKpkQ0H1UN+U8i6y
85226 jUqORlTSIRLIOTJCBumD1Z9S7eVnAztUwYyZmczpwA//DdmEEbK40ctb3B75aDFk4Zv6dOtouSCV
85227 98YPjUesWgbdYavi7NifFy2cyjw1l1VxzUOFsUcW9SxTgHbP0wBkvUCZ3czY28Sf1hNfQYOL+Q2H
85228 klY0bBoQCxfVWhyXWIQ8hBouXJE0bhlffxdpxWXvayHG1VA6v2G5BY3vbzQ6sm8UY78WO5upKv23
85229 KzhmBsUs4qpnHkWnjQRmQvaPK++IIGmPMowUc9orhpFjIpryp9vOiYurXccUwVswah+xt54ugQEC
85230 7c+WXmPbqOY4twIDAQABo2MwYTAfBgNVHSMEGDAWgBR8cks5x8DbYqVPm6oYNJKiyoOCWTAPBgNV
85231 HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUfHJLOcfA22KlT5uqGDSSosqD
85232 glkwDQYJKoZIhvcNAQEFBQADggEBACrDx0M3j92tpLIM7twUbY8opJhJywyA6vPtI2Z1fcXTIWd5
85233 0XPFtQO3WKwMVC/GVhMPMdoG52U7HW8228gd+f2ABsqjPWYWqJ1MFn3AlUa1UeTiH9fqBk1jjZaM
85234 7+czV0I664zBechNdn3e9rG3geCg+aF4RhcaVpjwTj2rHO3sOdwHSPdj/gauwqRcalsyiMXHM4Ws
85235 ZkJHwlgkmeHlPuV1LI5D1l08eB6olYIpUNHRFrrvwb562bTYzB5MRuF3sTGrvSrIzo9uoV1/A3U0
85236 5K2JRVRevq4opbs/eHnrc7MKDf2+yfdWrPa37S+bISnHOLaVxATywy39FCqQmbkHzJ8=
85237 -----END CERTIFICATE-----
85238
85239 Swisscom Root CA 2
85240 ==================
85241 -----BEGIN CERTIFICATE-----
85242 MIIF2TCCA8GgAwIBAgIQHp4o6Ejy5e/DfEoeWhhntjANBgkqhkiG9w0BAQsFADBkMQswCQYDVQQG
85243 EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy
85244 dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMjAeFw0xMTA2MjQwODM4MTRaFw0zMTA2
85245 MjUwNzM4MTRaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln
85246 aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAyMIIC
85247 IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlUJOhJ1R5tMJ6HJaI2nbeHCOFvErjw0DzpPM
85248 LgAIe6szjPTpQOYXTKueuEcUMncy3SgM3hhLX3af+Dk7/E6J2HzFZ++r0rk0X2s682Q2zsKwzxNo
85249 ysjL67XiPS4h3+os1OD5cJZM/2pYmLcX5BtS5X4HAB1f2uY+lQS3aYg5oUFgJWFLlTloYhyxCwWJ
85250 wDaCFCE/rtuh/bxvHGCGtlOUSbkrRsVPACu/obvLP+DHVxxX6NZp+MEkUp2IVd3Chy50I9AU/SpH
85251 Wrumnf2U5NGKpV+GY3aFy6//SSj8gO1MedK75MDvAe5QQQg1I3ArqRa0jG6F6bYRzzHdUyYb3y1a
85252 SgJA/MTAtukxGggo5WDDH8SQjhBiYEQN7Aq+VRhxLKX0srwVYv8c474d2h5Xszx+zYIdkeNL6yxS
85253 NLCK/RJOlrDrcH+eOfdmQrGrrFLadkBXeyq96G4DsguAhYidDMfCd7Camlf0uPoTXGiTOmekl9Ab
85254 mbeGMktg2M7v0Ax/lZ9vh0+Hio5fCHyqW/xavqGRn1V9TrALacywlKinh/LTSlDcX3KwFnUey7QY
85255 Ypqwpzmqm59m2I2mbJYV4+by+PGDYmy7Velhk6M99bFXi08jsJvllGov34zflVEpYKELKeRcVVi3
85256 qPyZ7iVNTA6z00yPhOgpD/0QVAKFyPnlw4vP5w8CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw
85257 HQYDVR0hBBYwFDASBgdghXQBUwIBBgdghXQBUwIBMBIGA1UdEwEB/wQIMAYBAf8CAQcwHQYDVR0O
85258 BBYEFE0mICKJS9PVpAqhb97iEoHF8TwuMB8GA1UdIwQYMBaAFE0mICKJS9PVpAqhb97iEoHF8Twu
85259 MA0GCSqGSIb3DQEBCwUAA4ICAQAyCrKkG8t9voJXiblqf/P0wS4RfbgZPnm3qKhyN2abGu2sEzsO
85260 v2LwnN+ee6FTSA5BesogpxcbtnjsQJHzQq0Qw1zv/2BZf82Fo4s9SBwlAjxnffUy6S8w5X2lejjQ
85261 82YqZh6NM4OKb3xuqFp1mrjX2lhIREeoTPpMSQpKwhI3qEAMw8jh0FcNlzKVxzqfl9NX+Ave5XLz
85262 o9v/tdhZsnPdTSpxsrpJ9csc1fV5yJmz/MFMdOO0vSk3FQQoHt5FRnDsr7p4DooqzgB53MBfGWcs
85263 a0vvaGgLQ+OswWIJ76bdZWGgr4RVSJFSHMYlkSrQwSIjYVmvRRGFHQEkNI/Ps/8XciATwoCqISxx
85264 OQ7Qj1zB09GOInJGTB2Wrk9xseEFKZZZ9LuedT3PDTcNYtsmjGOpI99nBjx8Oto0QuFmtEYE3saW
85265 mA9LSHokMnWRn6z3aOkquVVlzl1h0ydw2Df+n7mvoC5Wt6NlUe07qxS/TFED6F+KBZvuim6c779o
85266 +sjaC+NCydAXFJy3SuCvkychVSa1ZC+N8f+mQAWFBVzKBxlcCxMoTFh/wqXvRdpg065lYZ1Tg3TC
85267 rvJcwhbtkj6EPnNgiLx29CzP0H1907he0ZESEOnN3col49XtmS++dYFLJPlFRpTJKSFTnCZFqhMX
85268 5OfNeOI5wSsSnqaeG8XmDtkx2Q==
85269 -----END CERTIFICATE-----
85270
85271 Swisscom Root EV CA 2
85272 =====================
85273 -----BEGIN CERTIFICATE-----
85274 MIIF4DCCA8igAwIBAgIRAPL6ZOJ0Y9ON/RAdBB92ylgwDQYJKoZIhvcNAQELBQAwZzELMAkGA1UE
85275 BhMCY2gxETAPBgNVBAoTCFN3aXNzY29tMSUwIwYDVQQLExxEaWdpdGFsIENlcnRpZmljYXRlIFNl
85276 cnZpY2VzMR4wHAYDVQQDExVTd2lzc2NvbSBSb290IEVWIENBIDIwHhcNMTEwNjI0MDk0NTA4WhcN
85277 MzEwNjI1MDg0NTA4WjBnMQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsT
85278 HERpZ2l0YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxHjAcBgNVBAMTFVN3aXNzY29tIFJvb3QgRVYg
85279 Q0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMT3HS9X6lds93BdY7BxUglgRCgz
85280 o3pOCvrY6myLURYaVa5UJsTMRQdBTxB5f3HSek4/OE6zAMaVylvNwSqD1ycfMQ4jFrclyxy0uYAy
85281 Xhqdk/HoPGAsp15XGVhRXrwsVgu42O+LgrQ8uMIkqBPHoCE2G3pXKSinLr9xJZDzRINpUKTk4Rti
85282 GZQJo/PDvO/0vezbE53PnUgJUmfANykRHvvSEaeFGHR55E+FFOtSN+KxRdjMDUN/rhPSays/p8Li
85283 qG12W0OfvrSdsyaGOx9/5fLoZigWJdBLlzin5M8J0TbDC77aO0RYjb7xnglrPvMyxyuHxuxenPaH
85284 Za0zKcQvidm5y8kDnftslFGXEBuGCxobP/YCfnvUxVFkKJ3106yDgYjTdLRZncHrYTNaRdHLOdAG
85285 alNgHa/2+2m8atwBz735j9m9W8E6X47aD0upm50qKGsaCnw8qyIL5XctcfaCNYGu+HuB5ur+rPQa
85286 m3Rc6I8k9l2dRsQs0h4rIWqDJ2dVSqTjyDKXZpBy2uPUZC5f46Fq9mDU5zXNysRojddxyNMkM3Ox
85287 bPlq4SjbX8Y96L5V5jcb7STZDxmPX2MYWFCBUWVv8p9+agTnNCRxunZLWB4ZvRVgRaoMEkABnRDi
85288 xzgHcgplwLa7JSnaFp6LNYth7eVxV4O1PHGf40+/fh6Bn0GXAgMBAAGjgYYwgYMwDgYDVR0PAQH/
85289 BAQDAgGGMB0GA1UdIQQWMBQwEgYHYIV0AVMCAgYHYIV0AVMCAjASBgNVHRMBAf8ECDAGAQH/AgED
85290 MB0GA1UdDgQWBBRF2aWBbj2ITY1x0kbBbkUe88SAnTAfBgNVHSMEGDAWgBRF2aWBbj2ITY1x0kbB
85291 bkUe88SAnTANBgkqhkiG9w0BAQsFAAOCAgEAlDpzBp9SSzBc1P6xXCX5145v9Ydkn+0UjrgEjihL
85292 j6p7jjm02Vj2e6E1CqGdivdj5eu9OYLU43otb98TPLr+flaYC/NUn81ETm484T4VvwYmneTwkLbU
85293 wp4wLh/vx3rEUMfqe9pQy3omywC0Wqu1kx+AiYQElY2NfwmTv9SoqORjbdlk5LgpWgi/UOGED1V7
85294 XwgiG/W9mR4U9s70WBCCswo9GcG/W6uqmdjyMb3lOGbcWAXH7WMaLgqXfIeTK7KK4/HsGOV1timH
85295 59yLGn602MnTihdsfSlEvoqq9X46Lmgxk7lq2prg2+kupYTNHAq4Sgj5nPFhJpiTt3tm7JFe3VE/
85296 23MPrQRYCd0EApUKPtN236YQHoA96M2kZNEzx5LH4k5E4wnJTsJdhw4Snr8PyQUQ3nqjsTzyP6Wq
85297 J3mtMX0f/fwZacXduT98zca0wjAefm6S139hdlqP65VNvBFuIXxZN5nQBrz5Bm0yFqXZaajh3DyA
85298 HmBR3NdUIR7KYndP+tiPsys6DXhyyWhBWkdKwqPrGtcKqzwyVcgKEZzfdNbwQBUdyLmPtTbFr/gi
85299 uMod89a2GQ+fYWVq6nTIfI/DT11lgh/ZDYnadXL77/FHZxOzyNEZiCcmmpl5fx7kLD977vHeTYuW
85300 l8PVP3wbI+2ksx0WckNLIOFZfsLorSa/ovc=
85301 -----END CERTIFICATE-----
85302
85303 CA Disig Root R1
85304 ================
85305 -----BEGIN CERTIFICATE-----
85306 MIIFaTCCA1GgAwIBAgIJAMMDmu5QkG4oMA0GCSqGSIb3DQEBBQUAMFIxCzAJBgNVBAYTAlNLMRMw
85307 EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp
85308 ZyBSb290IFIxMB4XDTEyMDcxOTA5MDY1NloXDTQyMDcxOTA5MDY1NlowUjELMAkGA1UEBhMCU0sx
85309 EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp
85310 c2lnIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCqw3j33Jijp1pedxiy
85311 3QRkD2P9m5YJgNXoqqXinCaUOuiZc4yd39ffg/N4T0Dhf9Kn0uXKE5Pn7cZ3Xza1lK/oOI7bm+V8
85312 u8yN63Vz4STN5qctGS7Y1oprFOsIYgrY3LMATcMjfF9DCCMyEtztDK3AfQ+lekLZWnDZv6fXARz2
85313 m6uOt0qGeKAeVjGu74IKgEH3G8muqzIm1Cxr7X1r5OJeIgpFy4QxTaz+29FHuvlglzmxZcfe+5nk
85314 CiKxLU3lSCZpq+Kq8/v8kiky6bM+TR8noc2OuRf7JT7JbvN32g0S9l3HuzYQ1VTW8+DiR0jm3hTa
85315 YVKvJrT1cU/J19IG32PK/yHoWQbgCNWEFVP3Q+V8xaCJmGtzxmjOZd69fwX3se72V6FglcXM6pM6
85316 vpmumwKjrckWtc7dXpl4fho5frLABaTAgqWjR56M6ly2vGfb5ipN0gTco65F97yLnByn1tUD3AjL
85317 LhbKXEAz6GfDLuemROoRRRw1ZS0eRWEkG4IupZ0zXWX4Qfkuy5Q/H6MMMSRE7cderVC6xkGbrPAX
85318 ZcD4XW9boAo0PO7X6oifmPmvTiT6l7Jkdtqr9O3jw2Dv1fkCyC2fg69naQanMVXVz0tv/wQFx1is
85319 XxYb5dKj6zHbHzMVTdDypVP1y+E9Tmgt2BLdqvLmTZtJ5cUoobqwWsagtQIDAQABo0IwQDAPBgNV
85320 HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUiQq0OJMa5qvum5EY+fU8PjXQ
85321 04IwDQYJKoZIhvcNAQEFBQADggIBADKL9p1Kyb4U5YysOMo6CdQbzoaz3evUuii+Eq5FLAR0rBNR
85322 xVgYZk2C2tXck8An4b58n1KeElb21Zyp9HWc+jcSjxyT7Ff+Bw+r1RL3D65hXlaASfX8MPWbTx9B
85323 LxyE04nH4toCdu0Jz2zBuByDHBb6lM19oMgY0sidbvW9adRtPTXoHqJPYNcHKfyyo6SdbhWSVhlM
85324 CrDpfNIZTUJG7L399ldb3Zh+pE3McgODWF3vkzpBemOqfDqo9ayk0d2iLbYq/J8BjuIQscTK5Gfb
85325 VSUZP/3oNn6z4eGBrxEWi1CXYBmCAMBrTXO40RMHPuq2MU/wQppt4hF05ZSsjYSVPCGvxdpHyN85
85326 YmLLW1AL14FABZyb7bq2ix4Eb5YgOe2kfSnbSM6C3NQCjR0EMVrHS/BsYVLXtFHCgWzN4funodKS
85327 ds+xDzdYpPJScWc/DIh4gInByLUfkmO+p3qKViwaqKactV2zY9ATIKHrkWzQjX2v3wvkF7mGnjix
85328 lAxYjOBVqjtjbZqJYLhkKpLGN/R+Q0O3c+gB53+XD9fyexn9GtePyfqFa3qdnom2piiZk4hA9z7N
85329 UaPK6u95RyG1/jLix8NRb76AdPCkwzryT+lf3xkK8jsTQ6wxpLPn6/wY1gGp8yqPNg7rtLG8t0zJ
85330 a7+h89n07eLw4+1knj0vllJPgFOL
85331 -----END CERTIFICATE-----
85332
85333 CA Disig Root R2
85334 ================
85335 -----BEGIN CERTIFICATE-----
85336 MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw
85337 EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp
85338 ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx
85339 EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp
85340 c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC
85341 w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia
85342 xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7
85343 A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S
85344 GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV
85345 g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa
85346 5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE
85347 koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A
85348 Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i
85349 Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV
85350 HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u
85351 Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM
85352 tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV
85353 sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je
85354 dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8
85355 1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx
85356 mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01
85357 utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0
85358 sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg
85359 UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV
85360 7+ZtsH8tZ/3zbBt1RqPlShfppNcL
85361 -----END CERTIFICATE-----
85362
85363 ACCVRAIZ1
85364 =========
85365 -----BEGIN CERTIFICATE-----
85366 MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB
85367 SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1
85368 MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH
85369 UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
85370 DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM
85371 jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0
85372 RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD
85373 aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ
85374 0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG
85375 WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7
85376 8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR
85377 5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J
85378 9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK
85379 Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw
85380 Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu
85381 Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2
85382 VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM
85383 Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA
85384 QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh
85385 AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA
85386 YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj
85387 AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA
85388 IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk
85389 aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0
85390 dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2
85391 MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI
85392 hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E
85393 R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN
85394 YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49
85395 nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ
85396 TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3
85397 sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h
85398 I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg
85399 Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd
85400 3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p
85401 EfbRD0tVNEYqi4Y7
85402 -----END CERTIFICATE-----
85403
85404 TWCA Global Root CA
85405 ===================
85406 -----BEGIN CERTIFICATE-----
85407 MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT
85408 CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD
85409 QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK
85410 EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg
85411 Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C
85412 nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV
85413 r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR
85414 Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV
85415 tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W
85416 KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99
85417 sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p
85418 yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn
85419 kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI
85420 zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC
85421 AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g
85422 cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn
85423 LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M
85424 8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg
85425 /eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg
85426 lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP
85427 A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m
85428 i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8
85429 EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3
85430 zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0=
85431 -----END CERTIFICATE-----
85432
85433 TeliaSonera Root CA v1
85434 ======================
85435 -----BEGIN CERTIFICATE-----
85436 MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE
85437 CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4
85438 MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW
85439 VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+
85440 6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA
85441 3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k
85442 B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn
85443 Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH
85444 oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3
85445 F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ
85446 oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7
85447 gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc
85448 TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB
85449 AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW
85450 DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm
85451 zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx
85452 0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW
85453 pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV
85454 G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc
85455 c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT
85456 JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2
85457 qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6
85458 Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems
85459 WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
85460 -----END CERTIFICATE-----
85461
85462 E-Tugra Certification Authority
85463 ===============================
85464 -----BEGIN CERTIFICATE-----
85465 MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w
85466 DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls
85467 ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN
85468 ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw
85469 NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx
85470 QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl
85471 cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD
85472 DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
85473 MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd
85474 hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K
85475 CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g
85476 ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ
85477 BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0
85478 E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz
85479 rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq
85480 jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn
85481 rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5
85482 dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB
85483 /wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG
85484 MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK
85485 kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO
85486 XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807
85487 VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo
85488 a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc
85489 dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV
85490 KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT
85491 Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0
85492 8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G
85493 C7TbO6Orb1wdtn7os4I07QZcJA==
85494 -----END CERTIFICATE-----
85495
85496 T-TeleSec GlobalRoot Class 2
85497 ============================
85498 -----BEGIN CERTIFICATE-----
85499 MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
85500 IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
85501 cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx
85502 MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
85503 dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
85504 ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3
85505 DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ
85506 SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F
85507 vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970
85508 2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV
85509 WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA
85510 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy
85511 YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4
85512 r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf
85513 vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR
85514 3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN
85515 9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg==
85516 -----END CERTIFICATE-----
85517
85518 Atos TrustedRoot 2011
85519 =====================
85520 -----BEGIN CERTIFICATE-----
85521 MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU
85522 cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4
85523 MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG
85524 A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV
85525 hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr
85526 54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+
85527 DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320
85528 HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR
85529 z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R
85530 l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ
85531 bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
85532 CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h
85533 k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh
85534 TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9
85535 61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G
85536 3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
85537 -----END CERTIFICATE-----
85538
85539 QuoVadis Root CA 1 G3
85540 =====================
85541 -----BEGIN CERTIFICATE-----
85542 MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG
85543 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
85544 b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN
85545 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg
85546 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE
85547 PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm
85548 PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6
85549 Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN
85550 ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l
85551 g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV
85552 7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX
85553 9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f
85554 iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg
85555 t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
85556 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI
85557 hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC
85558 MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3
85559 GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct
85560 Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP
85561 +V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh
85562 3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa
85563 wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6
85564 O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0
85565 FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV
85566 hMJKzRwuJIczYOXD
85567 -----END CERTIFICATE-----
85568
85569 QuoVadis Root CA 2 G3
85570 =====================
85571 -----BEGIN CERTIFICATE-----
85572 MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG
85573 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
85574 b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN
85575 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg
85576 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh
85577 ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY
85578 NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t
85579 oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o
85580 MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l
85581 V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo
85582 L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ
85583 sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD
85584 6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh
85585 lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
85586 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI
85587 hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66
85588 AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K
85589 pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9
85590 x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz
85591 dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X
85592 U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw
85593 mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD
85594 zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN
85595 JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr
85596 O3jtZsSOeWmD3n+M
85597 -----END CERTIFICATE-----
85598
85599 QuoVadis Root CA 3 G3
85600 =====================
85601 -----BEGIN CERTIFICATE-----
85602 MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG
85603 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
85604 b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN
85605 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg
85606 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286
85607 IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL
85608 Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe
85609 6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3
85610 I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U
85611 VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7
85612 5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi
85613 Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM
85614 dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt
85615 rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
85616 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI
85617 hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px
85618 KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS
85619 t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ
85620 TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du
85621 DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib
85622 Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD
85623 hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX
85624 0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW
85625 dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2
85626 PpxxVJkES/1Y+Zj0
85627 -----END CERTIFICATE-----
85628
85629 DigiCert Assured ID Root G2
85630 ===========================
85631 -----BEGIN CERTIFICATE-----
85632 MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG
85633 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
85634 IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw
85635 MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
85636 ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw
85637 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH
85638 35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq
85639 bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw
85640 VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP
85641 YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn
85642 lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO
85643 w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv
85644 0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz
85645 d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW
85646 hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M
85647 jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
85648 IhNzbM8m9Yop5w==
85649 -----END CERTIFICATE-----
85650
85651 DigiCert Assured ID Root G3
85652 ===========================
85653 -----BEGIN CERTIFICATE-----
85654 MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV
85655 UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD
85656 VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
85657 MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
85658 d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ
85659 BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb
85660 RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs
85661 KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF
85662 UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy
85663 YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy
85664 1vUhZscv6pZjamVFkpUBtA==
85665 -----END CERTIFICATE-----
85666
85667 DigiCert Global Root G2
85668 =======================
85669 -----BEGIN CERTIFICATE-----
85670 MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG
85671 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
85672 HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx
85673 MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
85674 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq
85675 hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ
85676 kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO
85677 3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV
85678 BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM
85679 UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB
85680 o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu
85681 5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr
85682 F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U
85683 WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH
85684 QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/
85685 iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
85686 MrY=
85687 -----END CERTIFICATE-----
85688
85689 DigiCert Global Root G3
85690 =======================
85691 -----BEGIN CERTIFICATE-----
85692 MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV
85693 UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD
85694 VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw
85695 MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k
85696 aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C
85697 AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O
85698 YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP
85699 BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp
85700 Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y
85701 3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34
85702 VOKa5Vt8sycX
85703 -----END CERTIFICATE-----
85704
85705 DigiCert Trusted Root G4
85706 ========================
85707 -----BEGIN CERTIFICATE-----
85708 MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG
85709 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw
85710 HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
85711 MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
85712 d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G
85713 CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp
85714 pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o
85715 k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa
85716 vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY
85717 QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6
85718 MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm
85719 mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7
85720 f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH
85721 dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8
85722 oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
85723 DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
85724 ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY
85725 ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr
85726 yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy
85727 7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah
85728 ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN
85729 5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb
85730 /UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa
85731 5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK
85732 G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP
85733 82Z+
85734 -----END CERTIFICATE-----
85735
85736 WoSign
85737 ======
85738 -----BEGIN CERTIFICATE-----
85739 MIIFdjCCA16gAwIBAgIQXmjWEXGUY1BWAGjzPsnFkTANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQG
85740 EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxKjAoBgNVBAMTIUNlcnRpZmljYXRpb24g
85741 QXV0aG9yaXR5IG9mIFdvU2lnbjAeFw0wOTA4MDgwMTAwMDFaFw0zOTA4MDgwMTAwMDFaMFUxCzAJ
85742 BgNVBAYTAkNOMRowGAYDVQQKExFXb1NpZ24gQ0EgTGltaXRlZDEqMCgGA1UEAxMhQ2VydGlmaWNh
85743 dGlvbiBBdXRob3JpdHkgb2YgV29TaWduMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA
85744 vcqNrLiRFVaXe2tcesLea9mhsMMQI/qnobLMMfo+2aYpbxY94Gv4uEBf2zmoAHqLoE1UfcIiePyO
85745 CbiohdfMlZdLdNiefvAA5A6JrkkoRBoQmTIPJYhTpA2zDxIIFgsDcSccf+Hb0v1naMQFXQoOXXDX
85746 2JegvFNBmpGN9J42Znp+VsGQX+axaCA2pIwkLCxHC1l2ZjC1vt7tj/id07sBMOby8w7gLJKA84X5
85747 KIq0VC6a7fd2/BVoFutKbOsuEo/Uz/4Mx1wdC34FMr5esAkqQtXJTpCzWQ27en7N1QhatH/YHGkR
85748 +ScPewavVIMYe+HdVHpRaG53/Ma/UkpmRqGyZxq7o093oL5d//xWC0Nyd5DKnvnyOfUNqfTq1+ez
85749 EC8wQjchzDBwyYaYD8xYTYO7feUapTeNtqwylwA6Y3EkHp43xP901DfA4v6IRmAR3Qg/UDaruHqk
85750 lWJqbrDKaiFaafPz+x1wOZXzp26mgYmhiMU7ccqjUu6Du/2gd/Tkb+dC221KmYo0SLwX3OSACCK2
85751 8jHAPwQ+658geda4BmRkAjHXqc1S+4RFaQkAKtxVi8QGRkvASh0JWzko/amrzgD5LkhLJuYwTKVY
85752 yrREgk/nkR4zw7CT/xH8gdLKH3Ep3XZPkiWvHYG3Dy+MwwbMLyejSuQOmbp8HkUff6oZRZb9/D0C
85753 AwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFOFmzw7R
85754 8bNLtwYgFP6HEtX2/vs+MA0GCSqGSIb3DQEBBQUAA4ICAQCoy3JAsnbBfnv8rWTjMnvMPLZdRtP1
85755 LOJwXcgu2AZ9mNELIaCJWSQBnfmvCX0KI4I01fx8cpm5o9dU9OpScA7F9dY74ToJMuYhOZO9sxXq
85756 T2r09Ys/L3yNWC7F4TmgPsc9SnOeQHrAK2GpZ8nzJLmzbVUsWh2eJXLOC62qx1ViC777Y7NhRCOj
85757 y+EaDveaBk3e1CNOIZZbOVtXHS9dCF4Jef98l7VNg64N1uajeeAz0JmWAjCnPv/So0M/BVoG6kQC
85758 2nz4SNAzqfkHx5Xh9T71XXG68pWpdIhhWeO/yloTunK0jF02h+mmxTwTv97QRCbut+wucPrXnbes
85759 5cVAWubXbHssw1abR80LzvobtCHXt2a49CUwi1wNuepnsvRtrtWhnk/Yn+knArAdBtaP4/tIEp9/
85760 EaEQPkxROpaw0RPxx9gmrjrKkcRpnd8BKWRRb2jaFOwIQZeQjdCygPLPwj2/kWjFgGcexGATVdVh
85761 mVd8upUPYUk6ynW8yQqTP2cOEvIo4jEbwFcW3wh8GcF+Dx+FHgo2fFt+J7x6v+Db9NpSvd4MVHAx
85762 kUOVyLzwPt0JfjBkUO1/AaQzZ01oT74V77D2AhGiGxMlOtzCWfHjXEa7ZywCRuoeSKbmW9m1vFGi
85763 kpbbqsY3Iqb+zCB0oy2pLmvLwIIRIbWTee5Ehr7XHuQe+w==
85764 -----END CERTIFICATE-----
85765
85766 WoSign China
85767 ============
85768 -----BEGIN CERTIFICATE-----
85769 MIIFWDCCA0CgAwIBAgIQUHBrzdgT/BtOOzNy0hFIjTANBgkqhkiG9w0BAQsFADBGMQswCQYDVQQG
85770 EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxGzAZBgNVBAMMEkNBIOayg+mAmuagueiv
85771 geS5pjAeFw0wOTA4MDgwMTAwMDFaFw0zOTA4MDgwMTAwMDFaMEYxCzAJBgNVBAYTAkNOMRowGAYD
85772 VQQKExFXb1NpZ24gQ0EgTGltaXRlZDEbMBkGA1UEAwwSQ0Eg5rKD6YCa5qC56K+B5LmmMIICIjAN
85773 BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0EkhHiX8h8EqwqzbdoYGTufQdDTc7WU1/FDWiD+k
85774 8H/rD195L4mx/bxjWDeTmzj4t1up+thxx7S8gJeNbEvxUNUqKaqoGXqW5pWOdO2XCld19AXbbQs5
85775 uQF/qvbW2mzmBeCkTVL829B0txGMe41P/4eDrv8FAxNXUDf+jJZSEExfv5RxadmWPgxDT74wwJ85
85776 dE8GRV2j1lY5aAfMh09Qd5Nx2UQIsYo06Yms25tO4dnkUkWMLhQfkWsZHWgpLFbE4h4TV2TwYeO5
85777 Ed+w4VegG63XX9Gv2ystP9Bojg/qnw+LNVgbExz03jWhCl3W6t8Sb8D7aQdGctyB9gQjF+BNdeFy
85778 b7Ao65vh4YOhn0pdr8yb+gIgthhid5E7o9Vlrdx8kHccREGkSovrlXLp9glk3Kgtn3R46MGiCWOc
85779 76DbT52VqyBPt7D3h1ymoOQ3OMdc4zUPLK2jgKLsLl3Az+2LBcLmc272idX10kaO6m1jGx6KyX2m
85780 +Jzr5dVjhU1zZmkR/sgO9MHHZklTfuQZa/HpelmjbX7FF+Ynxu8b22/8DU0GAbQOXDBGVWCvOGU6
85781 yke6rCzMRh+yRpY/8+0mBe53oWprfi1tWFxK1I5nuPHa1UaKJ/kR8slC/k7e3x9cxKSGhxYzoacX
85782 GKUN5AXlK8IrC6KVkLn9YDxOiT7nnO4fuwECAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1Ud
85783 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFOBNv9ybQV0T6GTwp+kVpOGBwboxMA0GCSqGSIb3DQEBCwUA
85784 A4ICAQBqinA4WbbaixjIvirTthnVZil6Xc1bL3McJk6jfW+rtylNpumlEYOnOXOvEESS5iVdT2H6
85785 yAa+Tkvv/vMx/sZ8cApBWNromUuWyXi8mHwCKe0JgOYKOoICKuLJL8hWGSbueBwj/feTZU7n85iY
85786 r83d2Z5AiDEoOqsuC7CsDCT6eiaY8xJhEPRdF/d+4niXVOKM6Cm6jBAyvd0zaziGfjk9DgNyp115
85787 j0WKWa5bIW4xRtVZjc8VX90xJc/bYNaBRHIpAlf2ltTW/+op2znFuCyKGo3Oy+dCMYYFaA6eFN0A
85788 kLppRQjbbpCBhqcqBT/mhDn4t/lXX0ykeVoQDF7Va/81XwVRHmyjdanPUIPTfPRm94KNPQx96N97
85789 qA4bLJyuQHCH2u2nFoJavjVsIE4iYdm8UXrNemHcSxH5/mc0zy4EZmFcV5cjjPOGG0jfKq+nwf/Y
85790 jj4Du9gqsPoUJbJRa4ZDhS4HIxaAjUz7tGM7zMN07RujHv41D198HRaG9Q7DlfEvr10lO1Hm13ZB
85791 ONFLAzkopR6RctR9q5czxNM+4Gm2KHmgCY0c0f9BckgG/Jou5yD5m6Leie2uPAmvylezkolwQOQv
85792 T8Jwg0DXJCxr5wkf09XHwQj02w47HAcLQxGEIYbpgNR12KvxAmLBsX5VYc8T1yaw15zLKYs4SgsO
85793 kI26oQ==
85794 -----END CERTIFICATE-----
85795
85796 COMODO RSA Certification Authority
85797 ==================================
85798 -----BEGIN CERTIFICATE-----
85799 MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE
85800 BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
85801 A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv
85802 biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC
85803 R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
85804 ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB
85805 dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn
85806 dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ
85807 FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+
85808 5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG
85809 x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX
85810 2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL
85811 OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3
85812 sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C
85813 GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5
85814 WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
85815 FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w
85816 DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt
85817 rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+
85818 nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg
85819 tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW
85820 sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp
85821 pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA
85822 zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq
85823 ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52
85824 7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I
85825 LaZRfyHBNVOFBkpdn627G190
85826 -----END CERTIFICATE-----
85827
85828 USERTrust RSA Certification Authority
85829 =====================================
85830 -----BEGIN CERTIFICATE-----
85831 MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UE
85832 BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
85833 ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
85834 dGlvbiBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UE
85835 BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
85836 ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
85837 dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz
85838 0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2j
85839 Y0K2dvKpOyuR+OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn
85840 RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O
85841 +T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq
85842 /nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKE
85843 Y1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJM
85844 lXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8
85845 yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+
85846 eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
85847 BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
85848 MAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPFUp/L+M+ZBn8b2kMVn54CVVeW
85849 FPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KOVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ
85850 7l8wXEskEVX/JJpuXior7gtNn3/3ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQ
85851 Eg9zKC7F4iRO/Fjs8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM
85852 8WcRiQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYzeSf7dNXGi
85853 FSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZXHlKYC6SQK5MNyosycdi
85854 yA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9c
85855 J2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRBVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGw
85856 sAvgnEzDHNb842m1R0aBL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gx
85857 Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9
85858 -----END CERTIFICATE-----
85859
85860 USERTrust ECC Certification Authority
85861 =====================================
85862 -----BEGIN CERTIFICATE-----
85863 MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC
85864 VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
85865 aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
85866 biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC
85867 VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
85868 aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
85869 biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2
85870 0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez
85871 nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV
85872 HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB
85873 HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu
85874 9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
85875 -----END CERTIFICATE-----
85876
85877 GlobalSign ECC Root CA - R4
85878 ===========================
85879 -----BEGIN CERTIFICATE-----
85880 MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEkMCIGA1UECxMb
85881 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
85882 EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
85883 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
85884 EwpHbG9iYWxTaWduMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprl
85885 OQcJFspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAwDgYDVR0P
85886 AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61FuOJAf/sKbvu+M8k8o4TV
85887 MAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGXkPoUVy0D7O48027KqGx2vKLeuwIgJ6iF
85888 JzWbVsaj8kfSt24bAgAXqmemFZHe+pTsewv4n4Q=
85889 -----END CERTIFICATE-----
85890
85891 GlobalSign ECC Root CA - R5
85892 ===========================
85893 -----BEGIN CERTIFICATE-----
85894 MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb
85895 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
85896 EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
85897 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
85898 EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6
85899 SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS
85900 h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
85901 BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx
85902 uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7
85903 yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3
85904 -----END CERTIFICATE-----
85905
85906 Staat der Nederlanden Root CA - G3
85907 ==================================
85908 -----BEGIN CERTIFICATE-----
85909 MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
85910 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
85911 Um9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloXDTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMC
85912 TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
85913 ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4y
85914 olQPcPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WWIkYFsO2t
85915 x1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqXxz8ecAgwoNzFs21v0IJy
85916 EavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFyKJLZWyNtZrVtB0LrpjPOktvA9mxjeM3K
85917 Tj215VKb8b475lRgsGYeCasH/lSJEULR9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUur
85918 mkVLoR9BvUhTFXFkC4az5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU5
85919 1nus6+N86U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7Ngzp
85920 07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHPbMk7ccHViLVlvMDo
85921 FxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXtBznaqB16nzaeErAMZRKQFWDZJkBE
85922 41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTtXUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMB
85923 AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleu
85924 yjWcLhL75LpdINyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD
85925 U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwpLiniyMMB8jPq
85926 KqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8Ipf3YF3qKS9Ysr1YvY2WTxB1
85927 v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixpgZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA
85928 8KCWAg8zxXHzniN9lLf9OtMJgwYh/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b
85929 8KKaa8MFSu1BYBQw0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0r
85930 mj1AfsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq4BZ+Extq
85931 1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR1VmiiXTTn74eS9fGbbeI
85932 JG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/QFH1T/U67cjF68IeHRaVesd+QnGTbksV
85933 tzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM94B7IWcnMFk=
85934 -----END CERTIFICATE-----
85935
85936 Staat der Nederlanden EV Root CA
85937 ================================
85938 -----BEGIN CERTIFICATE-----
85939 MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJOTDEeMBwGA1UE
85940 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
85941 RVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0yMjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5M
85942 MR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRl
85943 cmxhbmRlbiBFViBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkk
85944 SzrSM4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nCUiY4iKTW
85945 O0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3dZ//BYY1jTw+bbRcwJu+r
85946 0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46prfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8
85947 Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13lpJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gV
85948 XJrm0w912fxBmJc+qiXbj5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr
85949 08C+eKxCKFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS/ZbV
85950 0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0XcgOPvZuM5l5Tnrmd
85951 74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH1vI4gnPah1vlPNOePqc7nvQDs/nx
85952 fRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrPpx9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNC
85953 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwa
85954 ivsnuL8wbqg7MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI
85955 eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u2dfOWBfoqSmu
85956 c0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHSv4ilf0X8rLiltTMMgsT7B/Zq
85957 5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTCwPTxGfARKbalGAKb12NMcIxHowNDXLldRqAN
85958 b/9Zjr7dn3LDWyvfjFvO5QxGbJKyCqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tN
85959 f1zuacpzEPuKqf2evTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi
85960 5Dp6Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIaGl6I6lD4
85961 WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeLeG9QgkRQP2YGiqtDhFZK
85962 DyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGy
85963 eUN51q1veieQA6TqJIc/2b3Z6fJfUEkc7uzXLg==
85964 -----END CERTIFICATE-----
85965
85966 IdenTrust Commercial Root CA 1
85967 ==============================
85968 -----BEGIN CERTIFICATE-----
85969 MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG
85970 EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS
85971 b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES
85972 MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB
85973 IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld
85974 hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/
85975 mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi
85976 1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C
85977 XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl
85978 3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy
85979 NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV
85980 WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg
85981 xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix
85982 uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
85983 AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI
85984 hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH
85985 6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg
85986 ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt
85987 ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV
85988 YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX
85989 feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro
85990 kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe
85991 2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz
85992 Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R
85993 cGzM7vRX+Bi6hG6H
85994 -----END CERTIFICATE-----
85995
85996 IdenTrust Public Sector Root CA 1
85997 =================================
85998 -----BEGIN CERTIFICATE-----
85999 MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG
86000 EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv
86001 ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV
86002 UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS
86003 b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy
86004 P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6
86005 Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI
86006 rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf
86007 qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS
86008 mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn
86009 ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh
86010 LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v
86011 iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL
86012 4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B
86013 Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw
86014 DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj
86015 t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A
86016 mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt
86017 GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt
86018 m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx
86019 NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4
86020 Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI
86021 ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC
86022 ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ
86023 3Wl9af0AVqW3rLatt8o+Ae+c
86024 -----END CERTIFICATE-----
86025
86026 Entrust Root Certification Authority - G2
86027 =========================================
86028 -----BEGIN CERTIFICATE-----
86029 MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV
86030 BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy
86031 bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug
86032 b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw
86033 HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT
86034 DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx
86035 OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s
86036 eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi
86037 MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP
86038 /vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz
86039 HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU
86040 s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y
86041 TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx
86042 AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6
86043 0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z
86044 iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
86045 Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi
86046 nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+
86047 vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO
86048 e4pIb4tF9g==
86049 -----END CERTIFICATE-----
86050
86051 Entrust Root Certification Authority - EC1
86052 ==========================================
86053 -----BEGIN CERTIFICATE-----
86054 MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx
86055 FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn
86056 YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl
86057 ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
86058 IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw
86059 FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs
86060 LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg
86061 dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt
86062 IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy
86063 AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef
86064 9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
86065 FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h
86066 vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8
86067 kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
86068 -----END CERTIFICATE-----
86069
86070 CFCA EV ROOT
86071 ============
86072 -----BEGIN CERTIFICATE-----
86073 MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE
86074 CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB
86075 IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw
86076 MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD
86077 DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV
86078 BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD
86079 7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN
86080 uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW
86081 ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7
86082 xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f
86083 py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K
86084 gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol
86085 hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ
86086 tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf
86087 BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB
86088 /wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB
86089 ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q
86090 ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua
86091 4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG
86092 E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX
86093 BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn
86094 aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy
86095 PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX
86096 kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C
86097 ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
86098 -----END CERTIFICATE-----
86099
86100 TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H5
86101 ====================================================
86102 -----BEGIN CERTIFICATE-----
86103 MIIEJzCCAw+gAwIBAgIHAI4X/iQggTANBgkqhkiG9w0BAQsFADCBsTELMAkGA1UEBhMCVFIxDzAN
86104 BgNVBAcMBkFua2FyYTFNMEsGA1UECgxEVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp
86105 bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4xQjBABgNVBAMMOVTDnFJLVFJVU1Qg
86106 RWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSBINTAeFw0xMzA0MzAw
86107 ODA3MDFaFw0yMzA0MjgwODA3MDFaMIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0w
86108 SwYDVQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnE
86109 n2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBFbGVrdHJvbmlrIFNlcnRp
86110 ZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
86111 CgKCAQEApCUZ4WWe60ghUEoI5RHwWrom/4NZzkQqL/7hzmAD/I0Dpe3/a6i6zDQGn1k19uwsu537
86112 jVJp45wnEFPzpALFp/kRGml1bsMdi9GYjZOHp3GXDSHHmflS0yxjXVW86B8BSLlg/kJK9siArs1m
86113 ep5Fimh34khon6La8eHBEJ/rPCmBp+EyCNSgBbGM+42WAA4+Jd9ThiI7/PS98wl+d+yG6w8z5UNP
86114 9FR1bSmZLmZaQ9/LXMrI5Tjxfjs1nQ/0xVqhzPMggCTTV+wVunUlm+hkS7M0hO8EuPbJbKoCPrZV
86115 4jI3X/xml1/N1p7HIL9Nxqw/dV8c7TKcfGkAaZHjIxhT6QIDAQABo0IwQDAdBgNVHQ4EFgQUVpkH
86116 HtOsDGlktAxQR95DLL4gwPswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
86117 hvcNAQELBQADggEBAJ5FdnsXSDLyOIspve6WSk6BGLFRRyDN0GSxDsnZAdkJzsiZ3GglE9Rc8qPo
86118 BP5yCccLqh0lVX6Wmle3usURehnmp349hQ71+S4pL+f5bFgWV1Al9j4uPqrtd3GqqpmWRgqujuwq
86119 URawXs3qZwQcWDD1YIq9pr1N5Za0/EKJAWv2cMhQOQwt1WbZyNKzMrcbGW3LM/nfpeYVhDfwwvJl
86120 lpKQd/Ct9JDpEXjXk4nAPQu6KfTomZ1yju2dL+6SfaHx/126M2CFYv4HAqGEVka+lgqaE9chTLd8
86121 B59OTj+RdPsnnRHM3eaxynFNExc5JsUpISuTKWqW+qtB4Uu2NQvAmxU=
86122 -----END CERTIFICATE-----
86123
86124 Certinomis - Root CA
86125 ====================
86126 -----BEGIN CERTIFICATE-----
86127 MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjETMBEGA1UEChMK
86128 Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAbBgNVBAMTFENlcnRpbm9taXMg
86129 LSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMzMTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIx
86130 EzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRD
86131 ZXJ0aW5vbWlzIC0gUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQos
86132 P5L2fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJflLieY6pOo
86133 d5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQVWZUKxkd8aRi5pwP5ynap
86134 z8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDFTKWrteoB4owuZH9kb/2jJZOLyKIOSY00
86135 8B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09x
86136 RLWtwHkziOC/7aOgFLScCbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE
86137 6OXWk6RiwsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJwx3t
86138 FvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SGm/lg0h9tkQPTYKbV
86139 PZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4F2iw4lNVYC2vPsKD2NkJK/DAZNuH
86140 i5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZngWVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGj
86141 YzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I
86142 6tNxIqSSaHh02TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF
86143 AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/0KGRHCwPT5iV
86144 WVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWwF6YSjNRieOpWauwK0kDDPAUw
86145 Pk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZSg081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAX
86146 lCOotQqSD7J6wWAsOMwaplv/8gzjqh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJ
86147 y29SWwNyhlCVCNSNh4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9
86148 Iff/ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8Vbtaw5Bng
86149 DwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwjY/M50n92Uaf0yKHxDHYi
86150 I0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nM
86151 cyrDflOR1m749fPH0FFNjkulW+YZFzvWgQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVr
86152 hkIGuUE=
86153 -----END CERTIFICATE-----
86154
86155 OISTE WISeKey Global Root GB CA
86156 ===============================
86157 -----BEGIN CERTIFICATE-----
86158 MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG
86159 EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl
86160 ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw
86161 MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD
86162 VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds
86163 b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX
86164 scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP
86165 rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk
86166 9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o
86167 Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg
86168 GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
86169 /zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI
86170 hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD
86171 dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0
86172 VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui
86173 HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic
86174 Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM=
86175 -----END CERTIFICATE-----
86176
86177 Certification Authority of WoSign G2
86178 ====================================
86179 -----BEGIN CERTIFICATE-----
86180 MIIDfDCCAmSgAwIBAgIQayXaioidfLwPBbOxemFFRDANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQG
86181 EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxLTArBgNVBAMTJENlcnRpZmljYXRpb24g
86182 QXV0aG9yaXR5IG9mIFdvU2lnbiBHMjAeFw0xNDExMDgwMDU4NThaFw00NDExMDgwMDU4NThaMFgx
86183 CzAJBgNVBAYTAkNOMRowGAYDVQQKExFXb1NpZ24gQ0EgTGltaXRlZDEtMCsGA1UEAxMkQ2VydGlm
86184 aWNhdGlvbiBBdXRob3JpdHkgb2YgV29TaWduIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
86185 CgKCAQEAvsXEoCKASU+/2YcRxlPhuw+9YH+v9oIOH9ywjj2X4FA8jzrvZjtFB5sg+OPXJYY1kBai
86186 XW8wGQiHC38Gsp1ij96vkqVg1CuAmlI/9ZqD6TRay9nVYlzmDuDfBpgOgHzKtB0TiGsOqCR3A9Du
86187 W/PKaZE1OVbFbeP3PU9ekzgkyhjpJMuSA93MHD0JcOQg5PGurLtzaaNjOg9FD6FKmsLRY6zLEPg9
86188 5k4ot+vElbGs/V6r+kHLXZ1L3PR8du9nfwB6jdKgGlxNIuG12t12s9R23164i5jIFFTMaxeSt+BK
86189 v0mUYQs4kI9dJGwlezt52eJ+na2fmKEG/HgUYFf47oB3sQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
86190 AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU+mCp62XF3RYUCE4MD42b4Pdkr2cwDQYJKoZI
86191 hvcNAQELBQADggEBAFfDejaCnI2Y4qtAqkePx6db7XznPWZaOzG73/MWM5H8fHulwqZm46qwtyeY
86192 P0nXYGdnPzZPSsvxFPpahygc7Y9BMsaV+X3avXtbwrAh449G3CE4Q3RM+zD4F3LBMvzIkRfEzFg3
86193 TgvMWvchNSiDbGAtROtSjFA9tWwS1/oJu2yySrHFieT801LYYRf+epSEj3m2M1m6D8QL4nCgS3gu
86194 +sif/a+RZQp4OBXllxcU3fngLDT4ONCEIgDAFFEYKwLcMFrw6AF8NTojrwjkr6qOKEJJLvD1mTS+
86195 7Q9LGOHSJDy7XUe3IfKN0QqZjuNuPq1w4I+5ysxugTH2e5x6eeRncRg=
86196 -----END CERTIFICATE-----
86197
86198 CA WoSign ECC Root
86199 ==================
86200 -----BEGIN CERTIFICATE-----
86201 MIICCTCCAY+gAwIBAgIQaEpYcIBr8I8C+vbe6LCQkDAKBggqhkjOPQQDAzBGMQswCQYDVQQGEwJD
86202 TjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxGzAZBgNVBAMTEkNBIFdvU2lnbiBFQ0MgUm9v
86203 dDAeFw0xNDExMDgwMDU4NThaFw00NDExMDgwMDU4NThaMEYxCzAJBgNVBAYTAkNOMRowGAYDVQQK
86204 ExFXb1NpZ24gQ0EgTGltaXRlZDEbMBkGA1UEAxMSQ0EgV29TaWduIEVDQyBSb290MHYwEAYHKoZI
86205 zj0CAQYFK4EEACIDYgAE4f2OuEMkq5Z7hcK6C62N4DrjJLnSsb6IOsq/Srj57ywvr1FQPEd1bPiU
86206 t5v8KB7FVMxjnRZLU8HnIKvNrCXSf4/CwVqCXjCLelTOA7WRf6qU0NGKSMyCBSah1VES1ns2o0Iw
86207 QDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUqv3VWqP2h4syhf3R
86208 MluARZPzA7gwCgYIKoZIzj0EAwMDaAAwZQIxAOSkhLCB1T2wdKyUpOgOPQB0TKGXa/kNUTyh2Tv0
86209 Daupn75OcsqF1NnstTJFGG+rrQIwfcf3aWMvoeGY7xMQ0Xk/0f7qO3/eVvSQsRUR2LIiFdAvwyYu
86210 a/GRspBl9JrmkO5K
86211 -----END CERTIFICATE-----
86212
86213 SZAFIR ROOT CA2
86214 ===============
86215 -----BEGIN CERTIFICATE-----
86216 MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG
86217 A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV
86218 BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ
86219 BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD
86220 VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q
86221 qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK
86222 DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE
86223 2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ
86224 ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi
86225 ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
86226 AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC
86227 AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5
86228 O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67
86229 oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul
86230 4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6
86231 +/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw==
86232 -----END CERTIFICATE-----
86233
86234 Certum Trusted Network CA 2
86235 ===========================
86236 -----BEGIN CERTIFICATE-----
86237 MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE
86238 BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1
86239 bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y
86240 ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ
86241 TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl
86242 cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB
86243 IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9
86244 7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o
86245 CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b
86246 Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p
86247 uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130
86248 GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ
86249 9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB
86250 Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye
86251 hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM
86252 BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
86253 AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI
86254 hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW
86255 Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA
86256 L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo
86257 clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM
86258 pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb
86259 w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo
86260 J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm
86261 ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX
86262 is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7
86263 zAYspsbiDrW5viSP
86264 -----END CERTIFICATE-----
86265
86266 Hellenic Academic and Research Institutions RootCA 2015
86267 =======================================================
86268 -----BEGIN CERTIFICATE-----
86269 MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT
86270 BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0
86271 aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl
86272 YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx
86273 MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg
86274 QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV
86275 BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw
86276 MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv
86277 bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh
86278 iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+
86279 6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd
86280 FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr
86281 i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F
86282 GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2
86283 fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu
86284 iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc
86285 Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
86286 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI
86287 hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+
86288 D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM
86289 d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y
86290 d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn
86291 82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb
86292 davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F
86293 Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt
86294 J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa
86295 JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q
86296 p/UsQu0yrbYhnr68
86297 -----END CERTIFICATE-----
86298
86299 Hellenic Academic and Research Institutions ECC RootCA 2015
86300 ===========================================================
86301 -----BEGIN CERTIFICATE-----
86302 MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0
86303 aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u
86304 cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj
86305 aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw
86306 MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj
86307 IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD
86308 VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290
86309 Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP
86310 dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK
86311 Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
86312 BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA
86313 GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn
86314 dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR
86315 -----END CERTIFICATE-----
86316
86317 Certplus Root CA G1
86318 ===================
86319 -----BEGIN CERTIFICATE-----
86320 MIIFazCCA1OgAwIBAgISESBVg+QtPlRWhS2DN7cs3EYRMA0GCSqGSIb3DQEBDQUAMD4xCzAJBgNV
86321 BAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMTAe
86322 Fw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhD
86323 ZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQAD
86324 ggIPADCCAgoCggIBANpQh7bauKk+nWT6VjOaVj0W5QOVsjQcmm1iBdTYj+eJZJ+622SLZOZ5KmHN
86325 r49aiZFluVj8tANfkT8tEBXgfs+8/H9DZ6itXjYj2JizTfNDnjl8KvzsiNWI7nC9hRYt6kuJPKNx
86326 Qv4c/dMcLRC4hlTqQ7jbxofaqK6AJc96Jh2qkbBIb6613p7Y1/oA/caP0FG7Yn2ksYyy/yARujVj
86327 BYZHYEMzkPZHogNPlk2dT8Hq6pyi/jQu3rfKG3akt62f6ajUeD94/vI4CTYd0hYCyOwqaK/1jpTv
86328 LRN6HkJKHRUxrgwEV/xhc/MxVoYxgKDEEW4wduOU8F8ExKyHcomYxZ3MVwia9Az8fXoFOvpHgDm2
86329 z4QTd28n6v+WZxcIbekN1iNQMLAVdBM+5S//Ds3EC0pd8NgAM0lm66EYfFkuPSi5YXHLtaW6uOrc
86330 4nBvCGrch2c0798wct3zyT8j/zXhviEpIDCB5BmlIOklynMxdCm+4kLV87ImZsdo/Rmz5yCTmehd
86331 4F6H50boJZwKKSTUzViGUkAksnsPmBIgJPaQbEfIDbsYIC7Z/fyL8inqh3SV4EJQeIQEQWGw9CEj
86332 jy3LKCHyamz0GqbFFLQ3ZU+V/YDI+HLlJWvEYLF7bY5KinPOWftwenMGE9nTdDckQQoRb5fc5+R+
86333 ob0V8rqHDz1oihYHAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0G
86334 A1UdDgQWBBSowcCbkahDFXxdBie0KlHYlwuBsTAfBgNVHSMEGDAWgBSowcCbkahDFXxdBie0KlHY
86335 lwuBsTANBgkqhkiG9w0BAQ0FAAOCAgEAnFZvAX7RvUz1isbwJh/k4DgYzDLDKTudQSk0YcbX8ACh
86336 66Ryj5QXvBMsdbRX7gp8CXrc1cqh0DQT+Hern+X+2B50ioUHj3/MeXrKls3N/U/7/SMNkPX0XtPG
86337 YX2eEeAC7gkE2Qfdpoq3DIMku4NQkv5gdRE+2J2winq14J2by5BSS7CTKtQ+FjPlnsZlFT5kOwQ/
86338 2wyPX1wdaR+v8+khjPPvl/aatxm2hHSco1S1cE5j2FddUyGbQJJD+tZ3VTNPZNX70Cxqjm0lpu+F
86339 6ALEUz65noe8zDUa3qHpimOHZR4RKttjd5cUvpoUmRGywO6wT/gUITJDT5+rosuoD6o7BlXGEilX
86340 CNQ314cnrUlZp5GrRHpejXDbl85IULFzk/bwg2D5zfHhMf1bfHEhYxQUqq/F3pN+aLHsIqKqkHWe
86341 tUNy6mSjhEv9DKgma3GX7lZjZuhCVPnHHd/Qj1vfyDBviP4NxDMcU6ij/UgQ8uQKTuEVV/xuZDDC
86342 VRHc6qnNSlSsKWNEz0pAoNZoWRsz+e86i9sgktxChL8Bq4fA1SCC28a5g4VCXA9DO2pJNdWY9BW/
86343 +mGBDAkgGNLQFwzLSABQ6XaCjGTXOqAHVcweMcDvOrRl++O/QmueD6i9a5jc2NvLi6Td11n0bt3+
86344 qsOR0C5CB8AMTVPNJLFMWx5R9N/pkvo=
86345 -----END CERTIFICATE-----
86346
86347 Certplus Root CA G2
86348 ===================
86349 -----BEGIN CERTIFICATE-----
86350 MIICHDCCAaKgAwIBAgISESDZkc6uo+jF5//pAq/Pc7xVMAoGCCqGSM49BAMDMD4xCzAJBgNVBAYT
86351 AkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMjAeFw0x
86352 NDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0
86353 cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IA
86354 BM0PW1aC3/BFGtat93nwHcmsltaeTpwftEIRyoa/bfuFo8XlGVzX7qY/aWfYeOKmycTbLXku54uN
86355 Am8xIk0G42ByRZ0OQneezs/lf4WbGOT8zC5y0xaTTsqZY1yhBSpsBqNjMGEwDgYDVR0PAQH/BAQD
86356 AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMB8GA1Ud
86357 IwQYMBaAFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMAoGCCqGSM49BAMDA2gAMGUCMHD+sAvZ94OX7PNV
86358 HdTcswYO/jOYnYs5kGuUIe22113WTNchp+e/IQ8rzfcq3IUHnQIxAIYUFuXcsGXCwI4Un78kFmjl
86359 vPl5adytRSv3tjFzzAalU5ORGpOucGpnutee5WEaXw==
86360 -----END CERTIFICATE-----
86361
86362 OpenTrust Root CA G1
86363 ====================
86364 -----BEGIN CERTIFICATE-----
86365 MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUAMEAxCzAJBgNV
86366 BAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcx
86367 MB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoM
86368 CU9wZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEB
86369 AQUAA4ICDwAwggIKAoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7fa
86370 Yp6bwiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX/uMftk87
86371 ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR077F9jAHiOH3BX2pfJLKO
86372 YheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGPuY4zbGneWK2gDqdkVBFpRGZPTBKnjix9
86373 xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLxp2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO
86374 9z0M+Yo0FMT7MzUj8czxKselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq
86375 3ywgsNw2TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+WG+Oi
86376 n6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPwvFEVVJSmdz7QdFG9
86377 URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYYEQRVzXR7z2FwefR7LFxckvzluFqr
86378 TJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
86379 /zAdBgNVHQ4EFgQUl0YhVyE12jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/Px
86380 N3DlCPaTKbYwDQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E
86381 PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kfgLMtMrpkZ2Cv
86382 uVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbSFXJfLkur1J1juONI5f6ELlgK
86383 n0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLh
86384 X4SPgPL0DTatdrOjteFkdjpY3H1PXlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80
86385 nR14SohWZ25g/4/Ii+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcm
86386 GS3tTAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L9109S5zvE/
86387 bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/KyPu1svf0OnWZzsD2097+o
86388 4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJAwSQiumPv+i2tCqjI40cHLI5kqiPAlxA
86389 OXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj1oxx
86390 -----END CERTIFICATE-----
86391
86392 OpenTrust Root CA G2
86393 ====================
86394 -----BEGIN CERTIFICATE-----
86395 MIIFbzCCA1egAwIBAgISESChaRu/vbm9UpaPI+hIvyYRMA0GCSqGSIb3DQEBDQUAMEAxCzAJBgNV
86396 BAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcy
86397 MB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoM
86398 CU9wZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzIwggIiMA0GCSqGSIb3DQEB
86399 AQUAA4ICDwAwggIKAoICAQDMtlelM5QQgTJT32F+D3Y5z1zCU3UdSXqWON2ic2rxb95eolq5cSG+
86400 Ntmh/LzubKh8NBpxGuga2F8ORAbtp+Dz0mEL4DKiltE48MLaARf85KxP6O6JHnSrT78eCbY2albz
86401 4e6WiWYkBuTNQjpK3eCasMSCRbP+yatcfD7J6xcvDH1urqWPyKwlCm/61UWY0jUJ9gNDlP7ZvyCV
86402 eYCYitmJNbtRG6Q3ffyZO6v/v6wNj0OxmXsWEH4db0fEFY8ElggGQgT4hNYdvJGmQr5J1WqIP7wt
86403 UdGejeBSzFfdNTVY27SPJIjki9/ca1TSgSuyzpJLHB9G+h3Ykst2Z7UJmQnlrBcUVXDGPKBWCgOz
86404 3GIZ38i1MH/1PCZ1Eb3XG7OHngevZXHloM8apwkQHZOJZlvoPGIytbU6bumFAYueQ4xncyhZW+vj
86405 3CzMpSZyYhK05pyDRPZRpOLAeiRXyg6lPzq1O4vldu5w5pLeFlwoW5cZJ5L+epJUzpM5ChaHvGOz
86406 9bGTXOBut9Dq+WIyiET7vycotjCVXRIouZW+j1MY5aIYFuJWpLIsEPUdN6b4t/bQWVyJ98LVtZR0
86407 0dX+G7bw5tYee9I8y6jj9RjzIR9u701oBnstXW5DiabA+aC/gh7PU3+06yzbXfZqfUAkBXKJOAGT
86408 y3HCOV0GEfZvePg3DTmEJwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
86409 /zAdBgNVHQ4EFgQUajn6QiL35okATV59M4PLuG53hq8wHwYDVR0jBBgwFoAUajn6QiL35okATV59
86410 M4PLuG53hq8wDQYJKoZIhvcNAQENBQADggIBAJjLq0A85TMCl38th6aP1F5Kr7ge57tx+4BkJamz
86411 Gj5oXScmp7oq4fBXgwpkTx4idBvpkF/wrM//T2h6OKQQbA2xx6R3gBi2oihEdqc0nXGEL8pZ0keI
86412 mUEiyTCYYW49qKgFbdEfwFFEVn8nNQLdXpgKQuswv42hm1GqO+qTRmTFAHneIWv2V6CG1wZy7HBG
86413 S4tz3aAhdT7cHcCP009zHIXZ/n9iyJVvttN7jLpTwm+bREx50B1ws9efAvSyB7DH5fitIw6mVskp
86414 EndI2S9G/Tvw/HRwkqWOOAgfZDC2t0v7NqwQjqBSM2OdAzVWxWm9xiNaJ5T2pBL4LTM8oValX9YZ
86415 6e18CL13zSdkzJTaTkZQh+D5wVOAHrut+0dSixv9ovneDiK3PTNZbNTe9ZUGMg1RGUFcPk8G97kr
86416 gCf2o6p6fAbhQ8MTOWIaNr3gKC6UAuQpLmBVrkA9sHSSXvAgZJY/X0VdiLWK2gKgW0VU3jg9CcCo
86417 SmVGFvyqv1ROTVu+OEO3KMqLM6oaJbolXCkvW0pujOotnCr2BXbgd5eAiN1nE28daCSLT7d0geX0
86418 YJ96Vdc+N9oWaz53rK4YcJUIeSkDiv7BO7M/Gg+kO14fWKGVyasvc0rQLW6aWQ9VGHgtPFGml4vm
86419 u7JwqkwR3v98KzfUetF3NI/n+UL3PIEMS1IK
86420 -----END CERTIFICATE-----
86421
86422 OpenTrust Root CA G3
86423 ====================
86424 -----BEGIN CERTIFICATE-----
86425 MIICITCCAaagAwIBAgISESDm+Ez8JLC+BUCs2oMbNGA/MAoGCCqGSM49BAMDMEAxCzAJBgNVBAYT
86426 AkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEczMB4X
86427 DTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9w
86428 ZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzMwdjAQBgcqhkjOPQIBBgUrgQQA
86429 IgNiAARK7liuTcpm3gY6oxH84Bjwbhy6LTAMidnW7ptzg6kjFYwvWYpa3RTqnVkrQ7cG7DK2uu5B
86430 ta1doYXM6h0UZqNnfkbilPPntlahFVmhTzeXuSIevRHr9LIfXsMUmuXZl5mjYzBhMA4GA1UdDwEB
86431 /wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAf
86432 BgNVHSMEGDAWgBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAKBggqhkjOPQQDAwNpADBmAjEAj6jcnboM
86433 BBf6Fek9LykBl7+BFjNAk2z8+e2AcG+qj9uEwov1NcoG3GRvaBbhj5G5AjEA2Euly8LQCGzpGPta
86434 3U1fJAuwACEl74+nBCZx4nxp5V2a+EEfOzmTk51V6s2N8fvB
86435 -----END CERTIFICATE-----
86436
86437 ISRG Root X1
86438 ============
86439 -----BEGIN CERTIFICATE-----
86440 MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE
86441 BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD
86442 EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG
86443 EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT
86444 DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r
86445 Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1
86446 3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K
86447 b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN
86448 Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ
86449 4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf
86450 1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu
86451 hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH
86452 usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r
86453 OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G
86454 A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY
86455 9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
86456 ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV
86457 0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt
86458 hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw
86459 TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx
86460 e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA
86461 JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD
86462 YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n
86463 JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ
86464 m+kXQ99b21/+jh5Xos1AnX5iItreGCc=
86465 -----END CERTIFICATE-----
86466
86467 AC RAIZ FNMT-RCM
86468 ================
86469 -----BEGIN CERTIFICATE-----
86470 MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT
86471 AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw
86472 MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD
86473 TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
86474 ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf
86475 qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr
86476 btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL
86477 j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou
86478 08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw
86479 WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT
86480 tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ
86481 47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC
86482 ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa
86483 i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
86484 FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o
86485 dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD
86486 nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s
86487 D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ
86488 j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT
86489 Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW
86490 +YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7
86491 Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d
86492 8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm
86493 5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG
86494 rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM=
86495 -----END CERTIFICATE-----
86496
86497 Amazon Root CA 1
86498 ================
86499 -----BEGIN CERTIFICATE-----
86500 MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD
86501 VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1
86502 MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
86503 bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
86504 ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH
86505 FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ
86506 gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t
86507 dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce
86508 VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB
86509 /zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3
86510 DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM
86511 CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy
86512 8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa
86513 2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2
86514 xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5
86515 -----END CERTIFICATE-----
86516
86517 Amazon Root CA 2
86518 ================
86519 -----BEGIN CERTIFICATE-----
86520 MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD
86521 VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1
86522 MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
86523 bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
86524 ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4
86525 kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp
86526 N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9
86527 AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd
86528 fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx
86529 kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS
86530 btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0
86531 Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN
86532 c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+
86533 3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw
86534 DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA
86535 A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
86536 +gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE
86537 YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW
86538 xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ
86539 gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW
86540 aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV
86541 Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3
86542 KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi
86543 JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw=
86544 -----END CERTIFICATE-----
86545
86546 Amazon Root CA 3
86547 ================
86548 -----BEGIN CERTIFICATE-----
86549 MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG
86550 EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy
86551 NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
86552 MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB
86553 f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr
86554 Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43
86555 rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc
86556 eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw==
86557 -----END CERTIFICATE-----
86558
86559 Amazon Root CA 4
86560 ================
86561 -----BEGIN CERTIFICATE-----
86562 MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG
86563 EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy
86564 NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
86565 MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN
86566 /sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri
86567 83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
86568 HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA
86569 MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1
86570 AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA==
86571 -----END CERTIFICATE-----
86572
86573 LuxTrust Global Root 2
86574 ======================
86575 -----BEGIN CERTIFICATE-----
86576 MIIFwzCCA6ugAwIBAgIUCn6m30tEntpqJIWe5rgV0xZ/u7EwDQYJKoZIhvcNAQELBQAwRjELMAkG
86577 A1UEBhMCTFUxFjAUBgNVBAoMDUx1eFRydXN0IFMuQS4xHzAdBgNVBAMMFkx1eFRydXN0IEdsb2Jh
86578 bCBSb290IDIwHhcNMTUwMzA1MTMyMTU3WhcNMzUwMzA1MTMyMTU3WjBGMQswCQYDVQQGEwJMVTEW
86579 MBQGA1UECgwNTHV4VHJ1c3QgUy5BLjEfMB0GA1UEAwwWTHV4VHJ1c3QgR2xvYmFsIFJvb3QgMjCC
86580 AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANeFl78RmOnwYoNMPIf5U2o3C/IPPIfOb9wm
86581 Kb3FibrJgz337spbxm1Jc7TJRqMbNBM/wYlFV/TZsfs2ZUv7COJIcRHIbjuend+JZTemhfY7RBi2
86582 xjcwYkSSl2l9QjAk5A0MiWtj3sXh306pFGxT4GHO9hcvHTy95iJMHZP1EMShduxq3sVs35a0VkBC
86583 wGKSMKEtFZSg0iAGCW5qbeXrt77U8PEVfIvmTroTzEsnXpk8F12PgX8zPU/TPxvsXD/wPEx1bvKm
86584 1Z3aLQdjAsZy6ZS8TEmVT4hSyNvoaYL4zDRbIvCGp4m9SAptZoFtyMhk+wHh9OHe2Z7d21vUKpkm
86585 FRseTJIpgp7VkoGSQXAZ96Tlk0u8d2cx3Rz9MXANF5kM+Qw5GSoXtTBxVdUPrljhPS80m8+f9niF
86586 wpN6cj5mj5wWEWCPnolvZ77gR1o7DJpni89Gxq44o/KnvObWhWszJHAiS8sIm7vI+AIpHb4gDEa/
86587 a4ebsypmQjVGbKq6rfmYe+lQVRQxv7HaLe2ArWgk+2mr2HETMOZns4dA/Yl+8kPREd8vZS9kzl8U
86588 ubG/Mb2HeFpZZYiq/FkySIbWTLkpS5XTdvN3JW1CHDiDTf2jX5t/Lax5Gw5CMZdjpPuKadUiDTSQ
86589 MC6otOBttpSsvItO13D8xTiOZCXhTTmQzsmHhFhxAgMBAAGjgagwgaUwDwYDVR0TAQH/BAUwAwEB
86590 /zBCBgNVHSAEOzA5MDcGByuBKwEBAQowLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9yZXBvc2l0b3J5
86591 Lmx1eHRydXN0Lmx1MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBT/GCh2+UgFLKGu8SsbK7JT
86592 +Et8szAdBgNVHQ4EFgQU/xgodvlIBSyhrvErGyuyU/hLfLMwDQYJKoZIhvcNAQELBQADggIBAGoZ
86593 FO1uecEsh9QNcH7X9njJCwROxLHOk3D+sFTAMs2ZMGQXvw/l4jP9BzZAcg4atmpZ1gDlaCDdLnIN
86594 H2pkMSCEfUmmWjfrRcmF9dTHF5kH5ptV5AzoqbTOjFu1EVzPig4N1qx3gf4ynCSecs5U89BvolbW
86595 7MM3LGVYvlcAGvI1+ut7MV3CwRI9loGIlonBWVx65n9wNOeD4rHh4bhY79SV5GCc8JaXcozrhAIu
86596 ZY+kt9J/Z93I055cqqmkoCUUBpvsT34tC38ddfEz2O3OuHVtPlu5mB0xDVbYQw8wkbIEa91WvpWA
86597 VWe+2M2D2RjuLg+GLZKecBPs3lHJQ3gCpU3I+V/EkVhGFndadKpAvAefMLmx9xIX3eP/JEAdemrR
86598 TxgKqpAd60Ae36EeRJIQmvKN4dFLRp7oRUKX6kWZ8+xm1QL68qZKJKrezrnK+T+Tb/mjuuqlPpmt
86599 /f97mfVl7vBZKGfXkJWkE4SphMHozs51k2MavDzq1WQfLSoSOcbDWjLtR5EWDrw4wVDej8oqkDQc
86600 7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKqv+x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31I
86601 iyBMz2TWuJdGsE7RKlY6oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr
86602 -----END CERTIFICATE-----
86603
86604 TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
86605 =============================================
86606 -----BEGIN CERTIFICATE-----
86607 MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT
86608 D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr
86609 IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g
86610 TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp
86611 ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD
86612 VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt
86613 c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth
86614 bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11
86615 IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
86616 MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8
86617 6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc
86618 wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0
86619 3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9
86620 WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU
86621 ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
86622 KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh
86623 AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc
86624 lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R
86625 e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j
86626 q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM=
86627 -----END CERTIFICATE-----
86628 <?php
86629
86630 if (PHP_SAPI !== 'cli') {
86631     echo 'Warning: Composer should be invoked via the CLI version of PHP, not the '.PHP_SAPI.' SAPI'.PHP_EOL;
86632 }
86633
86634 require __DIR__.'/../src/bootstrap.php';
86635
86636 use Composer\Factory;
86637 use Composer\XdebugHandler;
86638 use Composer\Console\Application;
86639
86640 error_reporting(-1);
86641
86642 // Create output for XdebugHandler and Application
86643 $output = Factory::createOutput();
86644
86645 $xdebug = new XdebugHandler($output);
86646 $xdebug->check();
86647 unset($xdebug);
86648
86649 if (function_exists('ini_set')) {
86650     @ini_set('display_errors', 1);
86651
86652     $memoryInBytes = function ($value) {
86653         $unit = strtolower(substr($value, -1, 1));
86654         $value = (int) $value;
86655         switch($unit) {
86656             case 'g':
86657                 $value *= 1024;
86658                 // no break (cumulative multiplier)
86659             case 'm':
86660                 $value *= 1024;
86661                 // no break (cumulative multiplier)
86662             case 'k':
86663                 $value *= 1024;
86664         }
86665
86666         return $value;
86667     };
86668
86669     $memoryLimit = trim(ini_get('memory_limit'));
86670     // Increase memory_limit if it is lower than 1.5GB
86671     if ($memoryLimit != -1 && $memoryInBytes($memoryLimit) < 1024 * 1024 * 1536) {
86672         @ini_set('memory_limit', '1536M');
86673     }
86674     unset($memoryInBytes, $memoryLimit);
86675 }
86676
86677 putenv('COMPOSER_BINARY='.realpath($_SERVER['argv'][0]));
86678
86679 // run the command application
86680 $application = new Application();
86681 $application->run(null, $output);
86682
86683 Copyright (c) Nils Adermann, Jordi Boggiano
86684
86685 Permission is hereby granted, free of charge, to any person obtaining a copy
86686 of this software and associated documentation files (the "Software"), to deal
86687 in the Software without restriction, including without limitation the rights
86688 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
86689 copies of the Software, and to permit persons to whom the Software is furnished
86690 to do so, subject to the following conditions:
86691
86692 The above copyright notice and this permission notice shall be included in all
86693 copies or substantial portions of the Software.
86694
86695 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
86696 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
86697 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
86698 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
86699 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
86700 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
86701 THE SOFTWARE.
86702
86703 \v\9fè8\965\0\13\8f\98\ e\14\86ªÙ¹?\1d\ 2\0\0\0GBMB