]> git.mxchange.org Git - friendica.git/blob - util/composer.phar
Merge pull request #3943 from annando/getposts
[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\0Τ¶Y\ 5b\0\0¼cí߶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Autoload/ClassMapGenerator.php«\11\0\0Τ¶Y«\11\0\0\10ëÊ\9a\ 1\0\0\0\0\0\0\16\0\0\0src/Composer/Cache.phpt\13\0\0Τ¶Yt\13\0\0\0\11&#¶\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Command/AboutCommand.phpË\ 2\0\0Τ¶YË\ 2\0\0º¡Ãh¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/ArchiveCommand.phpL\14\0\0Τ¶YL\14\0\0\85\r;V¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/BaseCommand.phpÉ        \0\0Τ¶YÉ \0\0\97P!£¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Command/BaseDependencyCommand.phpÉ\18\0\0Τ¶YÉ\18\0\0D{²Ð¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Command/ClearCacheCommand.php]\ 5\0\0Τ¶Y]\ 5\0\0\1f\82ß´¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/ConfigCommand.php\aH\0\0Τ¶Y\aH\0\0\ fÃæ\ 5\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Command/CreateProjectCommand.phpì4\0\0Τ¶Yì4\0\0\13ô\18\8d\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/DependsCommand.php·\ 2\0\0Τ¶Y·\ 2\0\0o±¹ú¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/DiagnoseCommand.phpÍF\0\0Τ¶YÍF\0\0²E>F¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Command/DumpAutoloadCommand.php¨       \0\0Τ¶Y¨ \0\0g/\94\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/ExecCommand.phpi\a\0\0Τ¶Yi\a\0\0\ 4\80\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/GlobalCommand.phpü\a\0\0Τ¶Yü\a\0\0ÝH\8f\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/HomeCommand.php\1f\ e\0\0Τ¶Y\1f\ e\0\0\16±¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/InitCommand.phpT>\0\0Τ¶YT>\0\0\16\16Oø¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/InstallCommand.phpý\13\0\0Τ¶Yý\13\0\00ö:\89\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/LicensesCommand.php&\ e\0\0Τ¶Y&\ e\0\0Óv\83\1e\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/OutdatedCommand.php°
28 \0\0Τ¶Y°
29 \0\07àzk¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Command/ProhibitsCommand.phpË\ 2\0\0Τ¶YË\ 2\0\0\1ag\8fð¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/RemoveCommand.php\ 1\16\0\0Τ¶Y\ 1\16\0\0 O4\v\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Command/RequireCommand.php\9d\1f\0\0Τ¶Y\9d\1f\0\0BùÊǶ\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Command/RunScriptCommand.php \f\0\0Τ¶Y \f\0\0\ 3G\92\7f\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Command/ScriptAliasCommand.php\ 3\ 5\0\0Τ¶Y\ 3\ 5\0\0ÃJJü¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/SearchCommand.phpã\b\0\0Τ¶Yã\b\0\0ñ\v¼w¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Command/SelfUpdateCommand.phpï0\0\0Τ¶Yï0\0\0û­\ 3\f\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Command/ShowCommand.php\85d\0\0Τ¶Y\85d\0\0ó\87*é¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/StatusCommand.php/\15\0\0Τ¶Y/\15\0\0ôE\12\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/SuggestsCommand.php©\r\0\0Τ¶Y©\r\0\0\96º×U¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Command/UpdateCommand.php{"\0\0Τ¶Y{"\0\0e\8d­¸¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Command/ValidateCommand.php\18\14\0\0Τ¶Y\18\14\0\0lp\9c\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Composer.phpù  \0\0Τ¶Yù \0\0Á%\86\8b\ 1\0\0\0\0\0\0\17\0\0\0src/Composer/Config.phpÅ"\0\0Τ¶YÅ"\0\0\9d¡¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Config/ConfigSourceInterface.php\ e\ 2\0\0Τ¶Y\ e\ 2\0\0³\f[/¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Config/JsonConfigSource.php!\13\0\0Τ¶Y!\13\0\0¾S\r\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Console/Application.phpä2\0\0Τ¶Yä2\0\0 ª5=¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Console/HtmlOutputFormatter.php3\ 6\0\0Τ¶Y3\ 6\0\0Ú\81Eu¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/DependencyResolver/Decisions.phpQ\ f\0\0Τ¶YQ\ f\0\0?\98¬$¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/DefaultPolicy.php\ 2\17\0\0Τ¶Y\ 2\17\0\0õÝv\7f\ 1\0\0\0\0\0\0/\0\0\0src/Composer/DependencyResolver/GenericRule.php·\ 3\0\0Τ¶Y·\ 3\0\0Ì~¯³¶\ 1\0\0\0\0\0\0>\0\0\0src/Composer/DependencyResolver/Operation/InstallOperation.phpC\ 2\0\0Τ¶YC\ 2\0\0´\õ*¶\ 1\0\0\0\0\0\0I\0\0\0src/Composer/DependencyResolver/Operation/MarkAliasInstalledOperation.php÷\ 2\0\0Τ¶Y÷\ 2\0\0ïÎà÷¶\ 1\0\0\0\0\0\0K\0\0\0src/Composer/DependencyResolver/Operation/MarkAliasUninstalledOperation.phpý\ 2\0\0Τ¶Yý\ 2\0\0\193#\86\ 1\0\0\0\0\0\0@\0\0\0src/Composer/DependencyResolver/Operation/OperationInterface.phpÓ\0\0\0Τ¶YÓ\0\0\0Ùâ&ä¶\ 1\0\0\0\0\0\0=\0\0\0src/Composer/DependencyResolver/Operation/SolverOperation.php¹\ 1\0\0Τ¶Y¹\ 1\0\0&¢e
30\ 1\0\0\0\0\0\0@\0\0\0src/Composer/DependencyResolver/Operation/UninstallOperation.phpI\ 2\0\0Τ¶YI\ 2\0\0FûÂɶ\ 1\0\0\0\0\0\0=\0\0\0src/Composer/DependencyResolver/Operation/UpdateOperation.phph\ 3\0\0Τ¶Yh\ 3\0\0öSÕ]¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/DependencyResolver/PolicyInterface.php­\ 1\0\0Τ¶Y­\ 1\0\0\18\9f\8b\ 1\0\0\0\0\0\0(\0\0\0src/Composer/DependencyResolver/Pool.php°"\0\0Τ¶Y°"\0\0\1d   \8e\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/Problem.php\99\16\0\0Τ¶Y\99\16\0\0\ 3´\87Ķ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/Request.php\83\ 4\0\0Τ¶Y\83\ 4\0\0åVP\84\ 1\0\0\0\0\0\0(\0\0\0src/Composer/DependencyResolver/Rule.php¶\18\0\0Τ¶Y¶\18\0\0Ú{\8d\8d\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/Rule2Literals.php§\ 4\0\0Τ¶Y§\ 4\0\0~Ð'ò¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/DependencyResolver/RuleSet.phpª
31 \0\0Τ¶Yª
32 \0\0\82\e\ 1\0\0\0\0\0\04\0\0\0src/Composer/DependencyResolver/RuleSetGenerator.phpO\e\0\0Τ¶YO\e\0\0³Q[â¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/DependencyResolver/RuleSetIterator.php\14\ 6\0\0Τ¶Y\14\ 6\0\0}õÇù¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/DependencyResolver/RuleWatchChain.phpi\ 1\0\0Τ¶Yi\ 1\0\0\9a\ 1\0\0\0\0\0\02\0\0\0src/Composer/DependencyResolver/RuleWatchGraph.phpá\ 6\0\0Τ¶Yá\ 6\0\0\89rôv¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/DependencyResolver/RuleWatchNode.phpñ\ 3\0\0Τ¶Yñ\ 3\0\0ë\95\e\93\ 1\0\0\0\0\0\0*\0\0\0src/Composer/DependencyResolver/Solver.php\9f8\0\0Τ¶Y\9f8\0\0\1epöb¶\ 1\0\0\0\0\0\06\0\0\0src/Composer/DependencyResolver/SolverBugException.php\98\ 1\0\0Τ¶Y\98\ 1\0\0\7f"qN¶\ 1\0\0\0\0\0\0;\0\0\0src/Composer/DependencyResolver/SolverProblemsException.php¤\a\0\0Τ¶Y¤\a\0\0Ä\1d~\a\ 1\0\0\0\0\0\0/\0\0\0src/Composer/DependencyResolver/Transaction.phpô\13\0\0Τ¶Yô\13\0\0cïTܶ\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Downloader/ArchiveDownloader.php¸\ e\0\0Τ¶Y¸\ e\0\0±°Y\b\ 1\0\0\0\0\0\01\0\0\0src/Composer/Downloader/ChangeReportInterface.phpÌ\0\0\0Τ¶YÌ\0\0\0¯à¨¿¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Downloader/DownloadManager.phpG\15\0\0Τ¶YG\15\0\0\8a(í»¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Downloader/DownloaderInterface.phpÊ\ 1\0\0Τ¶YÊ\ 1\0\0gs!l¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Downloader/DvcsDownloaderInterface.phpÑ\0\0\0Τ¶YÑ\0\0\0\9c¿¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/FileDownloader.phpì\17\0\0Τ¶Yì\17\0\04\1eø\ 1\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Downloader/FilesystemException.php
33 \ 1\0\0Τ¶Y
34 \ 1\0\0.-\1e\8b\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Downloader/FossilDownloader.php`\v\0\0Τ¶Y`\v\0\0ÿI©u¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/GitDownloader.php\9d3\0\0Τ¶Y\9d3\0\01mU¥¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/GzipDownloader.phpó\ 6\0\0Τ¶Yó\ 6\0\0}Úo¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Downloader/HgDownloader.php8 \0\0Τ¶Y8 \0\0ëyàn¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/PathDownloader.phpK\11\0\0Τ¶YK\11\0\09\95&c¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/Downloader/PearPackageExtractor.phpu\e\0\0Τ¶Yu\e\0\0z\84\15\87\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Downloader/PerforceDownloader.phpÃ\a\0\0Τ¶YÃ\a\0\0\1c\91Èý¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Downloader/PharDownloader.phpå\0\0\0Τ¶Yå\0\0\0ÞÉ\1fç¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/RarDownloader.php\9e\a\0\0Τ¶Y\9e\a\0\06      3U¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/SvnDownloader.phpG\11\0\0Τ¶YG\11\0\0\86íV\96\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/TarDownloader.phpã\0\0\0Τ¶Yã\0\0\0Í\92X?¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Downloader/TransportException.php=\ 2\0\0Τ¶Y=\ 2\0\0ZÎÈÞ¶\ 1\0\0\0\0\0\09\0\0\0src/Composer/Downloader/VcsCapableDownloaderInterface.phpÔ\0\0\0Τ¶YÔ\0\0\0`§ôö¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/VcsDownloader.php"\16\0\0Τ¶Y"\16\0\0\9c\1a\9f\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Downloader/XzDownloader.php§\ 4\0\0Τ¶Y§\ 4\0\0W$;á¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Downloader/ZipDownloader.php\98\13\0\0Τ¶Y\98\13\0\0\9b@\ 2ü¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/EventDispatcher/Event.php \ 2\0\0Τ¶Y \ 2\0\0±\99jï¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/EventDispatcher/EventDispatcher.phpß0\0\0Τ¶Yß0\0\0}f\18\a\ 1\0\0\0\0\0\09\0\0\0src/Composer/EventDispatcher/EventSubscriberInterface.php©\0\0\0Τ¶Y©\0\0\0\ 1\ 1\0\0\0\0\0\09\0\0\0src/Composer/EventDispatcher/ScriptExecutionException.phpv\0\0\0Τ¶Yv\0\0\0wZ8S¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Exception/NoSslException.phpf\0\0\0Τ¶Yf\0\0\0ËíM\9d\ 1\0\0\0\0\0\0\18\0\0\0src/Composer/Factory.phpS=\0\0Τ¶YS=\0\0Fíж\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/IO/BaseIO.php\8c\10\0\0Τ¶Y\8c\10\0\0(\82l\91\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/IO/BufferIO.php*\ 4\0\0Τ¶Y*\ 4\0\0¢®hT¶\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/IO/ConsoleIO.php;\15\0\0Τ¶Y;\15\0\0Ê\17\9b\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/IO/IOInterface.phpì\ 5\0\0Τ¶Yì\ 5\0\0\0Õ\9d\ e\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/IO/NullIO.phpÀ\ 4\0\0Τ¶YÀ\ 4\0\0F`sʶ\ 1\0\0\0\0\0\0\1a\0\0\0src/Composer/Installer.php}\9a\0\0Τ¶Y}\9a\0\08P÷ý¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/BinaryInstaller.php\10\13\0\0Τ¶Y\10\13\0\0\8dv÷j¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Installer/BinaryPresenceInterface.phpË\0\0\0Τ¶YË\0\0\0À5\9a¨¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Installer/InstallationManager.php-\17\0\0Τ¶Y-\17\0\0¾}\8c\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Installer/InstallerEvent.php\ e\ 6\0\0Τ¶Y\ e\ 6\0\0lÔzi¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/InstallerEvents.phpÞ\0\0\0Τ¶YÞ\0\0\0ì\9f@G¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Installer/InstallerInterface.phpã\ 2\0\0Τ¶Yã\ 2\0\0^\83\93ʶ\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Installer/LibraryInstaller.php^\13\0\0Τ¶Y^\13\0\0\10\1aÍr¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Installer/MetapackageInstaller.php\9c\ 4\0\0Τ¶Y\9c\ 4\0\0Æ\12Å!¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/NoopInstaller.php+\ 5\0\0Τ¶Y+\ 5\0\0À·M}¶\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Installer/PackageEvent.phpe\ 3\0\0Τ¶Ye\ 3\0\0;° \1a\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/PackageEvents.php¸\ 1\0\0Τ¶Y¸\ 1\0\0dbØs¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Installer/PearBinaryInstaller.phpâ\f\0\0Τ¶Yâ\f\0\0;øiU¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Installer/PearInstaller.php¢\a\0\0Τ¶Y¢\a\0\0È\82¶Ñ¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Installer/PluginInstaller.php\9f\ 6\0\0Τ¶Y\9f\ 6\0\0<tú,¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Installer/ProjectInstaller.php\1d\ 6\0\0Τ¶Y\1d\ 6\0\0*0@P¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Installer/SuggestedPackagesReporter.php\10\a\0\0Τ¶Y\10\a\0\0+±]Ķ\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Json/JsonFile.php\ 3\14\0\0Τ¶Y\ 3\14\0\0VVN\15\ 1\0\0\0\0\0\0#\0\0\0src/Composer/Json/JsonFormatter.php\ 6\ 6\0\0Τ¶Y\ 6\ 6\0\0\1eÐqu¶\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Json/JsonManipulator.php¥2\0\0Τ¶Y¥2\0\0\96\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Json/JsonValidationException.php\\ 1\0\0Τ¶Y\\ 1\0\0.Xóܶ\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Package/AliasPackage.php\ 5\17\0\0Τ¶Y\ 5\17\0\0¹\97~\9a\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ArchivableFilesFilter.php       \ 2\0\0Τ¶Y \ 2\0\0yY+¦¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ArchivableFilesFinder.phpÞ\ 5\0\0Τ¶YÞ\ 5\0\0\f²²¹¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/Package/Archiver/ArchiveManager.php°\f\0\0Τ¶Y°\f\0\0gþÒ)¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Package/Archiver/ArchiverInterface.php\a\ 1\0\0Τ¶Y\a\ 1\0\0ñ´>\v\ 1\0\0\0\0\0\03\0\0\0src/Composer/Package/Archiver/BaseExcludeFilter.php\96\ 6\0\0Τ¶Y\96\ 6\0\0y¶=ƶ\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Archiver/ComposerExcludeFilter.php\1f\ 1\0\0Τ¶Y\1f\ 1\0\0\8bSZ0¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Package/Archiver/GitExcludeFilter.phpq\ 3\0\0Τ¶Yq\ 3\0\05¾i&¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/Archiver/HgExcludeFilter.php\13\ 5\0\0Τ¶Y\13\ 5\0\0~\94\ e¸¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Package/Archiver/PharArchiver.php>\ 6\0\0Τ¶Y>\ 6\0\0 5\89í¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Package/Archiver/ZipArchiver.php¼\ 4\0\0Τ¶Y¼\ 4\0\0\91XÝë¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Package/BasePackage.php&\r\0\0Τ¶Y&\r\0\0\e'\1fݶ\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Package/CompletePackage.phpü\ 6\0\0Τ¶Yü\ 6\0\0þM˶¶\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/CompletePackageInterface.phpõ\ 1\0\0Τ¶Yõ\ 1\0\0¦Ê\81ò¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Package/Dumper/ArrayDumper.phpë\v\0\0Τ¶Yë\v\0\0Ó8WE¶\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/Package/Link.php\88\ 5\0\0Τ¶Y\88\ 5\0\0å¶Y«¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/LinkConstraint/EmptyConstraint.php\82\ 1\0\0Τ¶Y\82\ 1\0\0\ eé~\8b\ 1\0\0\0\0\0\0?\0\0\0src/Composer/Package/LinkConstraint/LinkConstraintInterface.phpd\ 1\0\0Τ¶Yd\ 1\0\0¤ôLn¶\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/LinkConstraint/MultiConstraint.php\82\ 1\0\0Τ¶Y\82\ 1\0\0ób`ý¶\ 1\0\0\0\0\0\0:\0\0\0src/Composer/Package/LinkConstraint/SpecificConstraint.phpi\ 1\0\0Τ¶Yi\ 1\0\0Þ\94\9a\ 1\0\0\0\0\0\09\0\0\0src/Composer/Package/LinkConstraint/VersionConstraint.phpX\ 1\0\0Τ¶YX\ 1\0\0\ 2}`y¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Package/Loader/ArrayLoader.php¸\1e\0\0Τ¶Y¸\1e\0\06\r¤\1d\ 1\0\0\0\0\0\07\0\0\0src/Composer/Package/Loader/InvalidPackageException.phpE\ 2\0\0Τ¶YE\ 2\0\0xb\13¾¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Package/Loader/JsonLoader.phpù\ 1\0\0Τ¶Yù\ 1\0\0!~\88\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Package/Loader/LoaderInterface.php²\0\0\0Τ¶Y²\0\0\0¦}úζ\ 1\0\0\0\0\0\01\0\0\0src/Composer/Package/Loader/RootPackageLoader.php½\16\0\0Τ¶Y½\16\0\0\8d\ 1\0\0\0\0\0\05\0\0\0src/Composer/Package/Loader/ValidatingArrayLoader.phpõ2\0\0Τ¶Yõ2\0\0ÞEY7¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Package/Locker.php©!\0\0Τ¶Y©!\0\0A\8aõë¶\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Package/Package.phpÉ\1a\0\0Τ¶YÉ\1a\0\0\8f\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Package/PackageInterface.php \a\0\0Τ¶Y \a\0\0ûÇ^ƶ\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Package/RootAliasPackage.php\1f   \0\0Τ¶Y\1f \0\0      _\80ø¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Package/RootPackage.php\11\ 5\0\0Τ¶Y\11\ 5\0\0\ 2\8eÎ_¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Package/RootPackageInterface.php¹\ 3\0\0Τ¶Y¹\ 3\0\0"maV¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Package/Version/VersionGuesser.phpÊ\1c\0\0Τ¶YÊ\1c\0\0É{\13¯¶\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Package/Version/VersionParser.phpø\ 3\0\0Τ¶Yø\ 3\0\0\1e¾3l¶\ 1\0\0\0\0\0\00\0\0\0src/Composer/Package/Version/VersionSelector.phpK\f\0\0Τ¶YK\f\0\0²<\ fȶ\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Plugin/Capability/Capability.phpW\0\0\0Τ¶YW\0\0\0æ_¨1¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Plugin/Capability/CommandProvider.php\97\0\0\0Τ¶Y\97\0\0\0ûOâ>¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Plugin/Capable.php\7f\0\0\0Τ¶Y\7f\0\0\0Æq\15\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Plugin/CommandEvent.phpâ\ 2\0\0Τ¶Yâ\ 2\0\0³ÆÇW¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Plugin/PluginEvents.phpÂ\0\0\0Τ¶YÂ\0\0\0^Íþ\ 6\ 1\0\0\0\0\0\0'\0\0\0src/Composer/Plugin/PluginInterface.phpô\0\0\0Τ¶Yô\0\0\0)'*ض\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Plugin/PluginManager.php\1f$\0\0Τ¶Y\1f$\0\0ë\8e"»¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Plugin/PreFileDownloadEvent.php`\ 2\0\0Τ¶Y`\ 2\0\0\09-ζ\ 1\0\0\0\0\0\04\0\0\0src/Composer/Question/StrictConfirmationQuestion.php\1e\ 5\0\0Τ¶Y\1e\ 5\0\0'.³è¶\ 1\0\0\0\0\0\0+\0\0\0src/Composer/Repository/ArrayRepository.php\13\ e\0\0Τ¶Y\13\ e\0\0éÌt\0\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/ArtifactRepository.php»\f\0\0Τ¶Y»\f\0\0\88Ý÷<¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/BaseRepository.php_\r\0\0Τ¶Y_\r\0\0\96ûß\ e\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/ComposerRepository.php\T\0\0Τ¶Y\T\0\0+\8a;ê¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/CompositeRepository.php;\b\0\0Τ¶Y;\b\0\0¤¯S\1f\ 1\0\0\0\0\0\0;\0\0\0src/Composer/Repository/ConfigurableRepositoryInterface.php\85\0\0\0Τ¶Y\85\0\0\0±\9f_\1c\ 1\0\0\0\0\0\00\0\0\0src/Composer/Repository/FilesystemRepository.php×\ 4\0\0Τ¶Y×\ 4\0\0I\9cª\13\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/InstalledArrayRepository.php£\0\0\0Τ¶Y£\0\0\0/ö~>¶\ 1\0\0\0\0\0\09\0\0\0src/Composer/Repository/InstalledFilesystemRepository.php£\0\0\0Τ¶Y£\0\0\0V
35 \95\ 1\0\0\0\0\0\08\0\0\0src/Composer/Repository/InstalledRepositoryInterface.php\87\0\0\0Τ¶Y\87\0\0\0\18£9p¶\ 1\0\0\0\0\0\06\0\0\0src/Composer/Repository/InvalidRepositoryException.phpn\0\0\0Τ¶Yn\0\0\0à\93ë\98\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/PackageRepository.phpj\ 3\0\0Τ¶Yj\ 3\0\0¥ôò̶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/PathRepository.phpw
36 \0\0Τ¶Yw
37 \0\0\0~õ³¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Pear/BaseChannelReader.phpI\ 5\0\0Τ¶YI\ 5\0\0c\b6³¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/ChannelInfo.phpÄ\ 1\0\0Τ¶YÄ\ 1\0\0:T*ɶ\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/Pear/ChannelReader.phpí\ 6\0\0Τ¶Yí\ 6\0\0?ÈYT¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/Pear/ChannelRest10Reader.phpÁ \0\0Τ¶YÁ \0\0\ 4O\80ë¶\ 1\0\0\0\0\0\04\0\0\0src/Composer/Repository/Pear/ChannelRest11Reader.php& \0\0Τ¶Y& \0\0òUb\b\ 1\0\0\0\0\0\05\0\0\0src/Composer/Repository/Pear/DependencyConstraint.phpq\ 2\0\0Τ¶Yq\ 2\0\09\ e\17\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/Pear/DependencyInfo.phpq\ 1\0\0Τ¶Yq\ 1\0\0fºTò¶\ 1\0\0\0\0\0\08\0\0\0src/Composer/Repository/Pear/PackageDependencyParser.php\85\16\0\0Τ¶Y\85\16\0\0÷$Li¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/PackageInfo.php°\ 3\0\0Τ¶Y°\ 3\0\0\9f\r¸\f\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Pear/ReleaseInfo.php\92\ 1\0\0Τ¶Y\92\ 1\0\0o\93\8aö\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Repository/PearRepository.phpª\16\0\0Τ¶Yª\16\0\0)\9f\83\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/PlatformRepository.php\ 1\e\0\0Τ¶Y\ 1\e\0\0\ 3_Mì¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/RepositoryFactory.php\95\11\0\0Τ¶Y\95\11\0\0\80\83§\1d\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/RepositoryInterface.phpÛ\ 1\0\0Τ¶YÛ\ 1\0\0\92\11âÁ¶\ 1\0\0\0\0\0\0-\0\0\0src/Composer/Repository/RepositoryManager.php,
38 \0\0Τ¶Y,
39 \0\0¾\85\\95\ 1\0\0\0\0\0\07\0\0\0src/Composer/Repository/RepositorySecurityException.phpo\0\0\0Τ¶Yo\0\0\0pÕ«ª¶\ 1\0\0\0\0\0\0/\0\0\0src/Composer/Repository/Vcs/BitbucketDriver.phpô\1e\0\0Τ¶Yô\1e\0\0\ 4x¤ü¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/FossilDriver.php \12\0\0Τ¶Y \12\0\0]\8bÉQ¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Vcs/GitBitbucketDriver.phpê\ 5\0\0Τ¶Yê\ 5\0\0Ã\8e»\14\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/GitDriver.phpØ\11\0\0Τ¶YØ\11\0\0Ý"T̶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/GitHubDriver.phpz+\0\0Τ¶Yz+\0\0\13\1fÚb¶\ 1\0\0\0\0\0\0,\0\0\0src/Composer/Repository/Vcs/GitLabDriver.php\93"\0\0Τ¶Y\93"\0\0*\97\9c\ 1\0\0\0\0\0\01\0\0\0src/Composer/Repository/Vcs/HgBitbucketDriver.phpä\ 5\0\0Τ¶Yä\ 5\0\0i\9büà¶\ 1\0\0\0\0\0\0(\0\0\0src/Composer/Repository/Vcs/HgDriver.phpe\12\0\0Τ¶Ye\12\0\0O!O\13\ 1\0\0\0\0\0\0.\0\0\0src/Composer/Repository/Vcs/PerforceDriver.phpO     \0\0Τ¶YO \0\0@ËóN¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/SvnDriver.php\15\e\0\0Τ¶Y\15\e\0\0\1dÕzï¶\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/Vcs/VcsDriver.phpæ
40 \0\0Τ¶Yæ
41 \0\0eׯ-¶\ 1\0\0\0\0\0\02\0\0\0src/Composer/Repository/Vcs/VcsDriverInterface.php÷\ 2\0\0Τ¶Y÷\ 2\0\0ÇX[\89\ 1\0\0\0\0\0\0)\0\0\0src/Composer/Repository/VcsRepository.php´\1e\0\0Τ¶Y´\1e\0\0\ 1ªÖG¶\ 1\0\0\0\0\0\03\0\0\0src/Composer/Repository/WritableArrayRepository.php\ f\ 3\0\0Τ¶Y\ f\ 3\0\0¾G\17\ 1\0\0\0\0\0\07\0\0\0src/Composer/Repository/WritableRepositoryInterface.php\89\ 1\0\0Τ¶Y\89\ 1\0\0\91/sï¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/CommandEvent.phpW\0\0\0Τ¶YW\0\0\0£VZt¶\ 1\0\0\0\0\0\0\1d\0\0\0src/Composer/Script/Event.phpµ\ 2\0\0Τ¶Yµ\ 2\0\0lt¦M¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/PackageEvent.php\9c\0\0\0Τ¶Y\9c\0\0\0§ÿÉ\r\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Script/ScriptEvents.phpP\ 4\0\0Τ¶YP\ 4\0\0\87\8f\ 4¶¶\ 1\0\0\0\0\0\0 \0\0\0src/Composer/SelfUpdate/Keys.php\9d\ 1\0\0Τ¶Y\9d\ 1\0\0\vîÊN¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/SelfUpdate/Versions.phpì\ 5\0\0Τ¶Yì\ 5\0\0͵\91\83\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Util/AuthHelper.phpË\ 3\0\0Τ¶YË\ 3\0\0>zx\96\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/Bitbucket.php%\15\0\0Τ¶Y%\15\0\0n=gÓ¶\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Util/ComposerMirror.php±\ 4\0\0Τ¶Y±\ 4\0\0­½øض\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Util/ConfigValidator.phpu\12\0\0Τ¶Yu\12\0\0m\ 5áض\ 1\0\0\0\0\0\0"\0\0\0src/Composer/Util/ErrorHandler.php\87\ 4\0\0Τ¶Y\87\ 4\0\0He\1c\ 1\0\0\0\0\0\0 \0\0\0src/Composer/Util/Filesystem.phps.\0\0Τ¶Ys.\0\0\9bÍ®à¶\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Git.phpn$\0\0Τ¶Yn$\0\05XÇ\ e\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/Util/GitHub.phpÏ
42 \0\0Τ¶YÏ
43 \0\0ÁØ\å¶\ 1\0\0\0\0\0\0\1c\0\0\0src/Composer/Util/GitLab.php\99\f\0\0Τ¶Y\99\f\0\0\17BLF¶\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/IniHelper.php\9d\ 2\0\0Τ¶Y\9d\ 2\0\0Çþ\82\ 1\0\0\0\0\0\0$\0\0\0src/Composer/Util/NoProxyPattern.php¾\ 6\0\0Τ¶Y¾\ 6\0\0Z+°m¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Perforce.php\1e2\0\0Τ¶Y\1e2\0\0­\ 65P¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Platform.phpü\ 4\0\0Τ¶Yü\ 4\0\0s­fç¶\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Util/ProcessExecutor.php\f\b\0\0Τ¶Y\f\b\0\0\88)sw¶\ 1\0\0\0\0\0\0&\0\0\0src/Composer/Util/RemoteFilesystem.php¥d\0\0Τ¶Y¥d\0\0,C}p¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/Util/Silencer.phpò\ 2\0\0Τ¶Yò\ 2\0\0.\8e\7fܶ\ 1\0\0\0\0\0\0!\0\0\0src/Composer/Util/SpdxLicense.php\ 3\ 1\0\0Τ¶Y\ 3\ 1\0\0¾7
44 ñ¶\ 1\0\0\0\0\0\0*\0\0\0src/Composer/Util/StreamContextFactory.phpÍ\ f\0\0Τ¶YÍ\ f\0\0\8bK:8¶\ 1\0\0\0\0\0\0\19\0\0\0src/Composer/Util/Svn.php¾\11\0\0Τ¶Y¾\11\0\0Ík\93ܶ\ 1\0\0\0\0\0\0\1f\0\0\0src/Composer/Util/TlsHelper.phpp
45 \0\0Τ¶Yp
46 \0\0¤eÞæ¶\ 1\0\0\0\0\0\0\1e\0\0\0src/Composer/XdebugHandler.php\93\ f\0\0Τ¶Y\93\ f\0\0\1cF·­¶\ 1\0\0\0\0\0\0\11\0\0\0src/bootstrap.php¹\ 1\0\0Τ¶Y¹\ 1\0\0\15I}\9c\ 1\0\0\0\0\0\0%\0\0\0src/Composer/Autoload/ClassLoader.php\8b4\0\0Τ¶Y\8b4\0\0Q\9f\94¼¶\ 1\0\0\0\0\0\0#\0\0\0res/composer-repository-schema.jsonð\ f\0\0Τ¶Yð\ f\0\0\81GÐà¶\ 1\0\0\0\0\0\0\18\0\0\0res/composer-schema.json_\93\0\0Τ¶Y_\93\0\0¤H\10õ¶\ 1\0\0\0\0\0\06\0\0\0vendor/composer/spdx-licenses/res/spdx-exceptions.jsoní\ 6\0\0Τ¶Yí\ 6\0\0ÆÅz±¶\ 1\0\0\0\0\0\04\0\0\0vendor/composer/spdx-licenses/res/spdx-licenses.jsonïf\0\0Τ¶Yïf\0\0"ï@\96\ 1\0\0\0\0\0\0*\0\0\0vendor/seld/cli-prompt/res/hiddeninput.exe\0$\0\0Τ¶Y\0$\0\0\95\8d¥v¶\ 1\0\0\0\0\0\0&\0\0\0vendor/symfony/console/Application.php¥V\0\0Τ¶Y¥V\0\0\15«8\88\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/console/Command/Command.php
47 #\0\0Τ¶Y
48 #\0\0\13¢\11Á¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Command/HelpCommand.phpÝ\a\0\0Τ¶YÝ\a\0\0\99\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Command/ListCommand.phpZ\b\0\0Τ¶YZ\b\0\0É£ \16\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/ConsoleEvents.phpï\0\0\0Τ¶Yï\0\0\0\rÕH¸¶\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/console/Descriptor/ApplicationDescription.phpß\b\0\0Τ¶Yß\b\0\0µ\8c°7¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Descriptor/Descriptor.php\9d\a\0\0Τ¶Y\9d\a\0\0\b;~Ķ\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/console/Descriptor/DescriptorInterface.phpü\0\0\0Τ¶Yü\0\0\0±Q\aµ¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Descriptor/JsonDescriptor.phpì\r\0\0Τ¶Yì\r\0\0á8-\8c\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Descriptor/MarkdownDescriptor.php¹\ e\0\0Τ¶Y¹\ e\0\0k\9f.a¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Descriptor/TextDescriptor.php\93\1e\0\0Τ¶Y\93\1e\0\0»]Ïø¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Descriptor/XmlDescriptor.php\ f\1c\0\0Τ¶Y\ f\1c\0\0\ 4\8bP$¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Event/ConsoleCommandEvent.php²\ 1\0\0Τ¶Y²\ 1\0\0Zk\89\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Event/ConsoleEvent.phpÅ\ 2\0\0Τ¶YÅ\ 2\0\0ÒxÛ\¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Event/ConsoleExceptionEvent.php\12\ 3\0\0Τ¶Y\12\ 3\0\0á\162é¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Event/ConsoleTerminateEvent.phpz\ 2\0\0Τ¶Yz\ 2\0\0³,îL¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Exception/CommandNotFoundException.phpÔ\ 1\0\0Τ¶YÔ\ 1\0\0È÷ L¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/console/Exception/ExceptionInterface.phpf\0\0\0Τ¶Yf\0\0\0¡ABª¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Exception/InvalidArgumentException.php¦\0\0\0Τ¶Y¦\0\0\0Ö̽Z¶\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/console/Exception/InvalidOptionException.php¦\0\0\0Τ¶Y¦\0\0\0\13Ë×H¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Exception/LogicException.php\92\0\0\0Τ¶Y\92\0\0\0ÍO\e¶\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/console/Exception/RuntimeException.php\96\0\0\0Τ¶Y\96\0\0\0Ùí,6¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Formatter/OutputFormatter.php\f\ e\0\0Τ¶Y\f\ e\0\0\83á&B¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/console/Formatter/OutputFormatterInterface.php\8c\ 1\0\0Τ¶Y\8c\ 1\0\0òññÀ¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyle.phpL\10\0\0Τ¶YL\10\0\0\8a\908<¶\ 1\0\0\0\0\0\0B\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyleInterface.php\86\ 1\0\0Τ¶Y\86\ 1\0\0ÝRÚ­¶\ 1\0\0\0\0\0\0>\0\0\0vendor/symfony/console/Formatter/OutputFormatterStyleStack.phpL\ 5\0\0Τ¶YL\ 5\0\0.=\16\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/console/Helper/DebugFormatterHelper.phpx\b\0\0Τ¶Yx\b\0\0N©Ø¼¶\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Helper/DescriptorHelper.phpz\ 5\0\0Τ¶Yz\ 5\0\0fÉÚý¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Helper/DialogHelper.phpú\1e\0\0Τ¶Yú\1e\0\0hX\8fö\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Helper/FormatterHelper.phpc\ 4\0\0Τ¶Yc\ 4\0\0\93ý«N¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/Helper/Helper.php¬\a\0\0Τ¶Y¬\a\0\0OÜs¢¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Helper/HelperInterface.phpç\0\0\0Τ¶Yç\0\0\0 \18Çã¶\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Helper/HelperSet.phpÐ\a\0\0Τ¶YÐ\a\0\0a\88~\r\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Helper/InputAwareHelper.phpc\ 1\0\0Τ¶Yc\ 1\0\0ñø\90\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Helper/ProcessHelper.phpÑ     \0\0Τ¶YÑ \0\0@±ã\81\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Helper/ProgressBar.phps%\0\0Τ¶Ys%\0\0鯦\81\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/ProgressHelper.php\\e\0\0Τ¶Y\\e\0\0\12?\8bá¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Helper/ProgressIndicator.phpK\14\0\0Τ¶YK\14\0\0í\1cÍ°¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/QuestionHelper.php\7f\e\0\0Τ¶Y\7f\e\0\0a4Íý¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/console/Helper/SymfonyQuestionHelper.phpl
49 \0\0Τ¶Yl
50 \0\0\1e÷ÞL¶\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/console/Helper/Table.php¢*\0\0Τ¶Y¢*\0\0\0\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Helper/TableCell.php\87\ 3\0\0Τ¶Y\87\ 3\0\0¨*æ\18\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Helper/TableHelper.php\13\f\0\0Τ¶Y\13\f\0\0¦pm\87\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Helper/TableSeparator.phpÍ\0\0\0Τ¶YÍ\0\0\0Qßa²¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Helper/TableStyle.php\1f
51 \0\0Τ¶Y\1f
52 \0\0PÞµ¦¶\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/console/Input/ArgvInput.php\14\15\0\0Τ¶Y\14\15\0\0¯Ü\10\9c\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/console/Input/ArrayInput.php_
53 \0\0Τ¶Y_
54 \0\0[µðɶ\ 1\0\0\0\0\0\0&\0\0\0vendor/symfony/console/Input/Input.phpª\v\0\0Τ¶Yª\v\0\0\ 3\1a\1f¶¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Input/InputArgument.php\12\ 6\0\0Τ¶Y\12\ 6\0\0ÁÜ\17\90\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/console/Input/InputAwareInterface.php\9a\0\0\0Τ¶Y\9a\0\0\0\87jT\9f\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Input/InputDefinition.php\96\19\0\0Τ¶Y\96\19\0\00Oly¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Input/InputInterface.php\9f\ 3\0\0Τ¶Y\9f\ 3\0\0¥R6Û¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Input/InputOption.php\1c\f\0\0Τ¶Y\1c\f\0\0\87¹§\7f\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Input/StringInput.php\98\ 6\0\0Τ¶Y\98\ 6\0\0 \1dÚ¤¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/console/LICENSE)\ 4\0\0Τ¶Y)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Logger/ConsoleLogger.php< \0\0Τ¶Y< \0\0:âÇl¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/console/Output/BufferedOutput.phpb\ 1\0\0Τ¶Yb\ 1\0\0çA?¦¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Output/ConsoleOutput.phpµ\a\0\0Τ¶Yµ\a\0\0
55 ¢S\¶\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Output/ConsoleOutputInterface.phpå\0\0\0Τ¶Yå\0\0\0rNô\0\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Output/NullOutput.phpÏ\ 3\0\0Τ¶YÏ\ 3\0\0®\98\8b\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/console/Output/Output.php\9a    \0\0Τ¶Y\9a \0\001 ý¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/console/Output/OutputInterface.php\1c\ 3\0\0Τ¶Y\1c\ 3\0\0\1aÓÚ>¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/console/Output/StreamOutput.phpÄ\ 5\0\0Τ¶YÄ\ 5\0\0õ\1aí\95\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/console/Question/ChoiceQuestion.phpy
56 \0\0Τ¶Yy
57 \0\0.\ f\Q¶\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/console/Question/ConfirmationQuestion.phpé\ 2\0\0Τ¶Yé\ 2\0\0\83\17Q@¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Question/Question.php#
58 \0\0Τ¶Y#
59 \0\0e¯ \ e\ 1\0\0\0\0\0\0 \0\0\0vendor/symfony/console/Shell.phpé\ f\0\0Τ¶Yé\ f\0\0½fü\91\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/console/Style/OutputStyle.php_\ 5\0\0Τ¶Y_\ 5\0\0\ 4û\ 5µ¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Style/StyleInterface.phpÔ\ 3\0\0Τ¶YÔ\ 3\0\0 ßÊj¶\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/console/Style/SymfonyStyle.php¼\1f\0\0Τ¶Y¼\1f\0\0öÅPg¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/console/Tester/ApplicationTester.phpÔ\ 5\0\0Τ¶YÔ\ 5\0\0¬ì¤d¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/console/Tester/CommandTester.php¯\ 6\0\0Τ¶Y¯\ 6\0\0{8"÷¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/debug/BufferingLogger.phpt\ 1\0\0Τ¶Yt\ 1\0\0=\0hܶ\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/debug/Debug.phpé\ 2\0\0Τ¶Yé\ 2\0\0Àxa?¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/debug/DebugClassLoader.phpï\1d\0\0Τ¶Yï\1d\0\0ß<§ê¶\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/debug/ErrorHandler.php\80C\0\0Τ¶Y\80C\0\0¥æõ¾¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/debug/Exception/ClassNotFoundException.php\84\ 1\0\0Τ¶Y\84\ 1\0\0n\90¡\85\ 1\0\0\0\0\0\08\0\0\0vendor/symfony/debug/Exception/ContextErrorException.php\98\ 1\0\0Τ¶Y\98\ 1\0\0-
60 d2¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/debug/Exception/DummyException.php\ 2\ 1\0\0Τ¶Y\ 2\ 1\0\0-"ûd¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/debug/Exception/FatalErrorException.phpï\ 6\0\0Τ¶Yï\ 6\0\0æ\ffz¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/debug/Exception/FatalThrowableError.phpD\ 2\0\0Τ¶YD\ 2\0\0¡\fÂí¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/debug/Exception/FlattenException.php²\16\0\0Τ¶Y²\16\0\0HòÑ\ f\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/debug/Exception/OutOfMemoryException.php~\0\0\0Τ¶Y~\0\0\0ë¨oâ¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/debug/Exception/UndefinedFunctionException.php\88\ 1\0\0Τ¶Y\88\ 1\0\0¢G\82\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/debug/Exception/UndefinedMethodException.php\86\ 1\0\0Τ¶Y\86\ 1\0\0¨LÚ:¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/debug/ExceptionHandler.php\1f3\0\0Τ¶Y\1f3\0\0%\E\17\ 1\0\0\0\0\0\0I\0\0\0vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php7\12\0\0Τ¶Y7\12\0\0Ñj/=¶\ 1\0\0\0\0\0\0E\0\0\0vendor/symfony/debug/FatalErrorHandler/FatalErrorHandlerInterface.php\ 3\ 1\0\0Τ¶Y\ 3\ 1\0\0ĹBV¶\ 1\0\0\0\0\0\0M\0\0\0vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.phpu\b\0\0Τ¶Yu\b\0\0éj\ 3\19\ 1\0\0\0\0\0\0K\0\0\0vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.phpN\ 5\0\0Τ¶YN\ 5\0\0Ço-ç¶\ 1\0\0\0\0\0\0\1c\0\0\0vendor/symfony/debug/LICENSE)\ 4\0\0Τ¶Y)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/filesystem/Exception/ExceptionInterface.phpi\0\0\0Τ¶Yi\0\0\0$ ÿ\9b\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/filesystem/Exception/FileNotFoundException.php¼\ 1\0\0Τ¶Y¼\ 1\0\0pí\¶¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/filesystem/Exception/IOException.php\87\ 1\0\0Τ¶Y\87\ 1\0\0\80ü#Ѷ\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/filesystem/Exception/IOExceptionInterface.php¦\0\0\0Τ¶Y¦\0\0\0jÙwM¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/filesystem/Filesystem.php¦1\0\0Τ¶Y¦1\0\0\8dò\86\ 1\0\0\0\0\0\0!\0\0\0vendor/symfony/filesystem/LICENSE)\ 4\0\0Τ¶Y)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/filesystem/LockHandler.php¢\ 5\0\0Τ¶Y¢\ 5\0\0D\91;i¶\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/finder/Adapter/AbstractAdapter.php\\v\0\0Τ¶Y\\v\0\0Æ\93É\80\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Adapter/AbstractFindAdapter.php\91\19\0\0Τ¶Y\91\19\0\0ao¦È¶\ 1\0\0\0\0\0\02\0\0\0vendor/symfony/finder/Adapter/AdapterInterface.php±\ 3\0\0Τ¶Y±\ 3\0\0ä»Ê&¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/finder/Adapter/BsdFindAdapter.php2\a\0\0Τ¶Y2\a\0\0Q/ÇC¶\ 1\0\0\0\0\0\00\0\0\0vendor/symfony/finder/Adapter/GnuFindAdapter.php\15\a\0\0Τ¶Y\15\a\0\0\r\17¡¾¶\ 1\0\0\0\0\0\0,\0\0\0vendor/symfony/finder/Adapter/PhpAdapter.phpô\a\0\0Τ¶Yô\a\0\0\16\1d:?¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/finder/Comparator/Comparator.php\8c\ 3\0\0Τ¶Y\8c\ 3\0\0\16wþT¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Comparator/DateComparator.php%\ 3\0\0Τ¶Y%\ 3\0\0L¿EǶ\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Comparator/NumberComparator.php~\ 3\0\0Τ¶Y~\ 3\0\0\94\87 x¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Exception/AccessDeniedException.php\84\0\0\0Τ¶Y\84\0\0\0½¾s\9c\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/finder/Exception/AdapterFailureException.php¯\ 2\0\0Τ¶Y¯\ 2\0\0\9côÔÁ¶\ 1\0\0\0\0\0\06\0\0\0vendor/symfony/finder/Exception/ExceptionInterface.php\84\0\0\0Τ¶Y\84\0\0\0\1cGz-¶\ 1\0\0\0\0\0\0A\0\0\0vendor/symfony/finder/Exception/OperationNotPermitedException.php)\ 1\0\0Τ¶Y)\ 1\0\0ìcj=¶\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/finder/Exception/ShellCommandFailureException.phpÂ\ 2\0\0Τ¶YÂ\ 2\0\0\19v\82ȶ\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/finder/Expression/Expression.php\a\ 6\0\0Τ¶Y\a\ 6\0\0µoÔ\ 6\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/finder/Expression/Glob.phpi\ 4\0\0Τ¶Yi\ 4\0\0@\8a\eº¶\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/finder/Expression/Regex.php\ 6\ f\0\0Τ¶Y\ 6\ f\0\0p8\0\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Expression/ValueInterface.phpÍ\ 1\0\0Τ¶YÍ\ 1\0\0²~øb¶\ 1\0\0\0\0\0\0 \0\0\0vendor/symfony/finder/Finder.phpÂ-\0\0Τ¶YÂ-\0\0\1e\98f´¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/finder/Glob.phpK\ 5\0\0Τ¶YK\ 5\0\0já±n¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/finder/Iterator/CustomFilterIterator.php]\ 2\0\0Τ¶Y]\ 2\0\0tà±µ¶\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/finder/Iterator/DateRangeFilterIterator.phpz\ 2\0\0Τ¶Yz\ 2\0\0ÂT-\ 5\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/finder/Iterator/DepthRangeFilterIterator.phpð\ 1\0\0Τ¶Yð\ 1\0\0ß0\99\ 4\ 1\0\0\0\0\0\0A\0\0\0vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.phpï\ 5\0\0Τ¶Yï\ 5\0\0¾\8dÒâ¶\ 1\0\0\0\0\0\04\0\0\0vendor/symfony/finder/Iterator/FilePathsIterator.php \ 6\0\0Τ¶Y \ 6\0\0fQCe¶\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Iterator/FileTypeFilterIterator.php\\ 2\0\0Τ¶Y\\ 2\0\0p\91'\98\ 1\0\0\0\0\0\0<\0\0\0vendor/symfony/finder/Iterator/FilecontentFilterIterator.php5\ 2\0\0Τ¶Y5\ 2\0\0\9aí\1f\14\ 1\0\0\0\0\0\09\0\0\0vendor/symfony/finder/Iterator/FilenameFilterIterator.phpr\ 1\0\0Τ¶Yr\ 1\0\0t\b\1a\ 1\0\0\0\0\0\01\0\0\0vendor/symfony/finder/Iterator/FilterIterator.phpÃ\ 2\0\0Τ¶YÃ\ 2\0\0\9a+µÞ¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/finder/Iterator/MultiplePcreFilterIterator.php/\ 5\0\0Τ¶Y/\ 5\0\0»Ç\1f\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/finder/Iterator/PathFilterIterator.phpÏ\ 1\0\0Τ¶YÏ\ 1\0\0º\1cªÇ¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php\15   \0\0Τ¶Y\15 \0\0ìt\90¶¶\ 1\0\0\0\0\0\0:\0\0\0vendor/symfony/finder/Iterator/SizeRangeFilterIterator.phpg\ 2\0\0Τ¶Yg\ 2\0\0\97é¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/finder/Iterator/SortableIterator.php,\ 6\0\0Τ¶Y,\ 6\0\0\96\1c\ 1\0\0\0\0\0\0\1d\0\0\0vendor/symfony/finder/LICENSE)\ 4\0\0Τ¶Y)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/finder/Shell/Command.phpS\v\0\0Τ¶YS\v\0\0cC\85\99\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/finder/Shell/Shell.phpp\ 4\0\0Τ¶Yp\ 4\0\0\18Ó}g¶\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/finder/SplFileInfo.phpÿ\ 2\0\0Τ¶Yÿ\ 2\0\0Ë\rOÀ¶\ 1\0\0\0\0\0\0(\0\0\0vendor/symfony/polyfill-mbstring/LICENSE)\ 4\0\0Τ¶Y)\ 4\0\0î*L\14\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/polyfill-mbstring/Mbstring.phpÄ6\0\0Τ¶YÄ6\0\0U.\17ݶ\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php2A\0\0Τ¶Y2A\0\0½\11=¨¶\ 1\0\0\0\0\0\0@\0\0\0vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php¡A\0\0Τ¶Y¡A\0\0\ eÚ    Í¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/polyfill-mbstring/bootstrap.php±\ f\0\0Τ¶Y±\ f\0\0|\8a©Ò¶\ 1\0\0\0\0\0\07\0\0\0vendor/symfony/process/Exception/ExceptionInterface.phpf\0\0\0Τ¶Yf\0\0\0]ö>T¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/process/Exception/InvalidArgumentException.php¨\0\0\0Τ¶Y¨\0\0\0ÐÀ+_¶\ 1\0\0\0\0\0\03\0\0\0vendor/symfony/process/Exception/LogicException.php\94\0\0\0Τ¶Y\94\0\0\0 ³ãñ¶\ 1\0\0\0\0\0\0;\0\0\0vendor/symfony/process/Exception/ProcessFailedException.phpx\ 3\0\0Τ¶Yx\ 3\0\0¨Ìzy¶\ 1\0\0\0\0\0\0=\0\0\0vendor/symfony/process/Exception/ProcessTimedOutException.php\1f\ 4\0\0Τ¶Y\1f\ 4\0\0.     Ãá¶\ 1\0\0\0\0\0\05\0\0\0vendor/symfony/process/Exception/RuntimeException.php\98\0\0\0Τ¶Y\98\0\0\0¢\eØ:¶\ 1\0\0\0\0\0\0+\0\0\0vendor/symfony/process/ExecutableFinder.php\9b\ 4\0\0Τ¶Y\9b\ 4\0\0ý\82m\9b\ 1\0\0\0\0\0\0\1e\0\0\0vendor/symfony/process/LICENSE)\ 4\0\0Τ¶Y)\ 4\0\0·)E`¶\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/process/PhpExecutableFinder.phpg\ 4\0\0Τ¶Yg\ 4\0\0\8dçµ\ 6\ 1\0\0\0\0\0\0%\0\0\0vendor/symfony/process/PhpProcess.phpü\ 3\0\0Τ¶Yü\ 3\0\0_\17\97\ 1\0\0\0\0\0\0.\0\0\0vendor/symfony/process/Pipes/AbstractPipes.php^\a\0\0Τ¶Y^\a\0\0%s\85ï¶\ 1\0\0\0\0\0\0/\0\0\0vendor/symfony/process/Pipes/PipesInterface.phpD\ 1\0\0Τ¶YD\ 1\0\0vØ\ 1\0\0\0\0\0\0*\0\0\0vendor/symfony/process/Pipes/UnixPipes.phpå\a\0\0Τ¶Yå\a\0\0\ 1È¥\ 4\ 1\0\0\0\0\0\0-\0\0\0vendor/symfony/process/Pipes/WindowsPipes.php\8d\v\0\0Τ¶Y\8d\v\0\0\85®\1e\ 1\0\0\0\0\0\0"\0\0\0vendor/symfony/process/Process.php§R\0\0Τ¶Y§R\0\0+Á¥\1f\ 1\0\0\0\0\0\0)\0\0\0vendor/symfony/process/ProcessBuilder.phpã
61 \0\0Τ¶Yã
62 \0\0ʧ°\88\ 1\0\0\0\0\0\0'\0\0\0vendor/symfony/process/ProcessUtils.phpK\ 6\0\0Τ¶YK\ 6\0\0µ½~ò¶\ 1\0\0\0\0\0\0\1c\0\0\0vendor/seld/jsonlint/LICENSE"\ 4\0\0Τ¶Y"\ 4\0\0a\83sy¶\ 1\0\0\0\0\0\0@\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/DuplicateKeyException.php*\ 1\0\0Τ¶Y*\ 1\0\0\19\95pñ¶\ 1\0\0\0\0\0\05\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/JsonParser.php/2\0\0Τ¶Y/2\0\0­ß\98ö¶\ 1\0\0\0\0\0\00\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/Lexer.php\ 6\ f\0\0Τ¶Y\ 6\ f\0\0%ÿ3N¶\ 1\0\0\0\0\0\0;\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/ParsingException.php\1e\ 1\0\0Τ¶Y\1e\ 1\0\0\89²\10ñ¶\ 1\0\0\0\0\0\04\0\0\0vendor/seld/jsonlint/src/Seld/JsonLint/Undefined.php>\0\0\0Τ¶Y>\0\0\0ÿq\9f\9f\ 1\0\0\0\0\0\0\1e\0\0\0vendor/seld/cli-prompt/LICENSE"\ 4\0\0Τ¶Y"\ 4\0\0\88ñ?e¶\ 1\0\0\0\0\0\0&\0\0\0vendor/seld/cli-prompt/res/example.php'\ 1\0\0Τ¶Y'\ 1\0\0I\1c\ 5£¶\ 1\0\0\0\0\0\0(\0\0\0vendor/seld/cli-prompt/src/CliPrompt.phpC\ 6\0\0Τ¶YC\ 6\0\0Ð}\8d\ 1\0\0\0\0\0\0(\0\0\0vendor/justinrainbow/json-schema/LICENSE \ 4\0\0Τ¶Y \ 4\0\0ºç\ 6©¶\ 1\0\0\0\0\0\0.\0\0\0vendor/justinrainbow/json-schema/demo/demo.phpñ\ 1\0\0Τ¶Yñ\ 1\0\0f\e\12\ 1\0\0\0\0\0\0N\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/BaseConstraint.php¡      \0\0Τ¶Y¡ \0\0\86wÌl¶\ 1\0\0\0\0\0\0T\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/CollectionConstraint.php.\r\0\0Τ¶Y.\r\0\0[÷3í¶\ 1\0\0\0\0\0\0J\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Constraint.php\f\ e\0\0Τ¶Y\f\ e\0\0Òé`\13\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/ConstraintInterface.php¼\ 1\0\0Τ¶Y¼\ 1\0\0ÿ Q\9c\ 1\0\0\0\0\0\0N\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/EnumConstraint.php]\ 3\0\0Τ¶Y]\ 3\0\0V\8eU<¶\ 1\0\0\0\0\0\0G\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/Factory.php;\r\0\0Τ¶Y;\r\0\0!/)\18\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/FormatConstraint.php\85\14\0\0Τ¶Y\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\0Τ¶Y\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\0Τ¶YÃ\11\0\0©Å¼x¶\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/SchemaConstraint.phpN \0\0Τ¶YN \0\0QÓmV¶\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/StringConstraint.php\7f\ 4\0\0Τ¶Y\7f\ 4\0\0¥w\9a\87\ 1\0\0\0\0\0\0X\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/LooseTypeCheck.phpa\ 4\0\0Τ¶Ya\ 4\0\0\v     qö\ 1\0\0\0\0\0\0Y\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/StrictTypeCheck.phpp\ 2\0\0Τ¶Yp\ 2\0\0\12r\1fë¶\ 1\0\0\0\0\0\0\\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeCheck/TypeCheckInterface.php\89\ 1\0\0Τ¶Y\89\ 1\0\0\93µ+j¶\ 1\0\0\0\0\0\0N\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/TypeConstraint.php&\ f\0\0Τ¶Y&\ f\0\04\98©T¶\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Constraints/UndefinedConstraint.php\ e!\0\0Τ¶Y\ e!\0\0\90Ò¶Z¶\ 1\0\0\0\0\0\0F\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Entity/JsonPointer.phpè\ 6\0\0Τ¶Yè\ 6\0\0\ 6{N\96\ 1\0\0\0\0\0\0P\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ExceptionInterface.phpI\0\0\0Τ¶YI\0\0\0%|\19°¶\ 1\0\0\0\0\0\0V\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidArgumentException.php\95\0\0\0Τ¶Y\95\0\0\0\8bàG\ 5\ 1\0\0\0\0\0\0T\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidConfigException.phpl\0\0\0Τ¶Yl\0\0\0A!L׶\ 1\0\0\0\0\0\0T\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaException.phpl\0\0\0Τ¶Yl\0\0\0è2÷þ¶\ 1\0\0\0\0\0\0]\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSchemaMediaTypeException.phpu\0\0\0Τ¶Yu\0\0\0=hç\a\ 1\0\0\0\0\0\0W\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/InvalidSourceUriException.phpw\0\0\0Τ¶Yw\0\0\0N-ò[¶\ 1\0\0\0\0\0\0S\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/JsonDecodingException.phpÞ\ 2\0\0Τ¶YÞ\ 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\0Τ¶Yo\0\0\0píÛù¶\ 1\0\0\0\0\0\0N\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/RuntimeException.php\85\0\0\0Τ¶Y\85\0\0\0\b%\85\97\ 1\0\0\0\0\0\0^\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/UnresolvableJsonPointerException.php\80\0\0\0Τ¶Y\80\0\0\0u-#1¶\ 1\0\0\0\0\0\0R\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/UriResolverException.phpj\0\0\0Τ¶Yj\0\0\0å\1a>\8f\ 1\0\0\0\0\0\0Q\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Exception/ValidationException.phpf\0\0\0Τ¶Yf\0\0\0¬¤\84þ¶\ 1\0\0\0\0\0\0K\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Iterator/ObjectIterator.phpþ\ 5\0\0Τ¶Yþ\ 5\0\0M\8f\84õ¶\ 1\0\0\0\0\0\0;\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Rfc3339.php \ 2\0\0Τ¶Y \ 2\0\0f4÷³¶\ 1\0\0\0\0\0\0A\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorage.php\84\f\0\0Τ¶Y\84\f\0\0Nt³è¶\ 1\0\0\0\0\0\0J\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/SchemaStorageInterface.php\ 1\ 1\0\0Τ¶Y\ 1\ 1\0\0o\8a+}¶\ 1\0\0\0\0\0\0T\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/AbstractRetriever.phpá\0\0\0Τ¶Yá\0\0\0[þA\81\ 1\0\0\0\0\0\0G\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/Curl.php¥\ 4\0\0Τ¶Y¥\ 4\0\0Ô§Lb¶\ 1\0\0\0\0\0\0R\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/FileGetContents.php%\ 5\0\0Τ¶Y%\ 5\0\05"\10 ¶\ 1\0\0\0\0\0\0R\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/PredefinedArray.php,\ 2\0\0Τ¶Y,\ 2\0\01\955þ¶\ 1\0\0\0\0\0\0X\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/Retrievers/UriRetrieverInterface.php®\0\0\0Τ¶Y®\0\0\0ÿ\8bÁå¶\ 1\0\0\0\0\0\0C\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriResolver.php\96  \0\0Τ¶Y\96 \0\0=&ßͶ\ 1\0\0\0\0\0\0D\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Uri/UriRetriever.php&\13\0\0Τ¶Y&\13\0\0¼î\82¢¶\ 1\0\0\0\0\0\0H\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/UriResolverInterface.php\83\0\0\0Τ¶Y\83\0\0\0\12J\80\1f\ 1\0\0\0\0\0\0I\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/UriRetrieverInterface.php\85\0\0\0Τ¶Y\85\0\0\0íæ\e\ 1\0\0\0\0\0\0=\0\0\0vendor/justinrainbow/json-schema/src/JsonSchema/Validator.phpn\ 5\0\0Τ¶Yn\ 5\0\0\90Ñ|§¶\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/spdx-licenses/LICENSE\1c\ 4\0\0Τ¶Y\1c\ 4\0\0\ 6Bhí¶\ 1\0\0\0\0\0\02\0\0\0vendor/composer/spdx-licenses/src/SpdxLicenses.phpç\11\0\0Τ¶Yç\11\0\0·\96U ¶\ 1\0\0\0\0\0\0\1e\0\0\0vendor/composer/semver/LICENSE\1c\ 4\0\0Τ¶Y\1c\ 4\0\0\ 6Bhí¶\ 1\0\0\0\0\0\0)\0\0\0vendor/composer/semver/src/Comparator.php\ 2\ 4\0\0Τ¶Y\ 2\ 4\0\0wl\83ï¶\ 1\0\0\0\0\0\0<\0\0\0vendor/composer/semver/src/Constraint/AbstractConstraint.php×\ 2\0\0Τ¶Y×\ 2\0\0õî>\8e\ 1\0\0\0\0\0\04\0\0\0vendor/composer/semver/src/Constraint/Constraint.phpª\f\0\0Τ¶Yª\f\0\0ÇO7²¶\ 1\0\0\0\0\0\0=\0\0\0vendor/composer/semver/src/Constraint/ConstraintInterface.phpß\0\0\0Τ¶Yß\0\0\00C,\87\ 1\0\0\0\0\0\09\0\0\0vendor/composer/semver/src/Constraint/EmptyConstraint.phpé\ 1\0\0Τ¶Yé\ 1\0\0!-Ø\99\ 1\0\0\0\0\0\09\0\0\0vendor/composer/semver/src/Constraint/MultiConstraint.php1\ 5\0\0Τ¶Y1\ 5\0\0í xU¶\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/semver/src/Semver.phpv\ 6\0\0Τ¶Yv\ 6\0\0\8b×È\9b\ 1\0\0\0\0\0\0,\0\0\0vendor/composer/semver/src/VersionParser.php¿*\0\0Τ¶Y¿*\0\0\13)mƶ\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/ca-bundle/LICENSE\1c\ 4\0\0Τ¶Y\1c\ 4\0\0*!^`¶\ 1\0\0\0\0\0\0*\0\0\0vendor/composer/ca-bundle/src/CaBundle.php½\e\0\0Τ¶Y½\e\0\0e\1c\e\1e\ 1\0\0\0\0\0\0\16\0\0\0vendor/psr/log/LICENSE=\ 4\0\0Τ¶Y=\ 4\0\0\8e\ 1\0\0\0\0\0\0)\0\0\0vendor/psr/log/Psr/Log/AbstractLogger.php;\ 4\0\0Τ¶Y;\ 4\0\0ñ>3[¶\ 1\0\0\0\0\0\03\0\0\0vendor/psr/log/Psr/Log/InvalidArgumentException.php`\0\0\0Τ¶Y`\0\0\0 \88X1¶\ 1\0\0\0\0\0\0#\0\0\0vendor/psr/log/Psr/Log/LogLevel.phpû\0\0\0Τ¶Yû\0\0\0jðñ8¶\ 1\0\0\0\0\0\0/\0\0\0vendor/psr/log/Psr/Log/LoggerAwareInterface.php|\0\0\0Τ¶Y|\0\0\0$\13£\88\ 1\0\0\0\0\0\0+\0\0\0vendor/psr/log/Psr/Log/LoggerAwareTrait.php§\0\0\0Τ¶Y§\0\0\0T½úB¶\ 1\0\0\0\0\0\0*\0\0\0vendor/psr/log/Psr/Log/LoggerInterface.phpÆ\ 2\0\0Τ¶YÆ\ 2\0\0»\12sg¶\ 1\0\0\0\0\0\0&\0\0\0vendor/psr/log/Psr/Log/LoggerTrait.phpi\ 4\0\0Τ¶Yi\ 4\0\035§Þ¶\ 1\0\0\0\0\0\0%\0\0\0vendor/psr/log/Psr/Log/NullLogger.php\9e\0\0\0Τ¶Y\9e\0\0\0Ç\ 2Ã\1f\ 1\0\0\0\0\0\03\0\0\0vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.phpü\f\0\0Τ¶Yü\f\0\0iq0ض\ 1\0\0\0\0\0\0\13\0\0\0vendor/autoload.php\82\0\0\0Τ¶Y\82\0\0\0ñ\ 3
66\ 1\0\0\0\0\0\0'\0\0\0vendor/composer/autoload_namespaces.phpd\0\0\0Τ¶Yd\0\0\0Z¡¦H¶\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/autoload_psr4.php\98\ 4\0\0Τ¶Y\98\ 4\0\0\9e\1c{¢¶\ 1\0\0\0\0\0\0%\0\0\0vendor/composer/autoload_classmap.phpd\0\0\0Τ¶Yd\0\0\0Z¡¦H¶\ 1\0\0\0\0\0\0"\0\0\0vendor/composer/autoload_files.phpÃ\0\0\0Τ¶YÃ\0\0\0ÒÂür¶\ 1\0\0\0\0\0\0!\0\0\0vendor/composer/autoload_real.phpI\a\0\0Τ¶YI\a\0\06\8f\11\ 1\0\0\0\0\0\0#\0\0\0vendor/composer/autoload_static.php¬   \0\0Τ¶Y¬ \0\0\90\8fwz¶\ 1\0\0\0\0\0\0\1f\0\0\0vendor/composer/ClassLoader.php\9c\18\0\0Τ¶Y\9c\18\0\0¥ÂåN¶\ 1\0\0\0\0\0\0(\0\0\0vendor/composer/ca-bundle/res/cacert.pem\bè\ 3\0Τ¶Y\bè\ 3\0x85ú¶\ 1\0\0\0\0\0\0\f\0\0\0bin/composer\8b\ 5\0\0Τ¶Y\8b\ 5\0\0íeG\9a\ 1\0\0\0\0\0\0\a\0\0\0LICENSE.\ 4\0\0Τ¶Y.\ 4\0\0 Õ\b\ 3\ 1\0\0\0\0\0\0<?php
67
68
69
70
71
72
73
74
75
76
77
78 namespace Composer\Autoload;
79
80 use Composer\Config;
81 use Composer\EventDispatcher\EventDispatcher;
82 use Composer\Installer\InstallationManager;
83 use Composer\IO\IOInterface;
84 use Composer\Package\AliasPackage;
85 use Composer\Package\PackageInterface;
86 use Composer\Repository\InstalledRepositoryInterface;
87 use Composer\Util\Filesystem;
88 use Composer\Script\ScriptEvents;
89
90
91
92
93
94 class AutoloadGenerator
95 {
96
97
98
99 private $eventDispatcher;
100
101
102
103
104 private $io;
105
106
107
108
109 private $devMode = false;
110
111
112
113
114 private $classMapAuthoritative = false;
115
116
117
118
119 private $apcu = false;
120
121
122
123
124 private $runScripts = false;
125
126 public function __construct(EventDispatcher $eventDispatcher, IOInterface $io = null)
127 {
128 $this->eventDispatcher = $eventDispatcher;
129 $this->io = $io;
130 }
131
132 public function setDevMode($devMode = true)
133 {
134 $this->devMode = (bool) $devMode;
135 }
136
137
138
139
140
141
142
143 public function setClassMapAuthoritative($classMapAuthoritative)
144 {
145 $this->classMapAuthoritative = (bool) $classMapAuthoritative;
146 }
147
148
149
150
151
152
153 public function setApcu($apcu)
154 {
155 $this->apcu = (bool) $apcu;
156 }
157
158
159
160
161
162
163 public function setRunScripts($runScripts = true)
164 {
165 $this->runScripts = (bool) $runScripts;
166 }
167
168 public function dump(Config $config, InstalledRepositoryInterface $localRepo, PackageInterface $mainPackage, InstallationManager $installationManager, $targetDir, $scanPsr0Packages = false, $suffix = '')
169 {
170 if ($this->classMapAuthoritative) {
171
172  $scanPsr0Packages = true;
173 }
174 if ($this->runScripts) {
175 $this->eventDispatcher->dispatchScript(ScriptEvents::PRE_AUTOLOAD_DUMP, $this->devMode, array(), array(
176 'optimize' => (bool) $scanPsr0Packages,
177 ));
178 }
179
180 $filesystem = new Filesystem();
181 $filesystem->ensureDirectoryExists($config->get('vendor-dir'));
182
183  
184  
185  $basePath = $filesystem->normalizePath(realpath(realpath(getcwd())));
186 $vendorPath = $filesystem->normalizePath(realpath(realpath($config->get('vendor-dir'))));
187 $useGlobalIncludePath = (bool) $config->get('use-include-path');
188 $prependAutoloader = $config->get('prepend-autoloader') === false ? 'false' : 'true';
189 $targetDir = $vendorPath.'/'.$targetDir;
190 $filesystem->ensureDirectoryExists($targetDir);
191
192 $vendorPathCode = $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true);
193 $vendorPathCode52 = str_replace('__DIR__', 'dirname(__FILE__)', $vendorPathCode);
194 $vendorPathToTargetDirCode = $filesystem->findShortestPathCode($vendorPath, realpath($targetDir), true);
195
196 $appBaseDirCode = $filesystem->findShortestPathCode($vendorPath, $basePath, true);
197 $appBaseDirCode = str_replace('__DIR__', '$vendorDir', $appBaseDirCode);
198
199 $namespacesFile = <<<EOF
200 <?php
201
202 // autoload_namespaces.php @generated by Composer
203
204 \$vendorDir = $vendorPathCode52;
205 \$baseDir = $appBaseDirCode;
206
207 return array(
208
209 EOF;
210
211 $psr4File = <<<EOF
212 <?php
213
214 // autoload_psr4.php @generated by Composer
215
216 \$vendorDir = $vendorPathCode52;
217 \$baseDir = $appBaseDirCode;
218
219 return array(
220
221 EOF;
222
223
224  $packageMap = $this->buildPackageMap($installationManager, $mainPackage, $localRepo->getCanonicalPackages());
225 $autoloads = $this->parseAutoloads($packageMap, $mainPackage);
226
227
228  foreach ($autoloads['psr-0'] as $namespace => $paths) {
229 $exportedPaths = array();
230 foreach ($paths as $path) {
231 $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
232 }
233 $exportedPrefix = var_export($namespace, true);
234 $namespacesFile .= "    $exportedPrefix => ";
235 $namespacesFile .= "array(".implode(', ', $exportedPaths)."),\n";
236 }
237 $namespacesFile .= ");\n";
238
239
240  foreach ($autoloads['psr-4'] as $namespace => $paths) {
241 $exportedPaths = array();
242 foreach ($paths as $path) {
243 $exportedPaths[] = $this->getPathCode($filesystem, $basePath, $vendorPath, $path);
244 }
245 $exportedPrefix = var_export($namespace, true);
246 $psr4File .= "    $exportedPrefix => ";
247 $psr4File .= "array(".implode(', ', $exportedPaths)."),\n";
248 }
249 $psr4File .= ");\n";
250
251 $classmapFile = <<<EOF
252 <?php
253
254 // autoload_classmap.php @generated by Composer
255
256 \$vendorDir = $vendorPathCode52;
257 \$baseDir = $appBaseDirCode;
258
259 return array(
260
261 EOF;
262
263
264  $targetDirLoader = null;
265 $mainAutoload = $mainPackage->getAutoload();
266 if ($mainPackage->getTargetDir() && !empty($mainAutoload['psr-0'])) {
267 $levels = count(explode('/', $filesystem->normalizePath($mainPackage->getTargetDir())));
268 $prefixes = implode(', ', array_map(function ($prefix) {
269 return var_export($prefix, true);
270 }, array_keys($mainAutoload['psr-0'])));
271 $baseDirFromTargetDirCode = $filesystem->findShortestPathCode($targetDir, $basePath, true);
272
273 $targetDirLoader = <<<EOF
274
275     public static function autoload(\$class)
276     {
277         \$dir = $baseDirFromTargetDirCode . '/';
278         \$prefixes = array($prefixes);
279         foreach (\$prefixes as \$prefix) {
280             if (0 !== strpos(\$class, \$prefix)) {
281                 continue;
282             }
283             \$path = \$dir . implode('/', array_slice(explode('\\\\', \$class), $levels)).'.php';
284             if (!\$path = stream_resolve_include_path(\$path)) {
285                 return false;
286             }
287             require \$path;
288
289             return true;
290         }
291     }
292
293 EOF;
294 }
295
296 $blacklist = null;
297 if (!empty($autoloads['exclude-from-classmap'])) {
298 $blacklist = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
299 }
300
301
302  $classMap = array();
303 if ($scanPsr0Packages) {
304 $namespacesToScan = array();
305
306
307  foreach (array('psr-0', 'psr-4') as $psrType) {
308 foreach ($autoloads[$psrType] as $namespace => $paths) {
309 $namespacesToScan[$namespace][] = array('paths' => $paths, 'type' => $psrType);
310 }
311 }
312
313 krsort($namespacesToScan);
314
315 foreach ($namespacesToScan as $namespace => $groups) {
316 foreach ($groups as $group) {
317 foreach ($group['paths'] as $dir) {
318 $dir = $filesystem->normalizePath($filesystem->isAbsolutePath($dir) ? $dir : $basePath.'/'.$dir);
319 if (!is_dir($dir)) {
320 continue;
321 }
322
323 $namespaceFilter = $namespace === '' ? null : $namespace;
324 $classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, $namespaceFilter, $classMap);
325 }
326 }
327 }
328 }
329
330 foreach ($autoloads['classmap'] as $dir) {
331 $classMap = $this->addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist, null, $classMap);
332 }
333
334 ksort($classMap);
335 foreach ($classMap as $class => $code) {
336 $classmapFile .= '    '.var_export($class, true).' => '.$code;
337 }
338 $classmapFile .= ");\n";
339
340 if (!$suffix) {
341 if (!$config->get('autoloader-suffix') && is_readable($vendorPath.'/autoload.php')) {
342 $content = file_get_contents($vendorPath.'/autoload.php');
343 if (preg_match('{ComposerAutoloaderInit([^:\s]+)::}', $content, $match)) {
344 $suffix = $match[1];
345 }
346 }
347
348 if (!$suffix) {
349 $suffix = $config->get('autoloader-suffix') ?: md5(uniqid('', true));
350 }
351 }
352
353 file_put_contents($targetDir.'/autoload_namespaces.php', $namespacesFile);
354 file_put_contents($targetDir.'/autoload_psr4.php', $psr4File);
355 file_put_contents($targetDir.'/autoload_classmap.php', $classmapFile);
356 $includePathFilePath = $targetDir.'/include_paths.php';
357 if ($includePathFileContents = $this->getIncludePathsFile($packageMap, $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
358 file_put_contents($includePathFilePath, $includePathFileContents);
359 } elseif (file_exists($includePathFilePath)) {
360 unlink($includePathFilePath);
361 }
362 $includeFilesFilePath = $targetDir.'/autoload_files.php';
363 if ($includeFilesFileContents = $this->getIncludeFilesFile($autoloads['files'], $filesystem, $basePath, $vendorPath, $vendorPathCode52, $appBaseDirCode)) {
364 file_put_contents($includeFilesFilePath, $includeFilesFileContents);
365 } elseif (file_exists($includeFilesFilePath)) {
366 unlink($includeFilesFilePath);
367 }
368 file_put_contents($targetDir.'/autoload_static.php', $this->getStaticFile($suffix, $targetDir, $vendorPath, $basePath, $staticPhpVersion));
369 file_put_contents($vendorPath.'/autoload.php', $this->getAutoloadFile($vendorPathToTargetDirCode, $suffix));
370 file_put_contents($targetDir.'/autoload_real.php', $this->getAutoloadRealFile(true, (bool) $includePathFileContents, $targetDirLoader, (bool) $includeFilesFileContents, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion));
371
372 $this->safeCopy(__DIR__.'/ClassLoader.php', $targetDir.'/ClassLoader.php');
373 $this->safeCopy(__DIR__.'/../../../LICENSE', $targetDir.'/LICENSE');
374
375 if ($this->runScripts) {
376 $this->eventDispatcher->dispatchScript(ScriptEvents::POST_AUTOLOAD_DUMP, $this->devMode, array(), array(
377 'optimize' => (bool) $scanPsr0Packages,
378 ));
379 }
380 }
381
382 private function addClassMapCode($filesystem, $basePath, $vendorPath, $dir, $blacklist = null, $namespaceFilter = null, array $classMap = array())
383 {
384 foreach ($this->generateClassMap($dir, $blacklist, $namespaceFilter) as $class => $path) {
385 $pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path).",\n";
386 if (!isset($classMap[$class])) {
387 $classMap[$class] = $pathCode;
388 } elseif ($this->io && $classMap[$class] !== $pathCode && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($classMap[$class].' '.$path, '\\', '/'))) {
389 $this->io->writeError(
390 '<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
391 ' was found in both "'.str_replace(array('$vendorDir . \'', "',\n"), array($vendorPath, ''), $classMap[$class]).'" and "'.$path.'", the first will be used.</warning>'
392 );
393 }
394 }
395
396 return $classMap;
397 }
398
399 private function generateClassMap($dir, $blacklist = null, $namespaceFilter = null, $showAmbiguousWarning = true)
400 {
401 return ClassMapGenerator::createMap($dir, $blacklist, $showAmbiguousWarning ? $this->io : null, $namespaceFilter);
402 }
403
404 public function buildPackageMap(InstallationManager $installationManager, PackageInterface $mainPackage, array $packages)
405 {
406
407  $packageMap = array(array($mainPackage, ''));
408
409 foreach ($packages as $package) {
410 if ($package instanceof AliasPackage) {
411 continue;
412 }
413 $this->validatePackage($package);
414
415 $packageMap[] = array(
416 $package,
417 $installationManager->getInstallPath($package),
418 );
419 }
420
421 return $packageMap;
422 }
423
424
425
426
427
428
429 protected function validatePackage(PackageInterface $package)
430 {
431 $autoload = $package->getAutoload();
432 if (!empty($autoload['psr-4']) && null !== $package->getTargetDir()) {
433 $name = $package->getName();
434 $package->getTargetDir();
435 throw new \InvalidArgumentException("PSR-4 autoloading is incompatible with the target-dir property, remove the target-dir in package '$name'.");
436 }
437 if (!empty($autoload['psr-4'])) {
438 foreach ($autoload['psr-4'] as $namespace => $dirs) {
439 if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
440 throw new \InvalidArgumentException("psr-4 namespaces must end with a namespace separator, '$namespace' does not, use '$namespace\\'.");
441 }
442 }
443 }
444 }
445
446
447
448
449
450
451
452
453 public function parseAutoloads(array $packageMap, PackageInterface $mainPackage)
454 {
455 $mainPackageMap = array_shift($packageMap);
456 $sortedPackageMap = $this->sortPackageMap($packageMap);
457 $sortedPackageMap[] = $mainPackageMap;
458 array_unshift($packageMap, $mainPackageMap);
459
460 $psr0 = $this->parseAutoloadsType($packageMap, 'psr-0', $mainPackage);
461 $psr4 = $this->parseAutoloadsType($packageMap, 'psr-4', $mainPackage);
462 $classmap = $this->parseAutoloadsType(array_reverse($sortedPackageMap), 'classmap', $mainPackage);
463 $files = $this->parseAutoloadsType($sortedPackageMap, 'files', $mainPackage);
464 $exclude = $this->parseAutoloadsType($sortedPackageMap, 'exclude-from-classmap', $mainPackage);
465
466 krsort($psr0);
467 krsort($psr4);
468
469 return array(
470 'psr-0' => $psr0,
471 'psr-4' => $psr4,
472 'classmap' => $classmap,
473 'files' => $files,
474 'exclude-from-classmap' => $exclude,
475 );
476 }
477
478
479
480
481
482
483
484 public function createLoader(array $autoloads)
485 {
486 $loader = new ClassLoader();
487
488 if (isset($autoloads['psr-0'])) {
489 foreach ($autoloads['psr-0'] as $namespace => $path) {
490 $loader->add($namespace, $path);
491 }
492 }
493
494 if (isset($autoloads['psr-4'])) {
495 foreach ($autoloads['psr-4'] as $namespace => $path) {
496 $loader->addPsr4($namespace, $path);
497 }
498 }
499
500 if (isset($autoloads['classmap'])) {
501 $blacklist = null;
502 if (!empty($autoloads['exclude-from-classmap'])) {
503 $blacklist = '{(' . implode('|', $autoloads['exclude-from-classmap']) . ')}';
504 }
505
506 foreach ($autoloads['classmap'] as $dir) {
507 try {
508 $loader->addClassMap($this->generateClassMap($dir, $blacklist, null, false));
509 } catch (\RuntimeException $e) {
510 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
511 }
512 }
513 }
514
515 return $loader;
516 }
517
518 protected function getIncludePathsFile(array $packageMap, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
519 {
520 $includePaths = array();
521
522 foreach ($packageMap as $item) {
523 list($package, $installPath) = $item;
524
525 if (null !== $package->getTargetDir() && strlen($package->getTargetDir()) > 0) {
526 $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
527 }
528
529 foreach ($package->getIncludePaths() as $includePath) {
530 $includePath = trim($includePath, '/');
531 $includePaths[] = empty($installPath) ? $includePath : $installPath.'/'.$includePath;
532 }
533 }
534
535 if (!$includePaths) {
536 return;
537 }
538
539 $includePathsCode = '';
540 foreach ($includePaths as $path) {
541 $includePathsCode .= "    " . $this->getPathCode($filesystem, $basePath, $vendorPath, $path) . ",\n";
542 }
543
544 return <<<EOF
545 <?php
546
547 // include_paths.php @generated by Composer
548
549 \$vendorDir = $vendorPathCode;
550 \$baseDir = $appBaseDirCode;
551
552 return array(
553 $includePathsCode);
554
555 EOF;
556 }
557
558 protected function getIncludeFilesFile(array $files, Filesystem $filesystem, $basePath, $vendorPath, $vendorPathCode, $appBaseDirCode)
559 {
560 $filesCode = '';
561 foreach ($files as $fileIdentifier => $functionFile) {
562 $filesCode .= '    ' . var_export($fileIdentifier, true) . ' => '
563 . $this->getPathCode($filesystem, $basePath, $vendorPath, $functionFile) . ",\n";
564 }
565
566 if (!$filesCode) {
567 return false;
568 }
569
570 return <<<EOF
571 <?php
572
573 // autoload_files.php @generated by Composer
574
575 \$vendorDir = $vendorPathCode;
576 \$baseDir = $appBaseDirCode;
577
578 return array(
579 $filesCode);
580
581 EOF;
582 }
583
584 protected function getPathCode(Filesystem $filesystem, $basePath, $vendorPath, $path)
585 {
586 if (!$filesystem->isAbsolutePath($path)) {
587 $path = $basePath . '/' . $path;
588 }
589 $path = $filesystem->normalizePath($path);
590
591 $baseDir = '';
592 if (strpos($path.'/', $vendorPath.'/') === 0) {
593 $path = substr($path, strlen($vendorPath));
594 $baseDir = '$vendorDir';
595
596 if ($path !== false) {
597 $baseDir .= " . ";
598 }
599 } else {
600 $path = $filesystem->normalizePath($filesystem->findShortestPath($basePath, $path, true));
601 if (!$filesystem->isAbsolutePath($path)) {
602 $baseDir = '$baseDir . ';
603 $path = '/' . $path;
604 }
605 }
606
607 if (preg_match('/\.phar.+$/', $path)) {
608 $baseDir = "'phar://' . " . $baseDir;
609 }
610
611 return $baseDir . (($path !== false) ? var_export($path, true) : "");
612 }
613
614 protected function getAutoloadFile($vendorPathToTargetDirCode, $suffix)
615 {
616 $lastChar = $vendorPathToTargetDirCode[strlen($vendorPathToTargetDirCode) - 1];
617 if ("'" === $lastChar || '"' === $lastChar) {
618 $vendorPathToTargetDirCode = substr($vendorPathToTargetDirCode, 0, -1).'/autoload_real.php'.$lastChar;
619 } else {
620 $vendorPathToTargetDirCode .= " . '/autoload_real.php'";
621 }
622
623 return <<<AUTOLOAD
624 <?php
625
626 // autoload.php @generated by Composer
627
628 require_once $vendorPathToTargetDirCode;
629
630 return ComposerAutoloaderInit$suffix::getLoader();
631
632 AUTOLOAD;
633 }
634
635 protected function getAutoloadRealFile($useClassMap, $useIncludePath, $targetDirLoader, $useIncludeFiles, $vendorPathCode, $appBaseDirCode, $suffix, $useGlobalIncludePath, $prependAutoloader, $staticPhpVersion = 70000)
636 {
637 $file = <<<HEADER
638 <?php
639
640 // autoload_real.php @generated by Composer
641
642 class ComposerAutoloaderInit$suffix
643 {
644     private static \$loader;
645
646     public static function loadClassLoader(\$class)
647     {
648         if ('Composer\\Autoload\\ClassLoader' === \$class) {
649             require __DIR__ . '/ClassLoader.php';
650         }
651     }
652
653     public static function getLoader()
654     {
655         if (null !== self::\$loader) {
656             return self::\$loader;
657         }
658
659         spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'), true, $prependAutoloader);
660         self::\$loader = \$loader = new \\Composer\\Autoload\\ClassLoader();
661         spl_autoload_unregister(array('ComposerAutoloaderInit$suffix', 'loadClassLoader'));
662
663
664 HEADER;
665
666 if ($useIncludePath) {
667 $file .= <<<'INCLUDE_PATH'
668         $includePaths = require __DIR__ . '/include_paths.php';
669         array_push($includePaths, get_include_path());
670         set_include_path(implode(PATH_SEPARATOR, $includePaths));
671
672
673 INCLUDE_PATH;
674 }
675
676 $file .= <<<STATIC_INIT
677         \$useStaticLoader = PHP_VERSION_ID >= $staticPhpVersion && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
678         if (\$useStaticLoader) {
679             require_once __DIR__ . '/autoload_static.php';
680
681             call_user_func(\Composer\Autoload\ComposerStaticInit$suffix::getInitializer(\$loader));
682         } else {
683
684 STATIC_INIT;
685
686 if (!$this->classMapAuthoritative) {
687 $file .= <<<'PSR04'
688             $map = require __DIR__ . '/autoload_namespaces.php';
689             foreach ($map as $namespace => $path) {
690                 $loader->set($namespace, $path);
691             }
692
693             $map = require __DIR__ . '/autoload_psr4.php';
694             foreach ($map as $namespace => $path) {
695                 $loader->setPsr4($namespace, $path);
696             }
697
698
699 PSR04;
700 }
701
702 if ($useClassMap) {
703 $file .= <<<'CLASSMAP'
704             $classMap = require __DIR__ . '/autoload_classmap.php';
705             if ($classMap) {
706                 $loader->addClassMap($classMap);
707             }
708
709 CLASSMAP;
710 }
711
712 $file .= "        }\n\n";
713
714 if ($this->classMapAuthoritative) {
715 $file .= <<<'CLASSMAPAUTHORITATIVE'
716         $loader->setClassMapAuthoritative(true);
717
718 CLASSMAPAUTHORITATIVE;
719 }
720
721 if ($this->apcu) {
722 $apcuPrefix = substr(base64_encode(md5(uniqid('', true), true)), 0, -3);
723 $file .= <<<APCU
724         \$loader->setApcuPrefix('$apcuPrefix');
725
726 APCU;
727 }
728
729 if ($useGlobalIncludePath) {
730 $file .= <<<'INCLUDEPATH'
731         $loader->setUseIncludePath(true);
732
733 INCLUDEPATH;
734 }
735
736 if ($targetDirLoader) {
737 $file .= <<<REGISTER_TARGET_DIR_AUTOLOAD
738         spl_autoload_register(array('ComposerAutoloaderInit$suffix', 'autoload'), true, true);
739
740
741 REGISTER_TARGET_DIR_AUTOLOAD;
742 }
743
744 $file .= <<<REGISTER_LOADER
745         \$loader->register($prependAutoloader);
746
747
748 REGISTER_LOADER;
749
750 if ($useIncludeFiles) {
751 $file .= <<<INCLUDE_FILES
752         if (\$useStaticLoader) {
753             \$includeFiles = Composer\Autoload\ComposerStaticInit$suffix::\$files;
754         } else {
755             \$includeFiles = require __DIR__ . '/autoload_files.php';
756         }
757         foreach (\$includeFiles as \$fileIdentifier => \$file) {
758             composerRequire$suffix(\$fileIdentifier, \$file);
759         }
760
761
762 INCLUDE_FILES;
763 }
764
765 $file .= <<<METHOD_FOOTER
766         return \$loader;
767     }
768
769 METHOD_FOOTER;
770
771 $file .= $targetDirLoader;
772
773 if ($useIncludeFiles) {
774 return $file . <<<FOOTER
775 }
776
777 function composerRequire$suffix(\$fileIdentifier, \$file)
778 {
779     if (empty(\$GLOBALS['__composer_autoload_files'][\$fileIdentifier])) {
780         require \$file;
781
782         \$GLOBALS['__composer_autoload_files'][\$fileIdentifier] = true;
783     }
784 }
785
786 FOOTER;
787 }
788
789 return $file . <<<FOOTER
790 }
791
792 FOOTER;
793 }
794
795 protected function getStaticFile($suffix, $targetDir, $vendorPath, $basePath, &$staticPhpVersion)
796 {
797 $staticPhpVersion = 50600;
798
799 $file = <<<HEADER
800 <?php
801
802 // autoload_static.php @generated by Composer
803
804 namespace Composer\Autoload;
805
806 class ComposerStaticInit$suffix
807 {
808
809 HEADER;
810
811 $loader = new ClassLoader();
812
813 $map = require $targetDir . '/autoload_namespaces.php';
814 foreach ($map as $namespace => $path) {
815 $loader->set($namespace, $path);
816 }
817
818 $map = require $targetDir . '/autoload_psr4.php';
819 foreach ($map as $namespace => $path) {
820 $loader->setPsr4($namespace, $path);
821 }
822
823 $classMap = require $targetDir . '/autoload_classmap.php';
824 if ($classMap) {
825 $loader->addClassMap($classMap);
826 }
827
828 $filesystem = new Filesystem();
829
830 $vendorPathCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $vendorPath, true, true) . " . '/";
831 $appBaseDirCode = ' => ' . $filesystem->findShortestPathCode(realpath($targetDir), $basePath, true, true) . " . '/";
832
833 $absoluteVendorPathCode = ' => ' . substr(var_export(rtrim($vendorDir, '\\/') . '/', true), 0, -1);
834 $absoluteAppBaseDirCode = ' => ' . substr(var_export(rtrim($baseDir, '\\/') . '/', true), 0, -1);
835
836 $initializer = '';
837 $prefix = "\0Composer\Autoload\ClassLoader\0";
838 $prefixLen = strlen($prefix);
839 if (file_exists($targetDir . '/autoload_files.php')) {
840 $maps = array('files' => require $targetDir . '/autoload_files.php');
841 } else {
842 $maps = array();
843 }
844
845 foreach ((array) $loader as $prop => $value) {
846 if ($value && 0 === strpos($prop, $prefix)) {
847 $maps[substr($prop, $prefixLen)] = $value;
848 }
849 }
850
851 foreach ($maps as $prop => $value) {
852 if (count($value) > 32767) {
853
854  
855  $staticPhpVersion = 70000;
856 }
857 $value = var_export($value, true);
858 $value = str_replace($absoluteVendorPathCode, $vendorPathCode, $value);
859 $value = str_replace($absoluteAppBaseDirCode, $appBaseDirCode, $value);
860 $value = ltrim(preg_replace('/^ */m', '    $0$0', $value));
861
862 $file .= sprintf("    public static $%s = %s;\n\n", $prop, $value);
863 if ('files' !== $prop) {
864 $initializer .= "            \$loader->$prop = ComposerStaticInit$suffix::\$$prop;\n";
865 }
866 }
867
868 return $file . <<<INITIALIZER
869     public static function getInitializer(ClassLoader \$loader)
870     {
871         return \Closure::bind(function () use (\$loader) {
872 $initializer
873         }, null, ClassLoader::class);
874     }
875 }
876
877 INITIALIZER;
878 }
879
880 protected function parseAutoloadsType(array $packageMap, $type, PackageInterface $mainPackage)
881 {
882 $autoloads = array();
883
884 foreach ($packageMap as $item) {
885 list($package, $installPath) = $item;
886
887 $autoload = $package->getAutoload();
888 if ($this->devMode && $package === $mainPackage) {
889 $autoload = array_merge_recursive($autoload, $package->getDevAutoload());
890 }
891
892
893  if (!isset($autoload[$type]) || !is_array($autoload[$type])) {
894 continue;
895 }
896 if (null !== $package->getTargetDir() && $package !== $mainPackage) {
897 $installPath = substr($installPath, 0, -strlen('/'.$package->getTargetDir()));
898 }
899
900 foreach ($autoload[$type] as $namespace => $paths) {
901 foreach ((array) $paths as $path) {
902 if (($type === 'files' || $type === 'classmap' || $type === 'exclude-from-classmap') && $package->getTargetDir() && !is_readable($installPath.'/'.$path)) {
903
904  if ($package === $mainPackage) {
905 $targetDir = str_replace('\\<dirsep\\>', '[\\\\/]', preg_quote(str_replace(array('/', '\\'), '<dirsep>', $package->getTargetDir())));
906 $path = ltrim(preg_replace('{^'.$targetDir.'}', '', ltrim($path, '\\/')), '\\/');
907 } else {
908
909  $path = $package->getTargetDir() . '/' . $path;
910 }
911 }
912
913 if ($type === 'exclude-from-classmap') {
914
915  $path = preg_replace('{/+}', '/', preg_quote(trim(strtr($path, '\\', '/'), '/')));
916
917
918  $path = str_replace('\\*\\*', '.+?', $path);
919 $path = str_replace('\\*', '[^/]+?', $path);
920
921
922  $updir = null;
923 $path = preg_replace_callback(
924 '{^((?:(?:\\\\\\.){1,2}+/)+)}',
925 function ($matches) use (&$updir) {
926 if (isset($matches[1])) {
927
928  $updir = str_replace('\\.', '.', $matches[1]);
929 }
930
931 return '';
932 },
933 $path
934 );
935 if (empty($installPath)) {
936 $installPath = strtr(getcwd(), '\\', '/');
937 }
938
939 $resolvedPath = realpath($installPath . '/' . $updir);
940 $autoloads[] = preg_quote(strtr($resolvedPath, '\\', '/')) . '/' . $path;
941 continue;
942 }
943
944 $relativePath = empty($installPath) ? (empty($path) ? '.' : $path) : $installPath.'/'.$path;
945
946 if ($type === 'files') {
947 $autoloads[$this->getFileIdentifier($package, $path)] = $relativePath;
948 continue;
949 } elseif ($type === 'classmap') {
950 $autoloads[] = $relativePath;
951 continue;
952 }
953
954 $autoloads[$namespace][] = $relativePath;
955 }
956 }
957 }
958
959 return $autoloads;
960 }
961
962 protected function getFileIdentifier(PackageInterface $package, $path)
963 {
964 return md5($package->getName() . ':' . $path);
965 }
966
967
968
969
970
971
972
973
974
975 protected function sortPackageMap(array $packageMap)
976 {
977 $packages = array();
978 $paths = array();
979 $usageList = array();
980
981 foreach ($packageMap as $item) {
982 list($package, $path) = $item;
983 $name = $package->getName();
984 $packages[$name] = $package;
985 $paths[$name] = $path;
986
987 foreach (array_merge($package->getRequires(), $package->getDevRequires()) as $link) {
988 $target = $link->getTarget();
989 $usageList[$target][] = $name;
990 }
991 }
992
993 $computing = array();
994 $computed = array();
995 $computeImportance = function ($name) use (&$computeImportance, &$computing, &$computed, $usageList) {
996
997  if (isset($computed[$name])) {
998 return $computed[$name];
999 }
1000
1001
1002  if (isset($computing[$name])) {
1003 return 0;
1004 }
1005
1006 $computing[$name] = true;
1007 $weight = 0;
1008
1009 if (isset($usageList[$name])) {
1010 foreach ($usageList[$name] as $user) {
1011 $weight -= 1 - $computeImportance($user);
1012 }
1013 }
1014
1015 unset($computing[$name]);
1016 $computed[$name] = $weight;
1017
1018 return $weight;
1019 };
1020
1021 $weightList = array();
1022
1023 foreach ($packages as $name => $package) {
1024 $weight = $computeImportance($name);
1025 $weightList[$name] = $weight;
1026 }
1027
1028 $stable_sort = function (&$array) {
1029 static $transform, $restore;
1030
1031 $i = 0;
1032
1033 if (!$transform) {
1034 $transform = function (&$v, $k) use (&$i) {
1035 $v = array($v, ++$i, $k, $v);
1036 };
1037
1038 $restore = function (&$v, $k) {
1039 $v = $v[3];
1040 };
1041 }
1042
1043 array_walk($array, $transform);
1044 asort($array);
1045 array_walk($array, $restore);
1046 };
1047
1048 $stable_sort($weightList);
1049
1050 $sortedPackageMap = array();
1051
1052 foreach (array_keys($weightList) as $name) {
1053 $sortedPackageMap[] = array($packages[$name], $paths[$name]);
1054 }
1055
1056 return $sortedPackageMap;
1057 }
1058
1059
1060
1061
1062
1063
1064
1065 protected function safeCopy($source, $target)
1066 {
1067 $source = fopen($source, 'r');
1068 $target = fopen($target, 'w+');
1069
1070 stream_copy_to_stream($source, $target);
1071 fclose($source);
1072 fclose($target);
1073 }
1074 }
1075 <?php
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093 namespace Composer\Autoload;
1094
1095 use Symfony\Component\Finder\Finder;
1096 use Composer\IO\IOInterface;
1097 use Composer\Util\Filesystem;
1098
1099
1100
1101
1102
1103
1104
1105 class ClassMapGenerator
1106 {
1107
1108
1109
1110
1111
1112
1113 public static function dump($dirs, $file)
1114 {
1115 $maps = array();
1116
1117 foreach ($dirs as $dir) {
1118 $maps = array_merge($maps, static::createMap($dir));
1119 }
1120
1121 file_put_contents($file, sprintf('<?php return %s;', var_export($maps, true)));
1122 }
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135 public static function createMap($path, $blacklist = null, IOInterface $io = null, $namespace = null)
1136 {
1137 if (is_string($path)) {
1138 if (is_file($path)) {
1139 $path = array(new \SplFileInfo($path));
1140 } elseif (is_dir($path)) {
1141 $path = Finder::create()->files()->followLinks()->name('/\.(php|inc|hh)$/')->in($path);
1142 } else {
1143 throw new \RuntimeException(
1144 'Could not scan for classes inside "'.$path.
1145 '" which does not appear to be a file nor a folder'
1146 );
1147 }
1148 }
1149
1150 $map = array();
1151 $filesystem = new Filesystem();
1152 $cwd = realpath(getcwd());
1153
1154 foreach ($path as $file) {
1155 $filePath = $file->getPathname();
1156 if (!in_array(pathinfo($filePath, PATHINFO_EXTENSION), array('php', 'inc', 'hh'))) {
1157 continue;
1158 }
1159
1160 if (!$filesystem->isAbsolutePath($filePath)) {
1161 $filePath = $cwd . '/' . $filePath;
1162 $filePath = $filesystem->normalizePath($filePath);
1163 } else {
1164 $filePath = preg_replace('{[\\\\/]{2,}}', '/', $filePath);
1165 }
1166
1167
1168  if ($blacklist && preg_match($blacklist, strtr(realpath($filePath), '\\', '/'))) {
1169 continue;
1170 }
1171
1172 $classes = self::findClasses($filePath);
1173
1174 foreach ($classes as $class) {
1175
1176  if (null !== $namespace && 0 !== strpos($class, $namespace)) {
1177 continue;
1178 }
1179
1180 if (!isset($map[$class])) {
1181 $map[$class] = $filePath;
1182 } elseif ($io && $map[$class] !== $filePath && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($map[$class].' '.$filePath, '\\', '/'))) {
1183 $io->writeError(
1184 '<warning>Warning: Ambiguous class resolution, "'.$class.'"'.
1185 ' was found in both "'.$map[$class].'" and "'.$filePath.'", the first will be used.</warning>'
1186 );
1187 }
1188 }
1189 }
1190
1191 return $map;
1192 }
1193
1194
1195
1196
1197
1198
1199
1200
1201 private static function findClasses($path)
1202 {
1203 $extraTypes = PHP_VERSION_ID < 50400 ? '' : '|trait';
1204 if (defined('HHVM_VERSION') && version_compare(HHVM_VERSION, '3.3', '>=')) {
1205 $extraTypes .= '|enum';
1206 }
1207
1208
1209  
1210  $contents = @php_strip_whitespace($path);
1211 if (!$contents) {
1212 if (!file_exists($path)) {
1213 $message = 'File at "%s" does not exist, check your classmap definitions';
1214 } elseif (!is_readable($path)) {
1215 $message = 'File at "%s" is not readable, check its permissions';
1216 } elseif ('' === trim(file_get_contents($path))) {
1217
1218  return array();
1219 } else {
1220 $message = 'File at "%s" could not be parsed as PHP, it may be binary or corrupted';
1221 }
1222 $error = error_get_last();
1223 if (isset($error['message'])) {
1224 $message .= PHP_EOL . 'The following message may be helpful:' . PHP_EOL . $error['message'];
1225 }
1226 throw new \RuntimeException(sprintf($message, $path));
1227 }
1228
1229
1230  if (!preg_match('{\b(?:class|interface'.$extraTypes.')\s}i', $contents)) {
1231 return array();
1232 }
1233
1234
1235  $contents = preg_replace('{<<<\s*(\'?)(\w+)\\1(?:\r\n|\n|\r)(?:.*?)(?:\r\n|\n|\r)\\2(?=\r\n|\n|\r|;)}s', 'null', $contents);
1236
1237  $contents = preg_replace('{"[^"\\\\]*+(\\\\.[^"\\\\]*+)*+"|\'[^\'\\\\]*+(\\\\.[^\'\\\\]*+)*+\'}s', 'null', $contents);
1238
1239  if (substr($contents, 0, 2) !== '<?') {
1240 $contents = preg_replace('{^.+?<\?}s', '<?', $contents, 1, $replacements);
1241 if ($replacements === 0) {
1242 return array();
1243 }
1244 }
1245
1246  $contents = preg_replace('{\?>.+<\?}s', '?><?', $contents);
1247
1248  $pos = strrpos($contents, '?>');
1249 if (false !== $pos && false === strpos(substr($contents, $pos), '<?')) {
1250 $contents = substr($contents, 0, $pos);
1251 }
1252
1253 preg_match_all('{
1254             (?:
1255                  \b(?<![\$:>])(?P<type>class|interface'.$extraTypes.') \s++ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
1256                | \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*+ [\{;]
1257             )
1258         }ix', $contents, $matches);
1259
1260 $classes = array();
1261 $namespace = '';
1262
1263 for ($i = 0, $len = count($matches['type']); $i < $len; $i++) {
1264 if (!empty($matches['ns'][$i])) {
1265 $namespace = str_replace(array(' ', "\t", "\r", "\n"), '', $matches['nsname'][$i]) . '\\';
1266 } else {
1267 $name = $matches['name'][$i];
1268
1269  if ($name === 'extends' || $name === 'implements') {
1270 continue;
1271 }
1272 if ($name[0] === ':') {
1273
1274  $name = 'xhp'.substr(str_replace(array('-', ':'), array('_', '__'), $name), 1);
1275 } elseif ($matches['type'][$i] === 'enum') {
1276
1277  
1278  
1279  
1280  $name = rtrim($name, ':');
1281 }
1282 $classes[] = ltrim($namespace . $name, '\\');
1283 }
1284 }
1285
1286 return $classes;
1287 }
1288 }
1289 <?php
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301 namespace Composer;
1302
1303 use Composer\IO\IOInterface;
1304 use Composer\Util\Filesystem;
1305 use Composer\Util\Silencer;
1306 use Symfony\Component\Finder\Finder;
1307
1308
1309
1310
1311
1312
1313 class Cache
1314 {
1315 private static $cacheCollected = false;
1316 private $io;
1317 private $root;
1318 private $enabled = true;
1319 private $whitelist;
1320 private $filesystem;
1321
1322
1323
1324
1325
1326
1327
1328 public function __construct(IOInterface $io, $cacheDir, $whitelist = 'a-z0-9.', Filesystem $filesystem = null)
1329 {
1330 $this->io = $io;
1331 $this->root = rtrim($cacheDir, '/\\') . '/';
1332 $this->whitelist = $whitelist;
1333 $this->filesystem = $filesystem ?: new Filesystem();
1334
1335 if (preg_match('{(^|[\\\\/])(\$null|NUL|/dev/null)([\\\\/]|$)}', $cacheDir)) {
1336 $this->enabled = false;
1337
1338 return;
1339 }
1340
1341 if (
1342 (!is_dir($this->root) && !Silencer::call('mkdir', $this->root, 0777, true))
1343 || !is_writable($this->root)
1344 ) {
1345 $this->io->writeError('<warning>Cannot create cache directory ' . $this->root . ', or directory is not writable. Proceeding without cache</warning>');
1346 $this->enabled = false;
1347 }
1348 }
1349
1350 public function isEnabled()
1351 {
1352 return $this->enabled;
1353 }
1354
1355 public function getRoot()
1356 {
1357 return $this->root;
1358 }
1359
1360 public function read($file)
1361 {
1362 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1363 if ($this->enabled && file_exists($this->root . $file)) {
1364 $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
1365
1366 return file_get_contents($this->root . $file);
1367 }
1368
1369 return false;
1370 }
1371
1372 public function write($file, $contents)
1373 {
1374 if ($this->enabled) {
1375 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1376
1377 $this->io->writeError('Writing '.$this->root . $file.' into cache', true, IOInterface::DEBUG);
1378
1379 try {
1380 return file_put_contents($this->root . $file, $contents);
1381 } catch (\ErrorException $e) {
1382 $this->io->writeError('<warning>Failed to write into cache: '.$e->getMessage().'</warning>', true, IOInterface::DEBUG);
1383 if (preg_match('{^file_put_contents\(\): Only ([0-9]+) of ([0-9]+) bytes written}', $e->getMessage(), $m)) {
1384
1385  unlink($this->root . $file);
1386
1387 $message = sprintf(
1388 '<warning>Writing %1$s into cache failed after %2$u of %3$u bytes written, only %4$u bytes of free space available</warning>',
1389 $this->root . $file,
1390 $m[1],
1391 $m[2],
1392 @disk_free_space($this->root . dirname($file))
1393 );
1394
1395 $this->io->writeError($message);
1396
1397 return false;
1398 }
1399
1400 throw $e;
1401 }
1402 }
1403
1404 return false;
1405 }
1406
1407
1408
1409
1410 public function copyFrom($file, $source)
1411 {
1412 if ($this->enabled) {
1413 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1414 $this->filesystem->ensureDirectoryExists(dirname($this->root . $file));
1415
1416 if (!file_exists($source)) {
1417 $this->io->writeError('<error>'.$source.' does not exist, can not write into cache</error>');
1418 } elseif ($this->io->isDebug()) {
1419 $this->io->writeError('Writing '.$this->root . $file.' into cache from '.$source);
1420 }
1421
1422 return copy($source, $this->root . $file);
1423 }
1424
1425 return false;
1426 }
1427
1428
1429
1430
1431 public function copyTo($file, $target)
1432 {
1433 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1434 if ($this->enabled && file_exists($this->root . $file)) {
1435 try {
1436 touch($this->root . $file, filemtime($this->root . $file), time());
1437 } catch (\ErrorException $e) {
1438
1439  
1440  Silencer::call('touch', $this->root . $file);
1441 }
1442
1443 $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG);
1444
1445 return copy($this->root . $file, $target);
1446 }
1447
1448 return false;
1449 }
1450
1451 public function gcIsNecessary()
1452 {
1453 return (!self::$cacheCollected && !mt_rand(0, 50));
1454 }
1455
1456 public function remove($file)
1457 {
1458 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1459 if ($this->enabled && file_exists($this->root . $file)) {
1460 return $this->filesystem->unlink($this->root . $file);
1461 }
1462
1463 return false;
1464 }
1465
1466 public function clear()
1467 {
1468 if ($this->enabled) {
1469 return $this->filesystem->removeDirectory($this->root);
1470 }
1471
1472 return false;
1473 }
1474
1475 public function gc($ttl, $maxSize)
1476 {
1477 if ($this->enabled) {
1478 $expire = new \DateTime();
1479 $expire->modify('-'.$ttl.' seconds');
1480
1481 $finder = $this->getFinder()->date('until '.$expire->format('Y-m-d H:i:s'));
1482 foreach ($finder as $file) {
1483 $this->filesystem->unlink($file->getPathname());
1484 }
1485
1486 $totalSize = $this->filesystem->size($this->root);
1487 if ($totalSize > $maxSize) {
1488 $iterator = $this->getFinder()->sortByAccessedTime()->getIterator();
1489 while ($totalSize > $maxSize && $iterator->valid()) {
1490 $filepath = $iterator->current()->getPathname();
1491 $totalSize -= $this->filesystem->size($filepath);
1492 $this->filesystem->unlink($filepath);
1493 $iterator->next();
1494 }
1495 }
1496
1497 self::$cacheCollected = true;
1498
1499 return true;
1500 }
1501
1502 return false;
1503 }
1504
1505 public function sha1($file)
1506 {
1507 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1508 if ($this->enabled && file_exists($this->root . $file)) {
1509 return sha1_file($this->root . $file);
1510 }
1511
1512 return false;
1513 }
1514
1515 public function sha256($file)
1516 {
1517 $file = preg_replace('{[^'.$this->whitelist.']}i', '-', $file);
1518 if ($this->enabled && file_exists($this->root . $file)) {
1519 return hash_file('sha256', $this->root . $file);
1520 }
1521
1522 return false;
1523 }
1524
1525 protected function getFinder()
1526 {
1527 return Finder::create()->in($this->root)->files();
1528 }
1529 }
1530 <?php
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542 namespace Composer\Command;
1543
1544 use Symfony\Component\Console\Input\InputInterface;
1545 use Symfony\Component\Console\Output\OutputInterface;
1546
1547
1548
1549
1550 class AboutCommand extends BaseCommand
1551 {
1552 protected function configure()
1553 {
1554 $this
1555 ->setName('about')
1556 ->setDescription('Shows the short information about Composer.')
1557 ->setHelp(<<<EOT
1558 <info>php composer.phar about</info>
1559 EOT
1560 )
1561 ;
1562 }
1563
1564 protected function execute(InputInterface $input, OutputInterface $output)
1565 {
1566 $this->getIO()->write(<<<EOT
1567 <info>Composer - Package Management for PHP</info>
1568 <comment>Composer is a dependency manager tracking local dependencies of your projects and libraries.
1569 See https://getcomposer.org/ for more information.</comment>
1570 EOT
1571 );
1572 }
1573 }
1574 <?php
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586 namespace Composer\Command;
1587
1588 use Composer\Factory;
1589 use Composer\IO\IOInterface;
1590 use Composer\Config;
1591 use Composer\Composer;
1592 use Composer\Repository\CompositeRepository;
1593 use Composer\Repository\RepositoryFactory;
1594 use Composer\Script\ScriptEvents;
1595 use Composer\Plugin\CommandEvent;
1596 use Composer\Plugin\PluginEvents;
1597 use Composer\Util\Filesystem;
1598 use Symfony\Component\Console\Input\InputArgument;
1599 use Symfony\Component\Console\Input\InputInterface;
1600 use Symfony\Component\Console\Input\InputOption;
1601 use Symfony\Component\Console\Output\OutputInterface;
1602
1603
1604
1605
1606
1607
1608 class ArchiveCommand extends BaseCommand
1609 {
1610 protected function configure()
1611 {
1612 $this
1613 ->setName('archive')
1614 ->setDescription('Creates an archive of this composer package.')
1615 ->setDefinition(array(
1616 new InputArgument('package', InputArgument::OPTIONAL, 'The package to archive instead of the current project'),
1617 new InputArgument('version', InputArgument::OPTIONAL, 'A version constraint to find the package to archive'),
1618 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the resulting archive: tar or zip'),
1619 new InputOption('dir', null, InputOption::VALUE_REQUIRED, 'Write the archive to this directory'),
1620 new InputOption('file', null, InputOption::VALUE_REQUIRED, 'Write the archive with the given file name.'
1621 .' Note that the format will be appended.'),
1622 new InputOption('ignore-filters', false, InputOption::VALUE_NONE, 'Ignore filters when saving package'),
1623 ))
1624 ->setHelp(<<<EOT
1625 The <info>archive</info> command creates an archive of the specified format
1626 containing the files and directories of the Composer project or the specified
1627 package in the specified version and writes it to the specified directory.
1628
1629 <info>php composer.phar archive [--format=zip] [--dir=/foo] [package [version]]</info>
1630
1631 EOT
1632 )
1633 ;
1634 }
1635
1636 protected function execute(InputInterface $input, OutputInterface $output)
1637 {
1638 $config = Factory::createConfig();
1639 $composer = $this->getComposer(false);
1640 if ($composer) {
1641 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'archive', $input, $output);
1642 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
1643 $composer->getEventDispatcher()->dispatchScript(ScriptEvents::PRE_ARCHIVE_CMD);
1644 }
1645
1646 if (null === $input->getOption('format')) {
1647 $input->setOption('format', $config->get('archive-format'));
1648 }
1649 if (null === $input->getOption('dir')) {
1650 $input->setOption('dir', $config->get('archive-dir'));
1651 }
1652
1653 $returnCode = $this->archive(
1654 $this->getIO(),
1655 $config,
1656 $input->getArgument('package'),
1657 $input->getArgument('version'),
1658 $input->getOption('format'),
1659 $input->getOption('dir'),
1660 $input->getOption('file'),
1661 $input->getOption('ignore-filters'),
1662 $composer
1663 );
1664
1665 if (0 === $returnCode && $composer) {
1666 $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ARCHIVE_CMD);
1667 }
1668
1669 return $returnCode;
1670 }
1671
1672 protected function archive(IOInterface $io, Config $config, $packageName = null, $version = null, $format = 'tar', $dest = '.', $fileName = null, $ignoreFilters = false, Composer $composer = null)
1673 {
1674 if ($composer) {
1675 $archiveManager = $composer->getArchiveManager();
1676 } else {
1677 $factory = new Factory;
1678 $downloadManager = $factory->createDownloadManager($io, $config);
1679 $archiveManager = $factory->createArchiveManager($config, $downloadManager);
1680 }
1681
1682 if ($packageName) {
1683 $package = $this->selectPackage($io, $packageName, $version);
1684
1685 if (!$package) {
1686 return 1;
1687 }
1688 } else {
1689 $package = $this->getComposer()->getPackage();
1690 }
1691
1692 $io->writeError('<info>Creating the archive into "'.$dest.'".</info>');
1693 $packagePath = $archiveManager->archive($package, $format, $dest, $fileName, $ignoreFilters);
1694 $fs = new Filesystem;
1695 $shortPath = $fs->findShortestPath(getcwd(), $packagePath, true);
1696
1697 $io->writeError('Created: ', false);
1698 $io->write(strlen($shortPath) < strlen($packagePath) ? $shortPath : $packagePath);
1699
1700 return 0;
1701 }
1702
1703 protected function selectPackage(IOInterface $io, $packageName, $version = null)
1704 {
1705 $io->writeError('<info>Searching for the specified package.</info>');
1706
1707 if ($composer = $this->getComposer(false)) {
1708 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
1709 $repo = new CompositeRepository(array_merge(array($localRepo), $composer->getRepositoryManager()->getRepositories()));
1710 } else {
1711 $defaultRepos = RepositoryFactory::defaultRepos($this->getIO());
1712 $io->writeError('No composer.json found in the current directory, searching packages from ' . implode(', ', array_keys($defaultRepos)));
1713 $repo = new CompositeRepository($defaultRepos);
1714 }
1715
1716 $packages = $repo->findPackages($packageName, $version);
1717
1718 if (count($packages) > 1) {
1719 $package = reset($packages);
1720 $io->writeError('<info>Found multiple matches, selected '.$package->getPrettyString().'.</info>');
1721 $io->writeError('Alternatives were '.implode(', ', array_map(function ($p) {
1722 return $p->getPrettyString();
1723 }, $packages)).'.');
1724 $io->writeError('<comment>Please use a more specific constraint to pick a different package.</comment>');
1725 } elseif ($packages) {
1726 $package = reset($packages);
1727 $io->writeError('<info>Found an exact match '.$package->getPrettyString().'.</info>');
1728 } else {
1729 $io->writeError('<error>Could not find a package matching '.$packageName.'.</error>');
1730
1731 return false;
1732 }
1733
1734 return $package;
1735 }
1736 }
1737 <?php
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749 namespace Composer\Command;
1750
1751 use Composer\Composer;
1752 use Composer\Config;
1753 use Composer\Console\Application;
1754 use Composer\IO\IOInterface;
1755 use Composer\IO\NullIO;
1756 use Symfony\Component\Console\Input\InputInterface;
1757 use Symfony\Component\Console\Output\OutputInterface;
1758 use Symfony\Component\Console\Command\Command;
1759
1760
1761
1762
1763
1764
1765
1766 abstract class BaseCommand extends Command
1767 {
1768
1769
1770
1771 private $composer;
1772
1773
1774
1775
1776 private $io;
1777
1778
1779
1780
1781
1782
1783
1784 public function getComposer($required = true, $disablePlugins = null)
1785 {
1786 if (null === $this->composer) {
1787 $application = $this->getApplication();
1788 if ($application instanceof Application) {
1789
1790 $this->composer = $application->getComposer($required, $disablePlugins);
1791 } elseif ($required) {
1792 throw new \RuntimeException(
1793 'Could not create a Composer\Composer instance, you must inject '.
1794 'one if this command is not used with a Composer\Console\Application instance'
1795 );
1796 }
1797 }
1798
1799 return $this->composer;
1800 }
1801
1802
1803
1804
1805 public function setComposer(Composer $composer)
1806 {
1807 $this->composer = $composer;
1808 }
1809
1810
1811
1812
1813 public function resetComposer()
1814 {
1815 $this->composer = null;
1816 $this->getApplication()->resetComposer();
1817 }
1818
1819
1820
1821
1822
1823
1824
1825
1826 public function isProxyCommand()
1827 {
1828 return false;
1829 }
1830
1831
1832
1833
1834 public function getIO()
1835 {
1836 if (null === $this->io) {
1837 $application = $this->getApplication();
1838 if ($application instanceof Application) {
1839
1840 $this->io = $application->getIO();
1841 } else {
1842 $this->io = new NullIO();
1843 }
1844 }
1845
1846 return $this->io;
1847 }
1848
1849
1850
1851
1852 public function setIO(IOInterface $io)
1853 {
1854 $this->io = $io;
1855 }
1856
1857
1858
1859
1860 protected function initialize(InputInterface $input, OutputInterface $output)
1861 {
1862 if (true === $input->hasParameterOption(array('--no-ansi')) && $input->hasOption('no-progress')) {
1863 $input->setOption('no-progress', true);
1864 }
1865
1866 parent::initialize($input, $output);
1867 }
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878 protected function getPreferredInstallOptions(Config $config, InputInterface $input, $keepVcsRequiresPreferSource = false)
1879 {
1880 $preferSource = false;
1881 $preferDist = false;
1882
1883 switch ($config->get('preferred-install')) {
1884 case 'source':
1885 $preferSource = true;
1886 break;
1887 case 'dist':
1888 $preferDist = true;
1889 break;
1890 case 'auto':
1891 default:
1892
1893  break;
1894 }
1895
1896 if ($input->getOption('prefer-source') || $input->getOption('prefer-dist') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'))) {
1897 $preferSource = $input->getOption('prefer-source') || ($keepVcsRequiresPreferSource && $input->hasOption('keep-vcs') && $input->getOption('keep-vcs'));
1898 $preferDist = $input->getOption('prefer-dist');
1899 }
1900
1901 return array($preferSource, $preferDist);
1902 }
1903 }
1904 <?php
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916 namespace Composer\Command;
1917
1918 use Composer\DependencyResolver\Pool;
1919 use Composer\Package\Link;
1920 use Composer\Package\PackageInterface;
1921 use Composer\Repository\ArrayRepository;
1922 use Composer\Repository\CompositeRepository;
1923 use Composer\Repository\PlatformRepository;
1924 use Composer\Repository\RepositoryFactory;
1925 use Composer\Plugin\CommandEvent;
1926 use Composer\Plugin\PluginEvents;
1927 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
1928 use Composer\Package\Version\VersionParser;
1929 use Symfony\Component\Console\Helper\Table;
1930 use Symfony\Component\Console\Input\InputArgument;
1931 use Symfony\Component\Console\Input\InputInterface;
1932 use Symfony\Component\Console\Input\InputOption;
1933 use Symfony\Component\Console\Output\OutputInterface;
1934
1935
1936
1937
1938
1939
1940 class BaseDependencyCommand extends BaseCommand
1941 {
1942 const ARGUMENT_PACKAGE = 'package';
1943 const ARGUMENT_CONSTRAINT = 'constraint';
1944 const OPTION_RECURSIVE = 'recursive';
1945 const OPTION_TREE = 'tree';
1946
1947 protected $colors;
1948
1949
1950
1951
1952 protected function configure()
1953 {
1954 $this->setDefinition(array(
1955 new InputArgument(self::ARGUMENT_PACKAGE, InputArgument::REQUIRED, 'Package to inspect'),
1956 new InputArgument(self::ARGUMENT_CONSTRAINT, InputArgument::OPTIONAL, 'Optional version constraint', '*'),
1957 new InputOption(self::OPTION_RECURSIVE, 'r', InputOption::VALUE_NONE, 'Recursively resolves up to the root package'),
1958 new InputOption(self::OPTION_TREE, 't', InputOption::VALUE_NONE, 'Prints the results as a nested tree'),
1959 ));
1960 }
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970 protected function doExecute(InputInterface $input, OutputInterface $output, $inverted = false)
1971 {
1972
1973  $composer = $this->getComposer();
1974 $commandEvent = new CommandEvent(PluginEvents::COMMAND, $this->getName(), $input, $output);
1975 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
1976
1977
1978  $platformOverrides = $composer->getConfig()->get('platform') ?: array();
1979 $repository = new CompositeRepository(array(
1980 new ArrayRepository(array($composer->getPackage())),
1981 $composer->getRepositoryManager()->getLocalRepository(),
1982 new PlatformRepository(array(), $platformOverrides),
1983 ));
1984 $pool = new Pool();
1985 $pool->addRepository($repository);
1986
1987
1988  list($needle, $textConstraint) = array_pad(
1989 explode(':', $input->getArgument(self::ARGUMENT_PACKAGE)),
1990 2,
1991 $input->getArgument(self::ARGUMENT_CONSTRAINT)
1992 );
1993
1994
1995  $packages = $pool->whatProvides($needle);
1996 if (empty($packages)) {
1997 throw new \InvalidArgumentException(sprintf('Could not find package "%s" in your project', $needle));
1998 }
1999
2000
2001  
2002  if (!$repository->findPackage($needle, $textConstraint)) {
2003 $defaultRepos = new CompositeRepository(RepositoryFactory::defaultRepos($this->getIO()));
2004 if ($match = $defaultRepos->findPackage($needle, $textConstraint)) {
2005 $repository->addRepository(new ArrayRepository(array(clone $match)));
2006 }
2007 }
2008
2009
2010  $needles = array($needle);
2011 if ($inverted) {
2012 foreach ($packages as $package) {
2013 $needles = array_merge($needles, array_map(function (Link $link) {
2014 return $link->getTarget();
2015 }, $package->getReplaces()));
2016 }
2017 }
2018
2019
2020  if ('*' !== $textConstraint) {
2021 $versionParser = new VersionParser();
2022 $constraint = $versionParser->parseConstraints($textConstraint);
2023 } else {
2024 $constraint = null;
2025 }
2026
2027
2028  $renderTree = $input->getOption(self::OPTION_TREE);
2029 $recursive = $renderTree || $input->getOption(self::OPTION_RECURSIVE);
2030
2031
2032  $results = $repository->getDependents($needles, $constraint, $inverted, $recursive);
2033 if (empty($results)) {
2034 $extra = (null !== $constraint) ? sprintf(' in versions %smatching %s', $inverted ? 'not ' : '', $textConstraint) : '';
2035 $this->getIO()->writeError(sprintf('<info>There is no installed package depending on "%s"%s</info>',
2036 $needle, $extra));
2037 } elseif ($renderTree) {
2038 $this->initStyles($output);
2039 $root = $packages[0];
2040 $this->getIO()->write(sprintf('<info>%s</info> %s %s', $root->getPrettyName(), $root->getPrettyVersion(), $root->getDescription()));
2041 $this->printTree($results);
2042 } else {
2043 $this->printTable($output, $results);
2044 }
2045
2046 return 0;
2047 }
2048
2049
2050
2051
2052
2053
2054
2055 protected function printTable(OutputInterface $output, $results)
2056 {
2057 $table = array();
2058 $doubles = array();
2059 do {
2060 $queue = array();
2061 $rows = array();
2062 foreach ($results as $result) {
2063
2064
2065
2066
2067 list($package, $link, $children) = $result;
2068 $unique = (string) $link;
2069 if (isset($doubles[$unique])) {
2070 continue;
2071 }
2072 $doubles[$unique] = true;
2073 $version = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '-' : $package->getPrettyVersion();
2074 $rows[] = array($package->getPrettyName(), $version, $link->getDescription(), sprintf('%s (%s)', $link->getTarget(), $link->getPrettyConstraint()));
2075 if ($children) {
2076 $queue = array_merge($queue, $children);
2077 }
2078 }
2079 $results = $queue;
2080 $table = array_merge($rows, $table);
2081 } while (!empty($results));
2082
2083
2084  $renderer = new Table($output);
2085 $renderer->setStyle('compact');
2086 $renderer->getStyle()->setVerticalBorderChar('');
2087 $renderer->getStyle()->setCellRowContentFormat('%s  ');
2088 $renderer->setRows($table)->render();
2089 }
2090
2091
2092
2093
2094
2095
2096 protected function initStyles(OutputInterface $output)
2097 {
2098 $this->colors = array(
2099 'green',
2100 'yellow',
2101 'cyan',
2102 'magenta',
2103 'blue',
2104 );
2105
2106 foreach ($this->colors as $color) {
2107 $style = new OutputFormatterStyle($color);
2108 $output->getFormatter()->setStyle($color, $style);
2109 }
2110 }
2111
2112
2113
2114
2115
2116
2117
2118
2119 protected function printTree($results, $prefix = '', $level = 1)
2120 {
2121 $count = count($results);
2122 $idx = 0;
2123 foreach ($results as $result) {
2124
2125
2126
2127
2128
2129 list($package, $link, $children) = $result;
2130
2131 $color = $this->colors[$level % count($this->colors)];
2132 $prevColor = $this->colors[($level - 1) % count($this->colors)];
2133 $isLast = (++$idx == $count);
2134 $versionText = (strpos($package->getPrettyVersion(), 'No version set') === 0) ? '' : $package->getPrettyVersion();
2135 $packageText = rtrim(sprintf('<%s>%s</%1$s> %s', $color, $package->getPrettyName(), $versionText));
2136 $linkText = sprintf('%s <%s>%s</%2$s> %s', $link->getDescription(), $prevColor, $link->getTarget(), $link->getPrettyConstraint());
2137 $circularWarn = $children === false ? '(circular dependency aborted here)' : '';
2138 $this->writeTreeLine(rtrim(sprintf("%s%s%s (%s) %s", $prefix, $isLast ? '└──' : '├──', $packageText, $linkText, $circularWarn)));
2139 if ($children) {
2140 $this->printTree($children, $prefix . ($isLast ? '   ' : '│  '), $level + 1);
2141 }
2142 }
2143 }
2144
2145 private function writeTreeLine($line)
2146 {
2147 $io = $this->getIO();
2148 if (!$io->isDecorated()) {
2149 $line = str_replace(array('└', '├', '──', '│'), array('`-', '|-', '-', '|'), $line);
2150 }
2151
2152 $io->write($line);
2153 }
2154 }
2155 <?php
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167 namespace Composer\Command;
2168
2169 use Composer\Cache;
2170 use Composer\Factory;
2171 use Symfony\Component\Console\Input\InputInterface;
2172 use Symfony\Component\Console\Output\OutputInterface;
2173
2174
2175
2176
2177 class ClearCacheCommand extends BaseCommand
2178 {
2179 protected function configure()
2180 {
2181 $this
2182 ->setName('clear-cache')
2183 ->setAliases(array('clearcache'))
2184 ->setDescription('Clears composer\'s internal package cache.')
2185 ->setHelp(<<<EOT
2186 The <info>clear-cache</info> deletes all cached packages from composer's
2187 cache directory.
2188 EOT
2189 )
2190 ;
2191 }
2192
2193 protected function execute(InputInterface $input, OutputInterface $output)
2194 {
2195 $config = Factory::createConfig();
2196 $io = $this->getIO();
2197
2198 $cachePaths = array(
2199 'cache-vcs-dir' => $config->get('cache-vcs-dir'),
2200 'cache-repo-dir' => $config->get('cache-repo-dir'),
2201 'cache-files-dir' => $config->get('cache-files-dir'),
2202 'cache-dir' => $config->get('cache-dir'),
2203 );
2204
2205 foreach ($cachePaths as $key => $cachePath) {
2206 $cachePath = realpath($cachePath);
2207 if (!$cachePath) {
2208 $io->writeError("<info>Cache directory does not exist ($key): $cachePath</info>");
2209
2210 continue;
2211 }
2212 $cache = new Cache($io, $cachePath);
2213 if (!$cache->isEnabled()) {
2214 $io->writeError("<info>Cache is not enabled ($key): $cachePath</info>");
2215
2216 continue;
2217 }
2218
2219 $io->writeError("<info>Clearing cache ($key): $cachePath</info>");
2220 $cache->clear();
2221 }
2222
2223 $io->writeError('<info>All caches cleared.</info>');
2224 }
2225 }
2226 <?php
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238 namespace Composer\Command;
2239
2240 use Composer\Util\Platform;
2241 use Composer\Util\Silencer;
2242 use Symfony\Component\Console\Input\InputInterface;
2243 use Symfony\Component\Console\Input\InputArgument;
2244 use Symfony\Component\Console\Input\InputOption;
2245 use Symfony\Component\Console\Output\OutputInterface;
2246 use Composer\Config;
2247 use Composer\Config\JsonConfigSource;
2248 use Composer\Factory;
2249 use Composer\Json\JsonFile;
2250 use Composer\Semver\VersionParser;
2251 use Composer\Package\BasePackage;
2252
2253
2254
2255
2256
2257 class ConfigCommand extends BaseCommand
2258 {
2259
2260
2261
2262 protected $config;
2263
2264
2265
2266
2267 protected $configFile;
2268
2269
2270
2271
2272 protected $configSource;
2273
2274
2275
2276
2277 protected $authConfigFile;
2278
2279
2280
2281
2282 protected $authConfigSource;
2283
2284
2285
2286
2287 protected function configure()
2288 {
2289 $this
2290 ->setName('config')
2291 ->setDescription('Sets config options.')
2292 ->setDefinition(array(
2293 new InputOption('global', 'g', InputOption::VALUE_NONE, 'Apply command to the global config file'),
2294 new InputOption('editor', 'e', InputOption::VALUE_NONE, 'Open editor'),
2295 new InputOption('auth', 'a', InputOption::VALUE_NONE, 'Affect auth config file (only used for --editor)'),
2296 new InputOption('unset', null, InputOption::VALUE_NONE, 'Unset the given setting-key'),
2297 new InputOption('list', 'l', InputOption::VALUE_NONE, 'List configuration settings'),
2298 new InputOption('file', 'f', InputOption::VALUE_REQUIRED, 'If you want to choose a different composer.json or config.json'),
2299 new InputOption('absolute', null, InputOption::VALUE_NONE, 'Returns absolute paths when fetching *-dir config values instead of relative'),
2300 new InputArgument('setting-key', null, 'Setting key'),
2301 new InputArgument('setting-value', InputArgument::IS_ARRAY, 'Setting value'),
2302 ))
2303 ->setHelp(<<<EOT
2304 This command allows you to edit composer config settings and repositories
2305 in either the local composer.json file or the global config.json file.
2306
2307 Additionally it lets you edit most properties in the local composer.json.
2308
2309 To set a config setting:
2310
2311     <comment>%command.full_name% bin-dir bin/</comment>
2312
2313 To read a config setting:
2314
2315     <comment>%command.full_name% bin-dir</comment>
2316     Outputs: <info>bin</info>
2317
2318 To edit the global config.json file:
2319
2320     <comment>%command.full_name% --global</comment>
2321
2322 To add a repository:
2323
2324     <comment>%command.full_name% repositories.foo vcs https://bar.com</comment>
2325
2326 To remove a repository (repo is a short alias for repositories):
2327
2328     <comment>%command.full_name% --unset repo.foo</comment>
2329
2330 To disable packagist:
2331
2332     <comment>%command.full_name% repo.packagist false</comment>
2333
2334 You can alter repositories in the global config.json file by passing in the
2335 <info>--global</info> option.
2336
2337 To edit the file in an external editor:
2338
2339     <comment>%command.full_name% --editor</comment>
2340
2341 To choose your editor you can set the "EDITOR" env variable.
2342
2343 To get a list of configuration values in the file:
2344
2345     <comment>%command.full_name% --list</comment>
2346
2347 You can always pass more than one option. As an example, if you want to edit the
2348 global config.json file.
2349
2350     <comment>%command.full_name% --editor --global</comment>
2351 EOT
2352 )
2353 ;
2354 }
2355
2356
2357
2358
2359 protected function initialize(InputInterface $input, OutputInterface $output)
2360 {
2361 parent::initialize($input, $output);
2362
2363 if ($input->getOption('global') && null !== $input->getOption('file')) {
2364 throw new \RuntimeException('--file and --global can not be combined');
2365 }
2366
2367 $io = $this->getIO();
2368 $this->config = Factory::createConfig($io);
2369
2370
2371  
2372  $configFile = $input->getOption('global')
2373 ? ($this->config->get('home') . '/config.json')
2374 : ($input->getOption('file') ?: Factory::getComposerFile());
2375
2376
2377  if (
2378 ($configFile === 'composer.json' || $configFile === './composer.json')
2379 && !file_exists($configFile)
2380 && realpath(getcwd()) === realpath($this->config->get('home'))
2381 ) {
2382 file_put_contents($configFile, "{\n}\n");
2383 }
2384
2385 $this->configFile = new JsonFile($configFile, null, $io);
2386 $this->configSource = new JsonConfigSource($this->configFile);
2387
2388 $authConfigFile = $input->getOption('global')
2389 ? ($this->config->get('home') . '/auth.json')
2390 : dirname(realpath($configFile)) . '/auth.json';
2391
2392 $this->authConfigFile = new JsonFile($authConfigFile, null, $io);
2393 $this->authConfigSource = new JsonConfigSource($this->authConfigFile, true);
2394
2395
2396  if ($input->getOption('global') && !$this->configFile->exists()) {
2397 touch($this->configFile->getPath());
2398 $this->configFile->write(array('config' => new \ArrayObject));
2399 Silencer::call('chmod', $this->configFile->getPath(), 0600);
2400 }
2401 if ($input->getOption('global') && !$this->authConfigFile->exists()) {
2402 touch($this->authConfigFile->getPath());
2403 $this->authConfigFile->write(array('bitbucket-oauth' => new \ArrayObject, 'github-oauth' => new \ArrayObject, 'gitlab-oauth' => new \ArrayObject, 'gitlab-token' => new \ArrayObject, 'http-basic' => new \ArrayObject));
2404 Silencer::call('chmod', $this->authConfigFile->getPath(), 0600);
2405 }
2406
2407 if (!$this->configFile->exists()) {
2408 throw new \RuntimeException(sprintf('File "%s" cannot be found in the current directory', $configFile));
2409 }
2410 }
2411
2412
2413
2414
2415 protected function execute(InputInterface $input, OutputInterface $output)
2416 {
2417
2418  if ($input->getOption('editor')) {
2419 $editor = escapeshellcmd(getenv('EDITOR'));
2420 if (!$editor) {
2421 if (Platform::isWindows()) {
2422 $editor = 'notepad';
2423 } else {
2424 foreach (array('editor', 'vim', 'vi', 'nano', 'pico', 'ed') as $candidate) {
2425 if (exec('which '.$candidate)) {
2426 $editor = $candidate;
2427 break;
2428 }
2429 }
2430 }
2431 }
2432
2433 $file = $input->getOption('auth') ? $this->authConfigFile->getPath() : $this->configFile->getPath();
2434 system($editor . ' ' . $file . (Platform::isWindows() ? '' : ' > `tty`'));
2435
2436 return 0;
2437 }
2438
2439 if (!$input->getOption('global')) {
2440 $this->config->merge($this->configFile->read());
2441 $this->config->merge(array('config' => $this->authConfigFile->exists() ? $this->authConfigFile->read() : array()));
2442 }
2443
2444
2445  if ($input->getOption('list')) {
2446 $this->listConfiguration($this->config->all(), $this->config->raw(), $output);
2447
2448 return 0;
2449 }
2450
2451 $settingKey = $input->getArgument('setting-key');
2452 if (!$settingKey) {
2453 return 0;
2454 }
2455
2456
2457  if (array() !== $input->getArgument('setting-value') && $input->getOption('unset')) {
2458 throw new \RuntimeException('You can not combine a setting value with --unset');
2459 }
2460
2461
2462  if (array() === $input->getArgument('setting-value') && !$input->getOption('unset')) {
2463 $properties = array('name', 'type', 'description', 'homepage', 'version', 'minimum-stability', 'prefer-stable', 'keywords', 'license', 'extra');
2464 $rawData = $this->configFile->read();
2465 $data = $this->config->all();
2466 if (preg_match('/^repos?(?:itories)?(?:\.(.+))?/', $settingKey, $matches)) {
2467 if (!isset($matches[1]) || $matches[1] === '') {
2468 $value = isset($data['repositories']) ? $data['repositories'] : array();
2469 } else {
2470 if (!isset($data['repositories'][$matches[1]])) {
2471 throw new \InvalidArgumentException('There is no '.$matches[1].' repository defined');
2472 }
2473
2474 $value = $data['repositories'][$matches[1]];
2475 }
2476 } elseif (strpos($settingKey, '.')) {
2477 $bits = explode('.', $settingKey);
2478 if ($bits[0] === 'extra') {
2479 $data = $rawData;
2480 } else {
2481 $data = $data['config'];
2482 }
2483 $match = false;
2484 foreach ($bits as $bit) {
2485 $key = isset($key) ? $key.'.'.$bit : $bit;
2486 $match = false;
2487 if (isset($data[$key])) {
2488 $match = true;
2489 $data = $data[$key];
2490 unset($key);
2491 }
2492 }
2493
2494 if (!$match) {
2495 throw new \RuntimeException($settingKey.' is not defined.');
2496 }
2497
2498 $value = $data;
2499 } elseif (isset($data['config'][$settingKey])) {
2500 $value = $this->config->get($settingKey, $input->getOption('absolute') ? 0 : Config::RELATIVE_PATHS);
2501 } elseif (in_array($settingKey, $properties, true) && isset($rawData[$settingKey])) {
2502 $value = $rawData[$settingKey];
2503 } else {
2504 throw new \RuntimeException($settingKey.' is not defined');
2505 }
2506
2507 if (is_array($value)) {
2508 $value = json_encode($value);
2509 }
2510
2511 $this->getIO()->write($value);
2512
2513 return 0;
2514 }
2515
2516 $values = $input->getArgument('setting-value'); 
2517
2518 $booleanValidator = function ($val) {
2519 return in_array($val, array('true', 'false', '1', '0'), true);
2520 };
2521 $booleanNormalizer = function ($val) {
2522 return $val !== 'false' && (bool) $val;
2523 };
2524
2525
2526  $uniqueConfigValues = array(
2527 'process-timeout' => array('is_numeric', 'intval'),
2528 'use-include-path' => array($booleanValidator, $booleanNormalizer),
2529 'preferred-install' => array(
2530 function ($val) {
2531 return in_array($val, array('auto', 'source', 'dist'), true);
2532 },
2533 function ($val) {
2534 return $val;
2535 },
2536 ),
2537 'store-auths' => array(
2538 function ($val) {
2539 return in_array($val, array('true', 'false', 'prompt'), true);
2540 },
2541 function ($val) {
2542 if ('prompt' === $val) {
2543 return 'prompt';
2544 }
2545
2546 return $val !== 'false' && (bool) $val;
2547 },
2548 ),
2549 'notify-on-install' => array($booleanValidator, $booleanNormalizer),
2550 'vendor-dir' => array('is_string', function ($val) {
2551 return $val;
2552 }),
2553 'bin-dir' => array('is_string', function ($val) {
2554 return $val;
2555 }),
2556 'archive-dir' => array('is_string', function ($val) {
2557 return $val;
2558 }),
2559 'archive-format' => array('is_string', function ($val) {
2560 return $val;
2561 }),
2562 'data-dir' => array('is_string', function ($val) {
2563 return $val;
2564 }),
2565 'cache-dir' => array('is_string', function ($val) {
2566 return $val;
2567 }),
2568 'cache-files-dir' => array('is_string', function ($val) {
2569 return $val;
2570 }),
2571 'cache-repo-dir' => array('is_string', function ($val) {
2572 return $val;
2573 }),
2574 'cache-vcs-dir' => array('is_string', function ($val) {
2575 return $val;
2576 }),
2577 'cache-ttl' => array('is_numeric', 'intval'),
2578 'cache-files-ttl' => array('is_numeric', 'intval'),
2579 'cache-files-maxsize' => array(
2580 function ($val) {
2581 return preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $val) > 0;
2582 },
2583 function ($val) {
2584 return $val;
2585 },
2586 ),
2587 'bin-compat' => array(
2588 function ($val) {
2589 return in_array($val, array('auto', 'full'));
2590 },
2591 function ($val) {
2592 return $val;
2593 },
2594 ),
2595 'discard-changes' => array(
2596 function ($val) {
2597 return in_array($val, array('stash', 'true', 'false', '1', '0'), true);
2598 },
2599 function ($val) {
2600 if ('stash' === $val) {
2601 return 'stash';
2602 }
2603
2604 return $val !== 'false' && (bool) $val;
2605 },
2606 ),
2607 'autoloader-suffix' => array('is_string', function ($val) {
2608 return $val === 'null' ? null : $val;
2609 }),
2610 'sort-packages' => array($booleanValidator, $booleanNormalizer),
2611 'optimize-autoloader' => array($booleanValidator, $booleanNormalizer),
2612 'classmap-authoritative' => array($booleanValidator, $booleanNormalizer),
2613 'apcu-autoloader' => array($booleanValidator, $booleanNormalizer),
2614 'prepend-autoloader' => array($booleanValidator, $booleanNormalizer),
2615 'disable-tls' => array($booleanValidator, $booleanNormalizer),
2616 'secure-http' => array($booleanValidator, $booleanNormalizer),
2617 'cafile' => array(
2618 function ($val) {
2619 return file_exists($val) && is_readable($val);
2620 },
2621 function ($val) {
2622 return $val === 'null' ? null : $val;
2623 },
2624 ),
2625 'capath' => array(
2626 function ($val) {
2627 return is_dir($val) && is_readable($val);
2628 },
2629 function ($val) {
2630 return $val === 'null' ? null : $val;
2631 },
2632 ),
2633 'github-expose-hostname' => array($booleanValidator, $booleanNormalizer),
2634 'htaccess-protect' => array($booleanValidator, $booleanNormalizer),
2635 );
2636 $multiConfigValues = array(
2637 'github-protocols' => array(
2638 function ($vals) {
2639 if (!is_array($vals)) {
2640 return 'array expected';
2641 }
2642
2643 foreach ($vals as $val) {
2644 if (!in_array($val, array('git', 'https', 'ssh'))) {
2645 return 'valid protocols include: git, https, ssh';
2646 }
2647 }
2648
2649 return true;
2650 },
2651 function ($vals) {
2652 return $vals;
2653 },
2654 ),
2655 'github-domains' => array(
2656 function ($vals) {
2657 if (!is_array($vals)) {
2658 return 'array expected';
2659 }
2660
2661 return true;
2662 },
2663 function ($vals) {
2664 return $vals;
2665 },
2666 ),
2667 'gitlab-domains' => array(
2668 function ($vals) {
2669 if (!is_array($vals)) {
2670 return 'array expected';
2671 }
2672
2673 return true;
2674 },
2675 function ($vals) {
2676 return $vals;
2677 },
2678 ),
2679 );
2680
2681 if ($input->getOption('unset') && (isset($uniqueConfigValues[$settingKey]) || isset($multiConfigValues[$settingKey]))) {
2682 return $this->configSource->removeConfigSetting($settingKey);
2683 }
2684 if (isset($uniqueConfigValues[$settingKey])) {
2685 return $this->handleSingleValue($settingKey, $uniqueConfigValues[$settingKey], $values, 'addConfigSetting');
2686 }
2687 if (isset($multiConfigValues[$settingKey])) {
2688 return $this->handleMultiValue($settingKey, $multiConfigValues[$settingKey], $values, 'addConfigSetting');
2689 }
2690
2691
2692  $uniqueProps = array(
2693 'name' => array('is_string', function ($val) {
2694 return $val;
2695 }),
2696 'type' => array('is_string', function ($val) {
2697 return $val;
2698 }),
2699 'description' => array('is_string', function ($val) {
2700 return $val;
2701 }),
2702 'homepage' => array('is_string', function ($val) {
2703 return $val;
2704 }),
2705 'version' => array('is_string', function ($val) {
2706 return $val;
2707 }),
2708 'minimum-stability' => array(
2709 function ($val) {
2710 return isset(BasePackage::$stabilities[VersionParser::normalizeStability($val)]);
2711 },
2712 function ($val) {
2713 return VersionParser::normalizeStability($val);
2714 },
2715 ),
2716 'prefer-stable' => array($booleanValidator, $booleanNormalizer),
2717 );
2718 $multiProps = array(
2719 'keywords' => array(
2720 function ($vals) {
2721 if (!is_array($vals)) {
2722 return 'array expected';
2723 }
2724
2725 return true;
2726 },
2727 function ($vals) {
2728 return $vals;
2729 },
2730 ),
2731 'license' => array(
2732 function ($vals) {
2733 if (!is_array($vals)) {
2734 return 'array expected';
2735 }
2736
2737 return true;
2738 },
2739 function ($vals) {
2740 return $vals;
2741 },
2742 ),
2743 );
2744
2745 if ($input->getOption('global') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]) || substr($settingKey, 0, 6) === 'extra.')) {
2746 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');
2747 }
2748 if ($input->getOption('unset') && (isset($uniqueProps[$settingKey]) || isset($multiProps[$settingKey]))) {
2749 return $this->configSource->removeProperty($settingKey);
2750 }
2751 if (isset($uniqueProps[$settingKey])) {
2752 return $this->handleSingleValue($settingKey, $uniqueProps[$settingKey], $values, 'addProperty');
2753 }
2754 if (isset($multiProps[$settingKey])) {
2755 return $this->handleMultiValue($settingKey, $multiProps[$settingKey], $values, 'addProperty');
2756 }
2757
2758
2759  if (preg_match('/^repos?(?:itories)?\.(.+)/', $settingKey, $matches)) {
2760 if ($input->getOption('unset')) {
2761 return $this->configSource->removeRepository($matches[1]);
2762 }
2763
2764 if (2 === count($values)) {
2765 return $this->configSource->addRepository($matches[1], array(
2766 'type' => $values[0],
2767 'url' => $values[1],
2768 ));
2769 }
2770
2771 if (1 === count($values)) {
2772 $value = strtolower($values[0]);
2773 if (true === $booleanValidator($value)) {
2774 if (false === $booleanNormalizer($value)) {
2775 return $this->configSource->addRepository($matches[1], false);
2776 }
2777 } else {
2778 $value = JsonFile::parseJson($values[0]);
2779
2780 return $this->configSource->addRepository($matches[1], $value);
2781 }
2782 }
2783
2784 throw new \RuntimeException('You must pass the type and a url. Example: php composer.phar config repositories.foo vcs https://bar.com');
2785 }
2786
2787
2788  if (preg_match('/^extra\.(.+)/', $settingKey, $matches)) {
2789 if ($input->getOption('unset')) {
2790 return $this->configSource->removeProperty($settingKey);
2791 }
2792
2793 return $this->configSource->addProperty($settingKey, $values[0]);
2794 }
2795
2796
2797  if (preg_match('/^platform\.(.+)/', $settingKey, $matches)) {
2798 if ($input->getOption('unset')) {
2799 return $this->configSource->removeConfigSetting($settingKey);
2800 }
2801
2802 return $this->configSource->addConfigSetting($settingKey, $values[0]);
2803 }
2804
2805
2806  if (preg_match('/^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic)\.(.+)/', $settingKey, $matches)) {
2807 if ($input->getOption('unset')) {
2808 $this->authConfigSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2809 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2810
2811 return;
2812 }
2813
2814 if ($matches[1] === 'bitbucket-oauth') {
2815 if (2 !== count($values)) {
2816 throw new \RuntimeException('Expected two arguments (consumer-key, consumer-secret), got '.count($values));
2817 }
2818 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2819 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('consumer-key' => $values[0], 'consumer-secret' => $values[1]));
2820 } elseif (in_array($matches[1], array('github-oauth', 'gitlab-oauth', 'gitlab-token'), true)) {
2821 if (1 !== count($values)) {
2822 throw new \RuntimeException('Too many arguments, expected only one token');
2823 }
2824 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2825 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], $values[0]);
2826 } elseif ($matches[1] === 'http-basic') {
2827 if (2 !== count($values)) {
2828 throw new \RuntimeException('Expected two arguments (username, password), got '.count($values));
2829 }
2830 $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]);
2831 $this->authConfigSource->addConfigSetting($matches[1].'.'.$matches[2], array('username' => $values[0], 'password' => $values[1]));
2832 }
2833
2834 return;
2835 }
2836
2837 throw new \InvalidArgumentException('Setting '.$settingKey.' does not exist or is not supported by this command');
2838 }
2839
2840 protected function handleSingleValue($key, array $callbacks, array $values, $method)
2841 {
2842 list($validator, $normalizer) = $callbacks;
2843 if (1 !== count($values)) {
2844 throw new \RuntimeException('You can only pass one value. Example: php composer.phar config process-timeout 300');
2845 }
2846
2847 if (true !== $validation = $validator($values[0])) {
2848 throw new \RuntimeException(sprintf(
2849 '"%s" is an invalid value'.($validation ? ' ('.$validation.')' : ''),
2850 $values[0]
2851 ));
2852 }
2853
2854 return call_user_func(array($this->configSource, $method), $key, $normalizer($values[0]));
2855 }
2856
2857 protected function handleMultiValue($key, array $callbacks, array $values, $method)
2858 {
2859 list($validator, $normalizer) = $callbacks;
2860 if (true !== $validation = $validator($values)) {
2861 throw new \RuntimeException(sprintf(
2862 '%s is an invalid value'.($validation ? ' ('.$validation.')' : ''),
2863 json_encode($values)
2864 ));
2865 }
2866
2867 return call_user_func(array($this->configSource, $method), $key, $normalizer($values));
2868 }
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878 protected function listConfiguration(array $contents, array $rawContents, OutputInterface $output, $k = null)
2879 {
2880 $origK = $k;
2881 $io = $this->getIO();
2882 foreach ($contents as $key => $value) {
2883 if ($k === null && !in_array($key, array('config', 'repositories'))) {
2884 continue;
2885 }
2886
2887 $rawVal = isset($rawContents[$key]) ? $rawContents[$key] : null;
2888
2889 if (is_array($value) && (!is_numeric(key($value)) || ($key === 'repositories' && null === $k))) {
2890 $k .= preg_replace('{^config\.}', '', $key . '.');
2891 $this->listConfiguration($value, $rawVal, $output, $k);
2892 $k = $origK;
2893
2894 continue;
2895 }
2896
2897 if (is_array($value)) {
2898 $value = array_map(function ($val) {
2899 return is_array($val) ? json_encode($val) : $val;
2900 }, $value);
2901
2902 $value = '['.implode(', ', $value).']';
2903 }
2904
2905 if (is_bool($value)) {
2906 $value = var_export($value, true);
2907 }
2908
2909 if (is_string($rawVal) && $rawVal != $value) {
2910 $io->write('[<comment>' . $k . $key . '</comment>] <info>' . $rawVal . ' (' . $value . ')</info>');
2911 } else {
2912 $io->write('[<comment>' . $k . $key . '</comment>] <info>' . $value . '</info>');
2913 }
2914 }
2915 }
2916 }
2917 <?php
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929 namespace Composer\Command;
2930
2931 use Composer\Config;
2932 use Composer\Factory;
2933 use Composer\Installer;
2934 use Composer\Installer\ProjectInstaller;
2935 use Composer\Installer\InstallationManager;
2936 use Composer\Installer\SuggestedPackagesReporter;
2937 use Composer\IO\IOInterface;
2938 use Composer\Package\BasePackage;
2939 use Composer\DependencyResolver\Pool;
2940 use Composer\DependencyResolver\Operation\InstallOperation;
2941 use Composer\Package\Version\VersionSelector;
2942 use Composer\Package\AliasPackage;
2943 use Composer\Repository\RepositoryFactory;
2944 use Composer\Repository\CompositeRepository;
2945 use Composer\Repository\PlatformRepository;
2946 use Composer\Repository\InstalledFilesystemRepository;
2947 use Composer\Script\ScriptEvents;
2948 use Composer\Util\Silencer;
2949 use Symfony\Component\Console\Input\InputArgument;
2950 use Symfony\Component\Console\Input\InputInterface;
2951 use Symfony\Component\Console\Input\InputOption;
2952 use Symfony\Component\Console\Output\OutputInterface;
2953 use Symfony\Component\Finder\Finder;
2954 use Composer\Json\JsonFile;
2955 use Composer\Config\JsonConfigSource;
2956 use Composer\Util\Filesystem;
2957 use Composer\Package\Version\VersionParser;
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967 class CreateProjectCommand extends BaseCommand
2968 {
2969
2970
2971
2972 protected $suggestedPackagesReporter;
2973
2974 protected function configure()
2975 {
2976 $this
2977 ->setName('create-project')
2978 ->setDescription('Creates new project from a package into given directory.')
2979 ->setDefinition(array(
2980 new InputArgument('package', InputArgument::OPTIONAL, 'Package name to be installed'),
2981 new InputArgument('directory', InputArgument::OPTIONAL, 'Directory where the files should be created'),
2982 new InputArgument('version', InputArgument::OPTIONAL, 'Version, will default to latest'),
2983 new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum-stability allowed (unless a version is specified).'),
2984 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
2985 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
2986 new InputOption('repository', null, InputOption::VALUE_REQUIRED, 'Pick a different repository (as url or json config) to look for the package.'),
2987 new InputOption('repository-url', null, InputOption::VALUE_REQUIRED, 'DEPRECATED: Use --repository instead.'),
2988 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
2989 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
2990 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
2991 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Whether to prevent execution of all defined scripts in the root package.'),
2992 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
2993 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.'),
2994 new InputOption('keep-vcs', null, InputOption::VALUE_NONE, 'Whether to prevent deletion vcs folder.'),
2995 new InputOption('no-install', null, InputOption::VALUE_NONE, 'Whether to skip installation of the package dependencies.'),
2996 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
2997 ))
2998 ->setHelp(<<<EOT
2999 The <info>create-project</info> command creates a new project from a given
3000 package into a new directory. If executed without params and in a directory
3001 with a composer.json file it installs the packages for the current project.
3002
3003 You can use this command to bootstrap new projects or setup a clean
3004 version-controlled installation for developers of your project.
3005
3006 <info>php composer.phar create-project vendor/project target-directory [version]</info>
3007
3008 You can also specify the version with the package name using = or : as separator.
3009
3010 <info>php composer.phar create-project vendor/project:version target-directory</info>
3011
3012 To install unstable packages, either specify the version you want, or use the
3013 --stability=dev (where dev can be one of RC, beta, alpha or dev).
3014
3015 To setup a developer workable version you should create the project using the source
3016 controlled code by appending the <info>'--prefer-source'</info> flag.
3017
3018 To install a package from another repository than the default one you
3019 can pass the <info>'--repository=https://myrepository.org'</info> flag.
3020
3021 EOT
3022 )
3023 ;
3024 }
3025
3026 protected function execute(InputInterface $input, OutputInterface $output)
3027 {
3028 $config = Factory::createConfig();
3029 $io = $this->getIO();
3030
3031 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input, true);
3032
3033 if ($input->getOption('dev')) {
3034 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
3035 }
3036 if ($input->getOption('no-custom-installers')) {
3037 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
3038 $input->setOption('no-plugins', true);
3039 }
3040
3041 return $this->installProject(
3042 $io,
3043 $config,
3044 $input,
3045 $input->getArgument('package'),
3046 $input->getArgument('directory'),
3047 $input->getArgument('version'),
3048 $input->getOption('stability'),
3049 $preferSource,
3050 $preferDist,
3051 !$input->getOption('no-dev'),
3052 $input->getOption('repository') ?: $input->getOption('repository-url'),
3053 $input->getOption('no-plugins'),
3054 $input->getOption('no-scripts'),
3055 $input->getOption('keep-vcs'),
3056 $input->getOption('no-progress'),
3057 $input->getOption('no-install'),
3058 $input->getOption('ignore-platform-reqs'),
3059 !$input->getOption('no-secure-http')
3060 );
3061 }
3062
3063 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)
3064 {
3065 $oldCwd = getcwd();
3066
3067
3068  $io->loadConfiguration($config);
3069
3070 $this->suggestedPackagesReporter = new SuggestedPackagesReporter($io);
3071
3072 if ($packageName !== null) {
3073 $installedFromVcs = $this->installRootPackage($io, $config, $packageName, $directory, $packageVersion, $stability, $preferSource, $preferDist, $installDevPackages, $repository, $disablePlugins, $noScripts, $keepVcs, $noProgress, $ignorePlatformReqs, $secureHttp);
3074 } else {
3075 $installedFromVcs = false;
3076 }
3077
3078 $composer = Factory::create($io, null, $disablePlugins);
3079 $composer->getDownloadManager()->setOutputProgress(!$noProgress);
3080
3081 $fs = new Filesystem();
3082
3083 if ($noScripts === false) {
3084
3085  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_ROOT_PACKAGE_INSTALL, $installDevPackages);
3086 }
3087
3088 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($composer->getConfig(), $input);
3089
3090
3091  if ($noInstall === false) {
3092 $installer = Installer::create($io, $composer);
3093 $installer->setPreferSource($preferSource)
3094 ->setPreferDist($preferDist)
3095 ->setDevMode($installDevPackages)
3096 ->setRunScripts(!$noScripts)
3097 ->setIgnorePlatformRequirements($ignorePlatformReqs)
3098 ->setSuggestedPackagesReporter($this->suggestedPackagesReporter);
3099
3100 if ($disablePlugins) {
3101 $installer->disablePlugins();
3102 }
3103
3104 $status = $installer->run();
3105 if (0 !== $status) {
3106 return $status;
3107 }
3108 }
3109
3110 $hasVcs = $installedFromVcs;
3111 if (!$keepVcs && $installedFromVcs
3112 && (
3113 !$io->isInteractive()
3114 || $io->askConfirmation('<info>Do you want to remove the existing VCS (.git, .svn..) history?</info> [<comment>Y,n</comment>]? ', true)
3115 )
3116 ) {
3117 $finder = new Finder();
3118 $finder->depth(0)->directories()->in(getcwd())->ignoreVCS(false)->ignoreDotFiles(false);
3119 foreach (array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg', '.fslckout', '_FOSSIL_') as $vcsName) {
3120 $finder->name($vcsName);
3121 }
3122
3123 try {
3124 $dirs = iterator_to_array($finder);
3125 unset($finder);
3126 foreach ($dirs as $dir) {
3127 if (!$fs->removeDirectory($dir)) {
3128 throw new \RuntimeException('Could not remove '.$dir);
3129 }
3130 }
3131 } catch (\Exception $e) {
3132 $io->writeError('<error>An error occurred while removing the VCS metadata: '.$e->getMessage().'</error>');
3133 }
3134
3135 $hasVcs = false;
3136 }
3137
3138
3139  if (!$hasVcs) {
3140 $package = $composer->getPackage();
3141 $configSource = new JsonConfigSource(new JsonFile('composer.json'));
3142 foreach (BasePackage::$supportedLinkTypes as $type => $meta) {
3143 foreach ($package->{'get'.$meta['method']}() as $link) {
3144 if ($link->getPrettyConstraint() === 'self.version') {
3145 $configSource->addLink($type, $link->getTarget(), $package->getPrettyVersion());
3146 }
3147 }
3148 }
3149 }
3150
3151 if ($noScripts === false) {
3152
3153  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_CREATE_PROJECT_CMD, $installDevPackages);
3154 }
3155
3156 chdir($oldCwd);
3157 $vendorComposerDir = $composer->getConfig()->get('vendor-dir').'/composer';
3158 if (is_dir($vendorComposerDir) && $fs->isDirEmpty($vendorComposerDir)) {
3159 Silencer::call('rmdir', $vendorComposerDir);
3160 $vendorDir = $composer->getConfig()->get('vendor-dir');
3161 if (is_dir($vendorDir) && $fs->isDirEmpty($vendorDir)) {
3162 Silencer::call('rmdir', $vendorDir);
3163 }
3164 }
3165
3166 return 0;
3167 }
3168
3169 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)
3170 {
3171 if (!$secureHttp) {
3172 $config->merge(array('config' => array('secure-http' => false)));
3173 }
3174
3175 if (null === $repository) {
3176 $sourceRepo = new CompositeRepository(RepositoryFactory::defaultRepos($io, $config));
3177 } else {
3178 $sourceRepo = RepositoryFactory::fromString($io, $config, $repository, true);
3179 }
3180
3181 $parser = new VersionParser();
3182 $requirements = $parser->parseNameVersionPairs(array($packageName));
3183 $name = strtolower($requirements[0]['name']);
3184 if (!$packageVersion && isset($requirements[0]['version'])) {
3185 $packageVersion = $requirements[0]['version'];
3186 }
3187
3188 if (null === $stability) {
3189 if (preg_match('{^[^,\s]*?@('.implode('|', array_keys(BasePackage::$stabilities)).')$}i', $packageVersion, $match)) {
3190 $stability = $match[1];
3191 } else {
3192 $stability = VersionParser::parseStability($packageVersion);
3193 }
3194 }
3195
3196 $stability = VersionParser::normalizeStability($stability);
3197
3198 if (!isset(BasePackage::$stabilities[$stability])) {
3199 throw new \InvalidArgumentException('Invalid stability provided ('.$stability.'), must be one of: '.implode(', ', array_keys(BasePackage::$stabilities)));
3200 }
3201
3202 $pool = new Pool($stability);
3203 $pool->addRepository($sourceRepo);
3204
3205 $phpVersion = null;
3206 $prettyPhpVersion = null;
3207 if (!$ignorePlatformReqs) {
3208 $platformOverrides = $config->get('platform') ?: array();
3209
3210  $platform = new PlatformRepository(array(), $platformOverrides);
3211 $phpPackage = $platform->findPackage('php', '*');
3212 $phpVersion = $phpPackage->getVersion();
3213 $prettyPhpVersion = $phpPackage->getPrettyVersion();
3214 }
3215
3216
3217  $versionSelector = new VersionSelector($pool);
3218 $package = $versionSelector->findBestCandidate($name, $packageVersion, $phpVersion, $stability);
3219
3220 if (!$package) {
3221 $errorMessage = "Could not find package $name with " . ($packageVersion ? "version $packageVersion" : "stability $stability");
3222 if ($phpVersion && $versionSelector->findBestCandidate($name, $packageVersion, null, $stability)) {
3223 throw new \InvalidArgumentException($errorMessage .' in a version installable using your PHP version '.$prettyPhpVersion.'.');
3224 }
3225
3226 throw new \InvalidArgumentException($errorMessage .'.');
3227 }
3228
3229 if (null === $directory) {
3230 $parts = explode("/", $name, 2);
3231 $directory = getcwd() . DIRECTORY_SEPARATOR . array_pop($parts);
3232 }
3233
3234
3235  if (function_exists('pcntl_signal')) {
3236 declare(ticks=100);
3237 pcntl_signal(SIGINT, function () use ($directory) {
3238 $fs = new Filesystem();
3239 $fs->removeDirectory($directory);
3240 exit(130);
3241 });
3242 }
3243
3244 $io->writeError('<info>Installing ' . $package->getName() . ' (' . $package->getFullPrettyVersion(false) . ')</info>');
3245
3246 if ($disablePlugins) {
3247 $io->writeError('<info>Plugins have been disabled.</info>');
3248 }
3249
3250 if ($package instanceof AliasPackage) {
3251 $package = $package->getAliasOf();
3252 }
3253
3254 if (0 === strpos($package->getPrettyVersion(), 'dev-') && in_array($package->getSourceType(), array('git', 'hg'))) {
3255 $package->setSourceReference(substr($package->getPrettyVersion(), 4));
3256 }
3257
3258 $dm = $this->createDownloadManager($io, $config);
3259 $dm->setPreferSource($preferSource)
3260 ->setPreferDist($preferDist)
3261 ->setOutputProgress(!$noProgress);
3262
3263 $projectInstaller = new ProjectInstaller($directory, $dm);
3264 $im = $this->createInstallationManager();
3265 $im->addInstaller($projectInstaller);
3266 $im->install(new InstalledFilesystemRepository(new JsonFile('php://memory')), new InstallOperation($package));
3267 $im->notifyInstalls($io);
3268
3269
3270  $this->suggestedPackagesReporter->addSuggestionsFromPackage($package);
3271
3272 $installedFromVcs = 'source' === $package->getInstallationSource();
3273
3274 $io->writeError('<info>Created project in ' . $directory . '</info>');
3275 chdir($directory);
3276
3277 $_SERVER['COMPOSER_ROOT_VERSION'] = $package->getPrettyVersion();
3278 putenv('COMPOSER_ROOT_VERSION='.$_SERVER['COMPOSER_ROOT_VERSION']);
3279
3280 return $installedFromVcs;
3281 }
3282
3283 protected function createDownloadManager(IOInterface $io, Config $config)
3284 {
3285 $factory = new Factory();
3286
3287 return $factory->createDownloadManager($io, $config);
3288 }
3289
3290 protected function createInstallationManager()
3291 {
3292 return new InstallationManager();
3293 }
3294 }
3295 <?php
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307 namespace Composer\Command;
3308
3309 use Symfony\Component\Console\Input\InputInterface;
3310 use Symfony\Component\Console\Output\OutputInterface;
3311
3312
3313
3314
3315 class DependsCommand extends BaseDependencyCommand
3316 {
3317
3318
3319
3320 protected function configure()
3321 {
3322 parent::configure();
3323
3324 $this
3325 ->setName('depends')
3326 ->setAliases(array('why'))
3327 ->setDescription('Shows which packages cause the given package to be installed.')
3328 ->setHelp(<<<EOT
3329 Displays detailed information about where a package is referenced.
3330
3331 <info>php composer.phar depends composer/composer</info>
3332
3333 EOT
3334 )
3335 ;
3336 }
3337
3338
3339
3340
3341
3342
3343
3344
3345 protected function execute(InputInterface $input, OutputInterface $output)
3346 {
3347 return parent::doExecute($input, $output, false);
3348 }
3349 }
3350 <?php
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362 namespace Composer\Command;
3363
3364 use Composer\Composer;
3365 use Composer\Factory;
3366 use Composer\Config;
3367 use Composer\Downloader\TransportException;
3368 use Composer\Plugin\CommandEvent;
3369 use Composer\Plugin\PluginEvents;
3370 use Composer\Util\ConfigValidator;
3371 use Composer\Util\IniHelper;
3372 use Composer\Util\ProcessExecutor;
3373 use Composer\Util\RemoteFilesystem;
3374 use Composer\Util\StreamContextFactory;
3375 use Composer\SelfUpdate\Keys;
3376 use Composer\SelfUpdate\Versions;
3377 use Composer\IO\NullIO;
3378 use Symfony\Component\Console\Input\InputInterface;
3379 use Symfony\Component\Console\Output\OutputInterface;
3380
3381
3382
3383
3384 class DiagnoseCommand extends BaseCommand
3385 {
3386
3387 protected $rfs;
3388
3389
3390 protected $process;
3391
3392
3393 protected $exitCode = 0;
3394
3395 protected function configure()
3396 {
3397 $this
3398 ->setName('diagnose')
3399 ->setDescription('Diagnoses the system to identify common errors.')
3400 ->setHelp(<<<EOT
3401 The <info>diagnose</info> command checks common errors to help debugging problems.
3402
3403 The process exit code will be 1 in case of warnings and 2 for errors.
3404
3405 EOT
3406 )
3407 ;
3408 }
3409
3410
3411
3412
3413 protected function execute(InputInterface $input, OutputInterface $output)
3414 {
3415 $composer = $this->getComposer(false);
3416 $io = $this->getIO();
3417
3418 if ($composer) {
3419 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'diagnose', $input, $output);
3420 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
3421
3422 $io->write('Checking composer.json: ', false);
3423 $this->outputResult($this->checkComposerSchema());
3424 }
3425
3426 if ($composer) {
3427 $config = $composer->getConfig();
3428 } else {
3429 $config = Factory::createConfig();
3430 }
3431
3432 $config->merge(array('config' => array('secure-http' => false)));
3433 $config->prohibitUrlByConfig('http://packagist.org', new NullIO);
3434
3435 $this->rfs = Factory::createRemoteFilesystem($io, $config);
3436 $this->process = new ProcessExecutor($io);
3437
3438 $io->write('Checking platform settings: ', false);
3439 $this->outputResult($this->checkPlatform());
3440
3441 $io->write('Checking git settings: ', false);
3442 $this->outputResult($this->checkGit());
3443
3444 $io->write('Checking http connectivity to packagist: ', false);
3445 $this->outputResult($this->checkHttp('http', $config));
3446
3447 $io->write('Checking https connectivity to packagist: ', false);
3448 $this->outputResult($this->checkHttp('https', $config));
3449
3450 $opts = stream_context_get_options(StreamContextFactory::getContext('http://example.org'));
3451 if (!empty($opts['http']['proxy'])) {
3452 $io->write('Checking HTTP proxy: ', false);
3453 $this->outputResult($this->checkHttpProxy());
3454 $io->write('Checking HTTP proxy support for request_fulluri: ', false);
3455 $this->outputResult($this->checkHttpProxyFullUriRequestParam());
3456 $io->write('Checking HTTPS proxy support for request_fulluri: ', false);
3457 $this->outputResult($this->checkHttpsProxyFullUriRequestParam());
3458 }
3459
3460 if ($oauth = $config->get('github-oauth')) {
3461 foreach ($oauth as $domain => $token) {
3462 $io->write('Checking '.$domain.' oauth access: ', false);
3463 $this->outputResult($this->checkGithubOauth($domain, $token));
3464 }
3465 } else {
3466 $io->write('Checking github.com rate limit: ', false);
3467 try {
3468 $rate = $this->getGithubRateLimit('github.com');
3469 $this->outputResult(true);
3470 if (10 > $rate['remaining']) {
3471 $io->write('<warning>WARNING</warning>');
3472 $io->write(sprintf(
3473 '<comment>Github has a rate limit on their API. '
3474 . 'You currently have <options=bold>%u</options=bold> '
3475 . 'out of <options=bold>%u</options=bold> requests left.' . PHP_EOL
3476 . 'See https://developer.github.com/v3/#rate-limiting and also' . PHP_EOL
3477 . '    https://getcomposer.org/doc/articles/troubleshooting.md#api-rate-limit-and-oauth-tokens</comment>',
3478 $rate['remaining'],
3479 $rate['limit']
3480 ));
3481 }
3482 } catch (\Exception $e) {
3483 if ($e instanceof TransportException && $e->getCode() === 401) {
3484 $this->outputResult('<comment>The oauth token for github.com seems invalid, run "composer config --global --unset github-oauth.github.com" to remove it</comment>');
3485 } else {
3486 $this->outputResult($e);
3487 }
3488 }
3489 }
3490
3491 $io->write('Checking disk free space: ', false);
3492 $this->outputResult($this->checkDiskSpace($config));
3493
3494 if ('phar:' === substr(__FILE__, 0, 5)) {
3495 $io->write('Checking pubkeys: ', false);
3496 $this->outputResult($this->checkPubKeys($config));
3497
3498 $io->write('Checking composer version: ', false);
3499 $this->outputResult($this->checkVersion($config));
3500 }
3501
3502 return $this->exitCode;
3503 }
3504
3505 private function checkComposerSchema()
3506 {
3507 $validator = new ConfigValidator($this->getIO());
3508 list($errors, , $warnings) = $validator->validate(Factory::getComposerFile());
3509
3510 if ($errors || $warnings) {
3511 $messages = array(
3512 'error' => $errors,
3513 'warning' => $warnings,
3514 );
3515
3516 $output = '';
3517 foreach ($messages as $style => $msgs) {
3518 foreach ($msgs as $msg) {
3519 $output .= '<' . $style . '>' . $msg . '</' . $style . '>' . PHP_EOL;
3520 }
3521 }
3522
3523 return rtrim($output);
3524 }
3525
3526 return true;
3527 }
3528
3529 private function checkGit()
3530 {
3531 $this->process->execute('git config color.ui', $output);
3532 if (strtolower(trim($output)) === 'always') {
3533 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>';
3534 }
3535
3536 return true;
3537 }
3538
3539 private function checkHttp($proto, Config $config)
3540 {
3541 $disableTls = false;
3542 $result = array();
3543 if ($proto === 'https' && $config->get('disable-tls') === true) {
3544 $disableTls = true;
3545 $result[] = '<warning>Composer is configured to disable SSL/TLS protection. This will leave remote HTTPS requests vulnerable to Man-In-The-Middle attacks.</warning>';
3546 }
3547 if ($proto === 'https' && !extension_loaded('openssl') && !$disableTls) {
3548 $result[] = '<error>Composer is configured to use SSL/TLS protection but the openssl extension is not available.</error>';
3549 }
3550
3551 try {
3552 $this->rfs->getContents('packagist.org', $proto . '://packagist.org/packages.json', false);
3553 } catch (TransportException $e) {
3554 if (false !== strpos($e->getMessage(), 'cafile')) {
3555 $result[] = '<error>[' . get_class($e) . '] ' . $e->getMessage() . '</error>';
3556 $result[] = '<error>Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.</error>';
3557 $result[] = '<error>You can alternatively disable this error, at your own risk, by enabling the \'disable-tls\' option.</error>';
3558 } else {
3559 array_unshift($result, '[' . get_class($e) . '] ' . $e->getMessage());
3560 }
3561 }
3562
3563 if (count($result) > 0) {
3564 return $result;
3565 }
3566
3567 return true;
3568 }
3569
3570 private function checkHttpProxy()
3571 {
3572 $protocol = extension_loaded('openssl') ? 'https' : 'http';
3573 try {
3574 $json = json_decode($this->rfs->getContents('packagist.org', $protocol . '://packagist.org/packages.json', false), true);
3575 $hash = reset($json['provider-includes']);
3576 $hash = $hash['sha256'];
3577 $path = str_replace('%hash%', $hash, key($json['provider-includes']));
3578 $provider = $this->rfs->getContents('packagist.org', $protocol . '://packagist.org/'.$path, false);
3579
3580 if (hash('sha256', $provider) !== $hash) {
3581 return 'It seems that your proxy is modifying http traffic on the fly';
3582 }
3583 } catch (\Exception $e) {
3584 return $e;
3585 }
3586
3587 return true;
3588 }
3589
3590
3591
3592
3593
3594
3595
3596
3597 private function checkHttpProxyFullUriRequestParam()
3598 {
3599 $url = 'http://packagist.org/packages.json';
3600 try {
3601 $this->rfs->getContents('packagist.org', $url, false);
3602 } catch (TransportException $e) {
3603 try {
3604 $this->rfs->getContents('packagist.org', $url, false, array('http' => array('request_fulluri' => false)));
3605 } catch (TransportException $e) {
3606 return 'Unable to assess the situation, maybe packagist.org is down ('.$e->getMessage().')';
3607 }
3608
3609 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"';
3610 }
3611
3612 return true;
3613 }
3614
3615
3616
3617
3618
3619
3620
3621
3622 private function checkHttpsProxyFullUriRequestParam()
3623 {
3624 if (!extension_loaded('openssl')) {
3625 return 'You need the openssl extension installed for this check';
3626 }
3627
3628 $url = 'https://api.github.com/repos/Seldaek/jsonlint/zipball/1.0.0';
3629 try {
3630 $this->rfs->getContents('github.com', $url, false);
3631 } catch (TransportException $e) {
3632 try {
3633 $this->rfs->getContents('github.com', $url, false, array('http' => array('request_fulluri' => false)));
3634 } catch (TransportException $e) {
3635 return 'Unable to assess the situation, maybe github is down ('.$e->getMessage().')';
3636 }
3637
3638 return 'It seems there is a problem with your proxy server, try setting the "HTTPS_PROXY_REQUEST_FULLURI" environment variable to "false"';
3639 }
3640
3641 return true;
3642 }
3643
3644 private function checkGithubOauth($domain, $token)
3645 {
3646 $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
3647 try {
3648 $url = $domain === 'github.com' ? 'https://api.'.$domain.'/' : 'https://'.$domain.'/api/v3/';
3649
3650 return $this->rfs->getContents($domain, $url, false, array(
3651 'retry-auth-failure' => false,
3652 )) ? true : 'Unexpected error';
3653 } catch (\Exception $e) {
3654 if ($e instanceof TransportException && $e->getCode() === 401) {
3655 return '<comment>The oauth token for '.$domain.' seems invalid, run "composer config --global --unset github-oauth.'.$domain.'" to remove it</comment>';
3656 }
3657
3658 return $e;
3659 }
3660 }
3661
3662
3663
3664
3665
3666
3667
3668 private function getGithubRateLimit($domain, $token = null)
3669 {
3670 if ($token) {
3671 $this->getIO()->setAuthentication($domain, $token, 'x-oauth-basic');
3672 }
3673
3674 $url = $domain === 'github.com' ? 'https://api.'.$domain.'/rate_limit' : 'https://'.$domain.'/api/rate_limit';
3675 $json = $this->rfs->getContents($domain, $url, false, array('retry-auth-failure' => false));
3676 $data = json_decode($json, true);
3677
3678 return $data['resources']['core'];
3679 }
3680
3681 private function checkDiskSpace($config)
3682 {
3683 $minSpaceFree = 1024 * 1024;
3684 if ((($df = @disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
3685 || (($df = @disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
3686 ) {
3687 return '<error>The disk hosting '.$dir.' is full</error>';
3688 }
3689
3690 return true;
3691 }
3692
3693 private function checkPubKeys($config)
3694 {
3695 $home = $config->get('home');
3696 $errors = array();
3697 $io = $this->getIO();
3698
3699 if (file_exists($home.'/keys.tags.pub') && file_exists($home.'/keys.dev.pub')) {
3700 $io->write('');
3701 }
3702
3703 if (file_exists($home.'/keys.tags.pub')) {
3704 $io->write('Tags Public Key Fingerprint: ' . Keys::fingerprint($home.'/keys.tags.pub'));
3705 } else {
3706 $errors[] = '<error>Missing pubkey for tags verification</error>';
3707 }
3708
3709 if (file_exists($home.'/keys.dev.pub')) {
3710 $io->write('Dev Public Key Fingerprint: ' . Keys::fingerprint($home.'/keys.dev.pub'));
3711 } else {
3712 $errors[] = '<error>Missing pubkey for dev verification</error>';
3713 }
3714
3715 if ($errors) {
3716 $errors[] = '<error>Run composer self-update --update-keys to set them up</error>';
3717 }
3718
3719 return $errors ?: true;
3720 }
3721
3722 private function checkVersion($config)
3723 {
3724 $versionsUtil = new Versions($config, $this->rfs);
3725 $latest = $versionsUtil->getLatest();
3726
3727 if (Composer::VERSION !== $latest['version'] && Composer::VERSION !== '@package_version@') {
3728 return '<comment>You are not running the latest '.$versionsUtil->getChannel().' version, run `composer self-update` to update ('.Composer::VERSION.' => '.$latest['version'].')</comment>';
3729 }
3730
3731 return true;
3732 }
3733
3734
3735
3736
3737 private function outputResult($result)
3738 {
3739 $io = $this->getIO();
3740 if (true === $result) {
3741 $io->write('<info>OK</info>');
3742
3743 return;
3744 }
3745
3746 $hadError = false;
3747 if ($result instanceof \Exception) {
3748 $result = '<error>['.get_class($result).'] '.$result->getMessage().'</error>';
3749 }
3750
3751 if (!$result) {
3752
3753  $hadError = true;
3754 } else {
3755 if (!is_array($result)) {
3756 $result = array($result);
3757 }
3758 foreach ($result as $message) {
3759 if (false !== strpos($message, '<error>')) {
3760 $hadError = true;
3761 }
3762 }
3763 }
3764
3765 if ($hadError) {
3766 $io->write('<error>FAIL</error>');
3767 $this->exitCode = 2;
3768 } else {
3769 $io->write('<warning>WARNING</warning>');
3770 $this->exitCode = 1;
3771 }
3772
3773 if ($result) {
3774 foreach ($result as $message) {
3775 $io->write($message);
3776 }
3777 }
3778 }
3779
3780 private function checkPlatform()
3781 {
3782 $output = '';
3783 $out = function ($msg, $style) use (&$output) {
3784 $output .= '<'.$style.'>'.$msg.'</'.$style.'>'.PHP_EOL;
3785 };
3786
3787
3788  $errors = array();
3789 $warnings = array();
3790 $displayIniMessage = false;
3791
3792 $iniMessage = PHP_EOL.PHP_EOL.IniHelper::getMessage();
3793 $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.';
3794
3795 if (!function_exists('json_decode')) {
3796 $errors['json'] = true;
3797 }
3798
3799 if (!extension_loaded('Phar')) {
3800 $errors['phar'] = true;
3801 }
3802
3803 if (!extension_loaded('filter')) {
3804 $errors['filter'] = true;
3805 }
3806
3807 if (!extension_loaded('hash')) {
3808 $errors['hash'] = true;
3809 }
3810
3811 if (!extension_loaded('iconv') && !extension_loaded('mbstring')) {
3812 $errors['iconv_mbstring'] = true;
3813 }
3814
3815 if (!ini_get('allow_url_fopen')) {
3816 $errors['allow_url_fopen'] = true;
3817 }
3818
3819 if (extension_loaded('ionCube Loader') && ioncube_loader_iversion() < 40009) {
3820 $errors['ioncube'] = ioncube_loader_version();
3821 }
3822
3823 if (PHP_VERSION_ID < 50302) {
3824 $errors['php'] = PHP_VERSION;
3825 }
3826
3827 if (!isset($errors['php']) && PHP_VERSION_ID < 50304) {
3828 $warnings['php'] = PHP_VERSION;
3829 }
3830
3831 if (!extension_loaded('openssl')) {
3832 $errors['openssl'] = true;
3833 }
3834
3835 if (extension_loaded('openssl') && OPENSSL_VERSION_NUMBER < 0x1000100f) {
3836 $warnings['openssl_version'] = true;
3837 }
3838
3839 if (!defined('HHVM_VERSION') && !extension_loaded('apcu') && ini_get('apc.enable_cli')) {
3840 $warnings['apc_cli'] = true;
3841 }
3842
3843 if (!extension_loaded('zlib')) {
3844 $warnings['zlib'] = true;
3845 }
3846
3847 ob_start();
3848 phpinfo(INFO_GENERAL);
3849 $phpinfo = ob_get_clean();
3850 if (preg_match('{Configure Command(?: *</td><td class="v">| *=> *)(.*?)(?:</td>|$)}m', $phpinfo, $match)) {
3851 $configure = $match[1];
3852
3853 if (false !== strpos($configure, '--enable-sigchild')) {
3854 $warnings['sigchild'] = true;
3855 }
3856
3857 if (false !== strpos($configure, '--with-curlwrappers')) {
3858 $warnings['curlwrappers'] = true;
3859 }
3860 }
3861
3862 if (ini_get('xdebug.profiler_enabled')) {
3863 $warnings['xdebug_profile'] = true;
3864 } elseif (extension_loaded('xdebug')) {
3865 $warnings['xdebug_loaded'] = true;
3866 }
3867
3868 if (!empty($errors)) {
3869 foreach ($errors as $error => $current) {
3870 switch ($error) {
3871 case 'json':
3872 $text = PHP_EOL."The json extension is missing.".PHP_EOL;
3873 $text .= "Install it or recompile php without --disable-json";
3874 break;
3875
3876 case 'phar':
3877 $text = PHP_EOL."The phar extension is missing.".PHP_EOL;
3878 $text .= "Install it or recompile php without --disable-phar";
3879 break;
3880
3881 case 'filter':
3882 $text = PHP_EOL."The filter extension is missing.".PHP_EOL;
3883 $text .= "Install it or recompile php without --disable-filter";
3884 break;
3885
3886 case 'hash':
3887 $text = PHP_EOL."The hash extension is missing.".PHP_EOL;
3888 $text .= "Install it or recompile php without --disable-hash";
3889 break;
3890
3891 case 'iconv_mbstring':
3892 $text = PHP_EOL."The iconv OR mbstring extension is required and both are missing.".PHP_EOL;
3893 $text .= "Install either of them or recompile php without --disable-iconv";
3894 break;
3895
3896 case 'unicode':
3897 $text = PHP_EOL."The detect_unicode setting must be disabled.".PHP_EOL;
3898 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
3899 $text .= "    detect_unicode = Off";
3900 $displayIniMessage = true;
3901 break;
3902
3903 case 'suhosin':
3904 $text = PHP_EOL."The suhosin.executor.include.whitelist setting is incorrect.".PHP_EOL;
3905 $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;
3906 $text .= "    suhosin.executor.include.whitelist = phar ".$current;
3907 $displayIniMessage = true;
3908 break;
3909
3910 case 'php':
3911 $text = PHP_EOL."Your PHP ({$current}) is too old, you must upgrade to PHP 5.3.2 or higher.";
3912 break;
3913
3914 case 'allow_url_fopen':
3915 $text = PHP_EOL."The allow_url_fopen setting is incorrect.".PHP_EOL;
3916 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
3917 $text .= "    allow_url_fopen = On";
3918 $displayIniMessage = true;
3919 break;
3920
3921 case 'ioncube':
3922 $text = PHP_EOL."Your ionCube Loader extension ($current) is incompatible with Phar files.".PHP_EOL;
3923 $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;
3924 $text .= "    zend_extension = /usr/lib/php5/20090626+lfs/ioncube_loader_lin_5.3.so";
3925 $displayIniMessage = true;
3926 break;
3927
3928 case 'openssl':
3929 $text = PHP_EOL."The openssl extension is missing, which means that secure HTTPS transfers are impossible.".PHP_EOL;
3930 $text .= "If possible you should enable it or recompile php with --with-openssl";
3931 break;
3932 }
3933 $out($text, 'error');
3934 }
3935
3936 $output .= PHP_EOL;
3937 }
3938
3939 if (!empty($warnings)) {
3940 foreach ($warnings as $warning => $current) {
3941 switch ($warning) {
3942 case 'apc_cli':
3943 $text = "The apc.enable_cli setting is incorrect.".PHP_EOL;
3944 $text .= "Add the following to the end of your `php.ini`:".PHP_EOL;
3945 $text .= "  apc.enable_cli = Off";
3946 $displayIniMessage = true;
3947 break;
3948
3949 case 'zlib':
3950 $text = 'The zlib extension is not loaded, this can slow down Composer a lot.'.PHP_EOL;
3951 $text .= 'If possible, enable it or recompile php with --with-zlib'.PHP_EOL;
3952 $displayIniMessage = true;
3953 break;
3954
3955 case 'sigchild':
3956 $text = "PHP was compiled with --enable-sigchild which can cause issues on some platforms.".PHP_EOL;
3957 $text .= "Recompile it without this flag if possible, see also:".PHP_EOL;
3958 $text .= "  https://bugs.php.net/bug.php?id=22999";
3959 break;
3960
3961 case 'curlwrappers':
3962 $text = "PHP was compiled with --with-curlwrappers which will cause issues with HTTP authentication and GitHub.".PHP_EOL;
3963 $text .= " Recompile it without this flag if possible";
3964 break;
3965
3966 case 'php':
3967 $text = "Your PHP ({$current}) is quite old, upgrading to PHP 5.3.4 or higher is recommended.".PHP_EOL;
3968 $text .= " Composer works with 5.3.2+ for most people, but there might be edge case issues.";
3969 break;
3970
3971 case 'openssl_version':
3972
3973  $opensslVersion = strstr(trim(strstr(OPENSSL_VERSION_TEXT, ' ')), ' ', true);
3974 $opensslVersion = $opensslVersion ?: OPENSSL_VERSION_TEXT;
3975
3976 $text = "The OpenSSL library ({$opensslVersion}) used by PHP does not support TLSv1.2 or TLSv1.1.".PHP_EOL;
3977 $text .= "If possible you should upgrade OpenSSL to version 1.0.1 or above.";
3978 break;
3979
3980 case 'xdebug_loaded':
3981 $text = "The xdebug extension is loaded, this can slow down Composer a little.".PHP_EOL;
3982 $text .= " Disabling it when using Composer is recommended.";
3983 break;
3984
3985 case 'xdebug_profile':
3986 $text = "The xdebug.profiler_enabled setting is enabled, this can slow down Composer a lot.".PHP_EOL;
3987 $text .= "Add the following to the end of your `php.ini` to disable it:".PHP_EOL;
3988 $text .= "  xdebug.profiler_enabled = 0";
3989 $displayIniMessage = true;
3990 break;
3991 }
3992 $out($text, 'comment');
3993 }
3994 }
3995
3996 if ($displayIniMessage) {
3997 $out($iniMessage, 'comment');
3998 }
3999
4000 return !$warnings && !$errors ? true : $output;
4001 }
4002 }
4003 <?php
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015 namespace Composer\Command;
4016
4017 use Composer\Plugin\CommandEvent;
4018 use Composer\Plugin\PluginEvents;
4019 use Symfony\Component\Console\Input\InputInterface;
4020 use Symfony\Component\Console\Input\InputOption;
4021 use Symfony\Component\Console\Output\OutputInterface;
4022
4023
4024
4025
4026 class DumpAutoloadCommand extends BaseCommand
4027 {
4028 protected function configure()
4029 {
4030 $this
4031 ->setName('dump-autoload')
4032 ->setAliases(array('dumpautoload'))
4033 ->setDescription('Dumps the autoloader.')
4034 ->setDefinition(array(
4035 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
4036 new InputOption('optimize', 'o', InputOption::VALUE_NONE, 'Optimizes PSR0 and PSR4 packages to be loaded with classmaps too, good for production.'),
4037 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize`.'),
4038 new InputOption('apcu', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
4039 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables autoload-dev rules.'),
4040 ))
4041 ->setHelp(<<<EOT
4042 <info>php composer.phar dump-autoload</info>
4043 EOT
4044 )
4045 ;
4046 }
4047
4048 protected function execute(InputInterface $input, OutputInterface $output)
4049 {
4050 $composer = $this->getComposer();
4051
4052 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'dump-autoload', $input, $output);
4053 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
4054
4055 $installationManager = $composer->getInstallationManager();
4056 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
4057 $package = $composer->getPackage();
4058 $config = $composer->getConfig();
4059
4060 $optimize = $input->getOption('optimize') || $config->get('optimize-autoloader');
4061 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
4062 $apcu = $input->getOption('apcu') || $config->get('apcu-autoloader');
4063
4064 if ($optimize || $authoritative) {
4065 $this->getIO()->writeError('<info>Generating optimized autoload files</info>');
4066 } else {
4067 $this->getIO()->writeError('<info>Generating autoload files</info>');
4068 }
4069
4070 $generator = $composer->getAutoloadGenerator();
4071 $generator->setDevMode(!$input->getOption('no-dev'));
4072 $generator->setClassMapAuthoritative($authoritative);
4073 $generator->setApcu($apcu);
4074 $generator->setRunScripts(!$input->getOption('no-scripts'));
4075 $generator->dump($config, $localRepo, $package, $installationManager, 'composer', $optimize);
4076 }
4077 }
4078 <?php
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090 namespace Composer\Command;
4091
4092 use Symfony\Component\Console\Input\InputInterface;
4093 use Symfony\Component\Console\Input\InputOption;
4094 use Symfony\Component\Console\Output\OutputInterface;
4095 use Symfony\Component\Console\Input\InputArgument;
4096
4097
4098
4099
4100 class ExecCommand extends BaseCommand
4101 {
4102 protected function configure()
4103 {
4104 $this
4105 ->setName('exec')
4106 ->setDescription('Executes a vendored binary/script.')
4107 ->setDefinition(array(
4108 new InputOption('list', 'l', InputOption::VALUE_NONE),
4109 new InputArgument('binary', InputArgument::OPTIONAL, 'The binary to run, e.g. phpunit'),
4110 new InputArgument(
4111 'args',
4112 InputArgument::IS_ARRAY | InputArgument::OPTIONAL,
4113 'Arguments to pass to the binary. Use <info>--</info> to separate from composer arguments'
4114 ),
4115 ))
4116 ;
4117 }
4118
4119 protected function execute(InputInterface $input, OutputInterface $output)
4120 {
4121 $composer = $this->getComposer();
4122 $binDir = $composer->getConfig()->get('bin-dir');
4123 if ($input->getOption('list') || !$input->getArgument('binary')) {
4124 $bins = glob($binDir . '/*');
4125 $bins = array_merge($bins, array_map(function ($e) {
4126 return "$e (local)";
4127 }, $composer->getPackage()->getBinaries()));
4128
4129 if (!$bins) {
4130 throw new \RuntimeException("No binaries found in composer.json or in bin-dir ($binDir)");
4131 }
4132
4133 $this->getIO()->write(<<<EOT
4134 <comment>Available binaries:</comment>
4135 EOT
4136 );
4137
4138 foreach ($bins as $bin) {
4139
4140  if (isset($previousBin) && $bin === $previousBin.'.bat') {
4141 continue;
4142 }
4143
4144 $previousBin = $bin;
4145 $bin = basename($bin);
4146 $this->getIO()->write(<<<EOT
4147 <info>- $bin</info>
4148 EOT
4149 );
4150 }
4151
4152 return 0;
4153 }
4154
4155 $binary = $input->getArgument('binary');
4156
4157 $dispatcher = $composer->getEventDispatcher();
4158 $dispatcher->addListener('__exec_command', $binary);
4159 if ($output->getVerbosity() === OutputInterface::VERBOSITY_NORMAL) {
4160 $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
4161 }
4162
4163 return $dispatcher->dispatchScript('__exec_command', true, $input->getArgument('args'));
4164 }
4165 }
4166 <?php
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178 namespace Composer\Command;
4179
4180 use Composer\Factory;
4181 use Symfony\Component\Console\Input\InputInterface;
4182 use Symfony\Component\Console\Input\InputArgument;
4183 use Symfony\Component\Console\Input\StringInput;
4184 use Symfony\Component\Console\Output\OutputInterface;
4185
4186
4187
4188
4189 class GlobalCommand extends BaseCommand
4190 {
4191 protected function configure()
4192 {
4193 $this
4194 ->setName('global')
4195 ->setDescription('Allows running commands in the global composer dir ($COMPOSER_HOME).')
4196 ->setDefinition(array(
4197 new InputArgument('command-name', InputArgument::REQUIRED, ''),
4198 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
4199 ))
4200 ->setHelp(<<<EOT
4201 Use this command as a wrapper to run other Composer commands
4202 within the global context of COMPOSER_HOME.
4203
4204 You can use this to install CLI utilities globally, all you need
4205 is to add the COMPOSER_HOME/vendor/bin dir to your PATH env var.
4206
4207 COMPOSER_HOME is c:\Users\<user>\AppData\Roaming\Composer on Windows
4208 and /home/<user>/.composer on unix systems.
4209
4210 If your system uses freedesktop.org standards, then it will first check
4211 XDG_CONFIG_HOME or default to /home/<user>/.config/composer
4212
4213 Note: This path may vary depending on customizations to bin-dir in
4214 composer.json or the environmental variable COMPOSER_BIN_DIR.
4215
4216 EOT
4217 )
4218 ;
4219 }
4220
4221 public function run(InputInterface $input, OutputInterface $output)
4222 {
4223
4224  $tokens = preg_split('{\s+}', $input->__toString());
4225 $args = array();
4226 foreach ($tokens as $token) {
4227 if ($token && $token[0] !== '-') {
4228 $args[] = $token;
4229 if (count($args) >= 2) {
4230 break;
4231 }
4232 }
4233 }
4234
4235
4236  if (count($args) < 2) {
4237 return parent::run($input, $output);
4238 }
4239
4240
4241  $config = Factory::createConfig();
4242 chdir($config->get('home'));
4243 $this->getIO()->writeError('<info>Changed current directory to '.$config->get('home').'</info>');
4244
4245
4246  $input = new StringInput(preg_replace('{\bg(?:l(?:o(?:b(?:a(?:l)?)?)?)?)?\b}', '', $input->__toString(), 1));
4247 $this->getApplication()->resetComposer();
4248
4249 return $this->getApplication()->run($input, $output);
4250 }
4251
4252
4253
4254
4255 public function isProxyCommand()
4256 {
4257 return true;
4258 }
4259 }
4260 <?php
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272 namespace Composer\Command;
4273
4274 use Composer\Package\CompletePackageInterface;
4275 use Composer\Repository\RepositoryInterface;
4276 use Composer\Repository\ArrayRepository;
4277 use Composer\Repository\RepositoryFactory;
4278 use Composer\Util\Platform;
4279 use Composer\Util\ProcessExecutor;
4280 use Symfony\Component\Console\Input\InputArgument;
4281 use Symfony\Component\Console\Input\InputOption;
4282 use Symfony\Component\Console\Input\InputInterface;
4283 use Symfony\Component\Console\Output\OutputInterface;
4284
4285
4286
4287
4288 class HomeCommand extends BaseCommand
4289 {
4290
4291
4292
4293 protected function configure()
4294 {
4295 $this
4296 ->setName('browse')
4297 ->setAliases(array('home'))
4298 ->setDescription('Opens the package\'s repository URL or homepage in your browser.')
4299 ->setDefinition(array(
4300 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'Package(s) to browse to.'),
4301 new InputOption('homepage', 'H', InputOption::VALUE_NONE, 'Open the homepage instead of the repository URL.'),
4302 new InputOption('show', 's', InputOption::VALUE_NONE, 'Only show the homepage or repository URL.'),
4303 ))
4304 ->setHelp(<<<EOT
4305 The home command opens or shows a package's repository URL or
4306 homepage in your default browser.
4307
4308 To open the homepage by default, use -H or --homepage.
4309 To show instead of open the repository or homepage URL, use -s or --show.
4310 EOT
4311 );
4312 }
4313
4314
4315
4316
4317 protected function execute(InputInterface $input, OutputInterface $output)
4318 {
4319 $repos = $this->initializeRepos();
4320 $io = $this->getIO();
4321 $return = 0;
4322
4323 foreach ($input->getArgument('packages') as $packageName) {
4324 $handled = false;
4325 $packageExists = false;
4326 foreach ($repos as $repo) {
4327 foreach ($repo->findPackages($packageName) as $package) {
4328 $packageExists = true;
4329 if ($package instanceof CompletePackageInterface && $this->handlePackage($package, $input->getOption('homepage'), $input->getOption('show'))) {
4330 $handled = true;
4331 break 2;
4332 }
4333 }
4334 }
4335
4336 if (!$packageExists) {
4337 $return = 1;
4338 $io->writeError('<warning>Package '.$packageName.' not found</warning>');
4339 }
4340
4341 if (!$handled) {
4342 $return = 1;
4343 $io->writeError('<warning>'.($input->getOption('homepage') ? 'Invalid or missing homepage' : 'Invalid or missing repository URL').' for '.$packageName.'</warning>');
4344 }
4345 }
4346
4347 return $return;
4348 }
4349
4350 private function handlePackage(CompletePackageInterface $package, $showHomepage, $showOnly)
4351 {
4352 $support = $package->getSupport();
4353 $url = isset($support['source']) ? $support['source'] : $package->getSourceUrl();
4354 if (!$url || $showHomepage) {
4355 $url = $package->getHomepage();
4356 }
4357
4358 if (!$url || !filter_var($url, FILTER_VALIDATE_URL)) {
4359 return false;
4360 }
4361
4362 if ($showOnly) {
4363 $this->getIO()->write(sprintf('<info>%s</info>', $url));
4364 } else {
4365 $this->openBrowser($url);
4366 }
4367
4368 return true;
4369 }
4370
4371
4372
4373
4374
4375
4376 private function openBrowser($url)
4377 {
4378 $url = ProcessExecutor::escape($url);
4379
4380 $process = new ProcessExecutor($this->getIO());
4381 if (Platform::isWindows()) {
4382 return $process->execute('start "web" explorer "' . $url . '"', $output);
4383 }
4384
4385 $linux = $process->execute('which xdg-open', $output);
4386 $osx = $process->execute('which open', $output);
4387
4388 if (0 === $linux) {
4389 $process->execute('xdg-open ' . $url, $output);
4390 } elseif (0 === $osx) {
4391 $process->execute('open ' . $url, $output);
4392 } else {
4393 $this->getIO()->writeError('No suitable browser opening command found, open yourself: ' . $url);
4394 }
4395 }
4396
4397
4398
4399
4400
4401
4402
4403
4404 private function initializeRepos()
4405 {
4406 $composer = $this->getComposer(false);
4407
4408 if ($composer) {
4409 return array_merge(
4410 array(new ArrayRepository(array($composer->getPackage()))), 
4411  array($composer->getRepositoryManager()->getLocalRepository()), 
4412  $composer->getRepositoryManager()->getRepositories() 
4413  );
4414 }
4415
4416 return RepositoryFactory::defaultRepos($this->getIO());
4417 }
4418 }
4419 <?php
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431 namespace Composer\Command;
4432
4433 use Composer\DependencyResolver\Pool;
4434 use Composer\Json\JsonFile;
4435 use Composer\Factory;
4436 use Composer\Repository\RepositoryFactory;
4437 use Composer\Package\BasePackage;
4438 use Composer\Package\Version\VersionParser;
4439 use Composer\Package\Version\VersionSelector;
4440 use Composer\Repository\CompositeRepository;
4441 use Composer\Repository\PlatformRepository;
4442 use Composer\Util\ProcessExecutor;
4443 use Symfony\Component\Console\Input\InputInterface;
4444 use Symfony\Component\Console\Input\InputOption;
4445 use Symfony\Component\Console\Output\OutputInterface;
4446 use Symfony\Component\Process\Process;
4447 use Symfony\Component\Process\ExecutableFinder;
4448
4449
4450
4451
4452
4453 class InitCommand extends BaseCommand
4454 {
4455
4456 protected $repos;
4457
4458
4459 private $gitConfig;
4460
4461
4462 private $pool;
4463
4464
4465
4466
4467 protected function configure()
4468 {
4469 $this
4470 ->setName('init')
4471 ->setDescription('Creates a basic composer.json file in current directory.')
4472 ->setDefinition(array(
4473 new InputOption('name', null, InputOption::VALUE_REQUIRED, 'Name of the package'),
4474 new InputOption('description', null, InputOption::VALUE_REQUIRED, 'Description of package'),
4475 new InputOption('author', null, InputOption::VALUE_REQUIRED, 'Author name of package'),
4476
4477  new InputOption('type', null, InputOption::VALUE_OPTIONAL, 'Type of package (e.g. library, project, metapackage, composer-plugin)'),
4478 new InputOption('homepage', null, InputOption::VALUE_REQUIRED, 'Homepage of package'),
4479 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"'),
4480 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"'),
4481 new InputOption('stability', 's', InputOption::VALUE_REQUIRED, 'Minimum stability (empty or one of: '.implode(', ', array_keys(BasePackage::$stabilities)).')'),
4482 new InputOption('license', 'l', InputOption::VALUE_REQUIRED, 'License of package'),
4483 new InputOption('repository', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'Add custom repositories, either by URL or using JSON arrays'),
4484 ))
4485 ->setHelp(<<<EOT
4486 The <info>init</info> command creates a basic composer.json file
4487 in the current directory.
4488
4489 <info>php composer.phar init</info>
4490
4491 EOT
4492 )
4493 ;
4494 }
4495
4496
4497
4498
4499 protected function execute(InputInterface $input, OutputInterface $output)
4500 {
4501 $io = $this->getIO();
4502
4503 $whitelist = array('name', 'description', 'author', 'type', 'homepage', 'require', 'require-dev', 'stability', 'license');
4504 $options = array_filter(array_intersect_key($input->getOptions(), array_flip($whitelist)));
4505
4506 if (isset($options['author'])) {
4507 $options['authors'] = $this->formatAuthors($options['author']);
4508 unset($options['author']);
4509 }
4510
4511 $repositories = $input->getOption('repository');
4512 if ($repositories) {
4513 $config = Factory::createConfig($io);
4514 foreach ($repositories as $repo) {
4515 $options['repositories'][] = RepositoryFactory::configFromString($io, $config, $repo);
4516 }
4517 }
4518
4519 if (isset($options['stability'])) {
4520 $options['minimum-stability'] = $options['stability'];
4521 unset($options['stability']);
4522 }
4523
4524 $options['require'] = isset($options['require']) ? $this->formatRequirements($options['require']) : new \stdClass;
4525 if (array() === $options['require']) {
4526 $options['require'] = new \stdClass;
4527 }
4528
4529 if (isset($options['require-dev'])) {
4530 $options['require-dev'] = $this->formatRequirements($options['require-dev']);
4531 if (array() === $options['require-dev']) {
4532 $options['require-dev'] = new \stdClass;
4533 }
4534 }
4535
4536 $file = new JsonFile(Factory::getComposerFile());
4537 $json = $file->encode($options);
4538
4539 if ($input->isInteractive()) {
4540 $io->writeError(array('', $json, ''));
4541 if (!$io->askConfirmation('Do you confirm generation [<comment>yes</comment>]? ', true)) {
4542 $io->writeError('<error>Command aborted</error>');
4543
4544 return 1;
4545 }
4546 }
4547
4548 $file->write($options);
4549
4550 if ($input->isInteractive() && is_dir('.git')) {
4551 $ignoreFile = realpath('.gitignore');
4552
4553 if (false === $ignoreFile) {
4554 $ignoreFile = realpath('.') . '/.gitignore';
4555 }
4556
4557 if (!$this->hasVendorIgnore($ignoreFile)) {
4558 $question = 'Would you like the <info>vendor</info> directory added to your <info>.gitignore</info> [<comment>yes</comment>]? ';
4559
4560 if ($io->askConfirmation($question, true)) {
4561 $this->addVendorIgnore($ignoreFile);
4562 }
4563 }
4564 }
4565 }
4566
4567
4568
4569
4570 protected function interact(InputInterface $input, OutputInterface $output)
4571 {
4572 $git = $this->getGitConfig();
4573 $io = $this->getIO();
4574 $formatter = $this->getHelperSet()->get('formatter');
4575
4576
4577  $repositories = $input->getOption('repository');
4578 if ($repositories) {
4579 $config = Factory::createConfig($io);
4580 $repos = array(new PlatformRepository);
4581 foreach ($repositories as $repo) {
4582 $repos[] = RepositoryFactory::fromString($io, $config, $repo);
4583 }
4584 $repos[] = RepositoryFactory::createRepo($io, $config, array(
4585 'type' => 'composer',
4586 'url' => 'https://packagist.org',
4587 ));
4588
4589 $this->repos = new CompositeRepository($repos);
4590 unset($repos, $config, $repositories);
4591 }
4592
4593 $io->writeError(array(
4594 '',
4595 $formatter->formatBlock('Welcome to the Composer config generator', 'bg=blue;fg=white', true),
4596 '',
4597 ));
4598
4599
4600  $io->writeError(array(
4601 '',
4602 'This command will guide you through creating your composer.json config.',
4603 '',
4604 ));
4605
4606 $cwd = realpath(".");
4607
4608 if (!$name = $input->getOption('name')) {
4609 $name = basename($cwd);
4610 $name = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $name);
4611 $name = strtolower($name);
4612 if (isset($git['github.user'])) {
4613 $name = $git['github.user'] . '/' . $name;
4614 } elseif (!empty($_SERVER['USERNAME'])) {
4615 $name = $_SERVER['USERNAME'] . '/' . $name;
4616 } elseif (!empty($_SERVER['USER'])) {
4617 $name = $_SERVER['USER'] . '/' . $name;
4618 } elseif (get_current_user()) {
4619 $name = get_current_user() . '/' . $name;
4620 } else {
4621
4622  $name = $name . '/' . $name;
4623 }
4624 $name = strtolower($name);
4625 } else {
4626 if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}', $name)) {
4627 throw new \InvalidArgumentException(
4628 '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_.-]+'
4629 );
4630 }
4631 }
4632
4633 $name = $io->askAndValidate(
4634 'Package name (<vendor>/<name>) [<comment>'.$name.'</comment>]: ',
4635 function ($value) use ($name) {
4636 if (null === $value) {
4637 return $name;
4638 }
4639
4640 if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}', $value)) {
4641 throw new \InvalidArgumentException(
4642 '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_.-]+'
4643 );
4644 }
4645
4646 return $value;
4647 },
4648 null,
4649 $name
4650 );
4651 $input->setOption('name', $name);
4652
4653 $description = $input->getOption('description') ?: false;
4654 $description = $io->ask(
4655 'Description [<comment>'.$description.'</comment>]: ',
4656 $description
4657 );
4658 $input->setOption('description', $description);
4659
4660 if (null === $author = $input->getOption('author')) {
4661 if (isset($git['user.name']) && isset($git['user.email'])) {
4662 $author = sprintf('%s <%s>', $git['user.name'], $git['user.email']);
4663 }
4664 }
4665
4666 $self = $this;
4667 $author = $io->askAndValidate(
4668 'Author [<comment>'.$author.'</comment>, n to skip]: ',
4669 function ($value) use ($self, $author) {
4670 if ($value === 'n' || $value === 'no') {
4671 return;
4672 }
4673 $value = $value ?: $author;
4674 $author = $self->parseAuthorString($value);
4675
4676 return sprintf('%s <%s>', $author['name'], $author['email']);
4677 },
4678 null,
4679 $author
4680 );
4681 $input->setOption('author', $author);
4682
4683 $minimumStability = $input->getOption('stability') ?: null;
4684 $minimumStability = $io->askAndValidate(
4685 'Minimum Stability [<comment>'.$minimumStability.'</comment>]: ',
4686 function ($value) use ($self, $minimumStability) {
4687 if (null === $value) {
4688 return $minimumStability;
4689 }
4690
4691 if (!isset(BasePackage::$stabilities[$value])) {
4692 throw new \InvalidArgumentException(
4693 'Invalid minimum stability "'.$value.'". Must be empty or one of: '.
4694 implode(', ', array_keys(BasePackage::$stabilities))
4695 );
4696 }
4697
4698 return $value;
4699 },
4700 null,
4701 $minimumStability
4702 );
4703 $input->setOption('stability', $minimumStability);
4704
4705 $type = $input->getOption('type') ?: false;
4706 $type = $io->ask(
4707 'Package Type (e.g. library, project, metapackage, composer-plugin) [<comment>'.$type.'</comment>]: ',
4708 $type
4709 );
4710 $input->setOption('type', $type);
4711
4712 $license = $input->getOption('license') ?: false;
4713 $license = $io->ask(
4714 'License [<comment>'.$license.'</comment>]: ',
4715 $license
4716 );
4717 $input->setOption('license', $license);
4718
4719 $io->writeError(array('', 'Define your dependencies.', ''));
4720
4721 $question = 'Would you like to define your dependencies (require) interactively [<comment>yes</comment>]? ';
4722 $require = $input->getOption('require');
4723 $requirements = array();
4724 if ($require || $io->askConfirmation($question, true)) {
4725 $requirements = $this->determineRequirements($input, $output, $require);
4726 }
4727 $input->setOption('require', $requirements);
4728
4729 $question = 'Would you like to define your dev dependencies (require-dev) interactively [<comment>yes</comment>]? ';
4730 $requireDev = $input->getOption('require-dev');
4731 $devRequirements = array();
4732 if ($requireDev || $io->askConfirmation($question, true)) {
4733 $devRequirements = $this->determineRequirements($input, $output, $requireDev);
4734 }
4735 $input->setOption('require-dev', $devRequirements);
4736 }
4737
4738
4739
4740
4741
4742
4743 public function parseAuthorString($author)
4744 {
4745 if (preg_match('/^(?P<name>[- .,\p{L}\p{N}\p{Mn}\'’"()]+) <(?P<email>.+?)>$/u', $author, $match)) {
4746 if ($this->isValidEmail($match['email'])) {
4747 return array(
4748 'name' => trim($match['name']),
4749 'email' => $match['email'],
4750 );
4751 }
4752 }
4753
4754 throw new \InvalidArgumentException(
4755 'Invalid author string.  Must be in the format: '.
4756 'John Smith <john@example.com>'
4757 );
4758 }
4759
4760 protected function findPackages($name)
4761 {
4762 return $this->getRepos()->search($name);
4763 }
4764
4765 protected function getRepos()
4766 {
4767 if (!$this->repos) {
4768 $this->repos = new CompositeRepository(array_merge(
4769 array(new PlatformRepository),
4770 RepositoryFactory::defaultRepos($this->getIO())
4771 ));
4772 }
4773
4774 return $this->repos;
4775 }
4776
4777 protected function determineRequirements(InputInterface $input, OutputInterface $output, $requires = array(), $phpVersion = null, $preferredStability = 'stable')
4778 {
4779 if ($requires) {
4780 $requires = $this->normalizeRequirements($requires);
4781 $result = array();
4782 $io = $this->getIO();
4783
4784 foreach ($requires as $requirement) {
4785 if (!isset($requirement['version'])) {
4786
4787  $version = $this->findBestVersionForPackage($input, $requirement['name'], $phpVersion, $preferredStability);
4788 $requirement['version'] = $version;
4789
4790 $io->writeError(sprintf(
4791 'Using version <info>%s</info> for <info>%s</info>',
4792 $requirement['version'],
4793 $requirement['name']
4794 ));
4795 }
4796
4797 $result[] = $requirement['name'] . ' ' . $requirement['version'];
4798 }
4799
4800 return $result;
4801 }
4802
4803 $versionParser = new VersionParser();
4804 $io = $this->getIO();
4805 while (null !== $package = $io->ask('Search for a package: ')) {
4806 $matches = $this->findPackages($package);
4807
4808 if (count($matches)) {
4809 $exactMatch = null;
4810 $choices = array();
4811 foreach ($matches as $position => $foundPackage) {
4812 $choices[] = sprintf(' <info>%5s</info> %s', "[$position]", $foundPackage['name']);
4813 if ($foundPackage['name'] === $package) {
4814 $exactMatch = true;
4815 break;
4816 }
4817 }
4818
4819
4820  if (!$exactMatch) {
4821 $io->writeError(array(
4822 '',
4823 sprintf('Found <info>%s</info> packages matching <info>%s</info>', count($matches), $package),
4824 '',
4825 ));
4826
4827 $io->writeError($choices);
4828 $io->writeError('');
4829
4830 $validator = function ($selection) use ($matches, $versionParser) {
4831 if ('' === $selection) {
4832 return false;
4833 }
4834
4835 if (is_numeric($selection) && isset($matches[(int) $selection])) {
4836 $package = $matches[(int) $selection];
4837
4838 return $package['name'];
4839 }
4840
4841 if (preg_match('{^\s*(?P<name>[\S/]+)(?:\s+(?P<version>\S+))?\s*$}', $selection, $packageMatches)) {
4842 if (isset($packageMatches['version'])) {
4843
4844
4845
4846  $versionParser->parseConstraints($packageMatches['version']);
4847
4848 return $packageMatches['name'].' '.$packageMatches['version'];
4849 }
4850
4851
4852  return $packageMatches['name'];
4853 }
4854
4855 throw new \Exception('Not a valid selection');
4856 };
4857
4858 $package = $io->askAndValidate(
4859 'Enter package # to add, or the complete package name if it is not listed: ',
4860 $validator,
4861 3,
4862 false
4863 );
4864 }
4865
4866
4867  if (false !== $package && false === strpos($package, ' ')) {
4868 $validator = function ($input) {
4869 $input = trim($input);
4870
4871 return $input ?: false;
4872 };
4873
4874 $constraint = $io->askAndValidate(
4875 'Enter the version constraint to require (or leave blank to use the latest version): ',
4876 $validator,
4877 3,
4878 false
4879 );
4880
4881 if (false === $constraint) {
4882 $constraint = $this->findBestVersionForPackage($input, $package, $phpVersion, $preferredStability);
4883
4884 $io->writeError(sprintf(
4885 'Using version <info>%s</info> for <info>%s</info>',
4886 $constraint,
4887 $package
4888 ));
4889 }
4890
4891 $package .= ' '.$constraint;
4892 }
4893
4894 if (false !== $package) {
4895 $requires[] = $package;
4896 }
4897 }
4898 }
4899
4900 return $requires;
4901 }
4902
4903 protected function formatAuthors($author)
4904 {
4905 return array($this->parseAuthorString($author));
4906 }
4907
4908 protected function formatRequirements(array $requirements)
4909 {
4910 $requires = array();
4911 $requirements = $this->normalizeRequirements($requirements);
4912 foreach ($requirements as $requirement) {
4913 $requires[$requirement['name']] = $requirement['version'];
4914 }
4915
4916 return $requires;
4917 }
4918
4919 protected function getGitConfig()
4920 {
4921 if (null !== $this->gitConfig) {
4922 return $this->gitConfig;
4923 }
4924
4925 $finder = new ExecutableFinder();
4926 $gitBin = $finder->find('git');
4927
4928 $cmd = new Process(sprintf('%s config -l', ProcessExecutor::escape($gitBin)));
4929 $cmd->run();
4930
4931 if ($cmd->isSuccessful()) {
4932 $this->gitConfig = array();
4933 preg_match_all('{^([^=]+)=(.*)$}m', $cmd->getOutput(), $matches, PREG_SET_ORDER);
4934 foreach ($matches as $match) {
4935 $this->gitConfig[$match[1]] = $match[2];
4936 }
4937
4938 return $this->gitConfig;
4939 }
4940
4941 return $this->gitConfig = array();
4942 }
4943
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957
4958
4959
4960 protected function hasVendorIgnore($ignoreFile, $vendor = 'vendor')
4961 {
4962 if (!file_exists($ignoreFile)) {
4963 return false;
4964 }
4965
4966 $pattern = sprintf('{^/?%s(/\*?)?$}', preg_quote($vendor));
4967
4968 $lines = file($ignoreFile, FILE_IGNORE_NEW_LINES);
4969 foreach ($lines as $line) {
4970 if (preg_match($pattern, $line)) {
4971 return true;
4972 }
4973 }
4974
4975 return false;
4976 }
4977
4978 protected function normalizeRequirements(array $requirements)
4979 {
4980 $parser = new VersionParser();
4981
4982 return $parser->parseNameVersionPairs($requirements);
4983 }
4984
4985 protected function addVendorIgnore($ignoreFile, $vendor = '/vendor/')
4986 {
4987 $contents = "";
4988 if (file_exists($ignoreFile)) {
4989 $contents = file_get_contents($ignoreFile);
4990
4991 if ("\n" !== substr($contents, 0, -1)) {
4992 $contents .= "\n";
4993 }
4994 }
4995
4996 file_put_contents($ignoreFile, $contents . $vendor. "\n");
4997 }
4998
4999 protected function isValidEmail($email)
5000 {
5001
5002  if (!function_exists('filter_var')) {
5003 return true;
5004 }
5005
5006
5007  if (PHP_VERSION_ID < 50303) {
5008 return true;
5009 }
5010
5011 return false !== filter_var($email, FILTER_VALIDATE_EMAIL);
5012 }
5013
5014 private function getPool(InputInterface $input)
5015 {
5016 if (!$this->pool) {
5017 $this->pool = new Pool($this->getMinimumStability($input));
5018 $this->pool->addRepository($this->getRepos());
5019 }
5020
5021 return $this->pool;
5022 }
5023
5024 private function getMinimumStability(InputInterface $input)
5025 {
5026 if ($input->hasOption('stability')) {
5027 return $input->getOption('stability') ?: 'stable';
5028 }
5029
5030 $file = Factory::getComposerFile();
5031 if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
5032 if (!empty($composer['minimum-stability'])) {
5033 return $composer['minimum-stability'];
5034 }
5035 }
5036
5037 return 'stable';
5038 }
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052 private function findBestVersionForPackage(InputInterface $input, $name, $phpVersion, $preferredStability = 'stable')
5053 {
5054
5055  $versionSelector = new VersionSelector($this->getPool($input));
5056 $package = $versionSelector->findBestCandidate($name, null, $phpVersion, $preferredStability);
5057
5058 if (!$package) {
5059
5060  if ($phpVersion && $versionSelector->findBestCandidate($name)) {
5061 throw new \InvalidArgumentException(sprintf(
5062 'Could not find package %s at any version matching your PHP version %s', $name, $phpVersion
5063 ));
5064 }
5065 throw new \InvalidArgumentException(sprintf(
5066 'Could not find package %s at any version for your minimum-stability (%s). Check the package spelling or your minimum-stability',
5067 $name,
5068 $this->getMinimumStability($input)
5069 ));
5070 }
5071
5072 return $versionSelector->findRecommendedRequireVersion($package);
5073 }
5074 }
5075 <?php
5076
5077
5078
5079
5080
5081
5082
5083
5084
5085
5086
5087 namespace Composer\Command;
5088
5089 use Composer\Installer;
5090 use Composer\Plugin\CommandEvent;
5091 use Composer\Plugin\PluginEvents;
5092 use Symfony\Component\Console\Input\InputInterface;
5093 use Symfony\Component\Console\Input\InputOption;
5094 use Symfony\Component\Console\Input\InputArgument;
5095 use Symfony\Component\Console\Output\OutputInterface;
5096
5097
5098
5099
5100
5101
5102
5103 class InstallCommand extends BaseCommand
5104 {
5105 protected function configure()
5106 {
5107 $this
5108 ->setName('install')
5109 ->setDescription('Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json.')
5110 ->setDefinition(array(
5111 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
5112 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
5113 new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
5114 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
5115 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
5116 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
5117 new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
5118 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
5119 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
5120 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
5121 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
5122 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
5123 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
5124 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
5125 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
5126 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Should not be provided, use composer require instead to add a given package to composer.json.'),
5127 ))
5128 ->setHelp(<<<EOT
5129 The <info>install</info> command reads the composer.lock file from
5130 the current directory, processes it, and downloads and installs all the
5131 libraries and dependencies outlined in that file. If the file does not
5132 exist it will look for composer.json and do the same.
5133
5134 <info>php composer.phar install</info>
5135
5136 EOT
5137 )
5138 ;
5139 }
5140
5141 protected function execute(InputInterface $input, OutputInterface $output)
5142 {
5143 $io = $this->getIO();
5144 if ($args = $input->getArgument('packages')) {
5145 $io->writeError('<error>Invalid argument '.implode(' ', $args).'. Use "composer require '.implode(' ', $args).'" instead to add packages to your composer.json.</error>');
5146
5147 return 1;
5148 }
5149
5150 if ($input->getOption('no-custom-installers')) {
5151 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
5152 $input->setOption('no-plugins', true);
5153 }
5154
5155 if ($input->getOption('dev')) {
5156 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
5157 }
5158
5159 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
5160 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
5161
5162 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'install', $input, $output);
5163 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5164
5165 $install = Installer::create($io, $composer);
5166
5167 $config = $composer->getConfig();
5168 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
5169
5170 $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
5171 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
5172 $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
5173
5174 $install
5175 ->setDryRun($input->getOption('dry-run'))
5176 ->setVerbose($input->getOption('verbose'))
5177 ->setPreferSource($preferSource)
5178 ->setPreferDist($preferDist)
5179 ->setDevMode(!$input->getOption('no-dev'))
5180 ->setDumpAutoloader(!$input->getOption('no-autoloader'))
5181 ->setRunScripts(!$input->getOption('no-scripts'))
5182 ->setSkipSuggest($input->getOption('no-suggest'))
5183 ->setOptimizeAutoloader($optimize)
5184 ->setClassMapAuthoritative($authoritative)
5185 ->setApcuAutoloader($apcu)
5186 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
5187 ;
5188
5189 if ($input->getOption('no-plugins')) {
5190 $install->disablePlugins();
5191 }
5192
5193 return $install->run();
5194 }
5195 }
5196 <?php
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208 namespace Composer\Command;
5209
5210 use Composer\Json\JsonFile;
5211 use Composer\Plugin\CommandEvent;
5212 use Composer\Plugin\PluginEvents;
5213 use Composer\Package\PackageInterface;
5214 use Composer\Repository\RepositoryInterface;
5215 use Symfony\Component\Console\Helper\Table;
5216 use Symfony\Component\Console\Input\InputInterface;
5217 use Symfony\Component\Console\Input\InputOption;
5218 use Symfony\Component\Console\Output\OutputInterface;
5219
5220
5221
5222
5223 class LicensesCommand extends BaseCommand
5224 {
5225 protected function configure()
5226 {
5227 $this
5228 ->setName('licenses')
5229 ->setDescription('Shows information about licenses of dependencies.')
5230 ->setDefinition(array(
5231 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
5232 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables search in require-dev packages.'),
5233 ))
5234 ->setHelp(<<<EOT
5235 The license command displays detailed information about the licenses of
5236 the installed dependencies.
5237
5238 EOT
5239 )
5240 ;
5241 }
5242
5243 protected function execute(InputInterface $input, OutputInterface $output)
5244 {
5245 $composer = $this->getComposer();
5246
5247 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'licenses', $input, $output);
5248 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5249
5250 $root = $composer->getPackage();
5251 $repo = $composer->getRepositoryManager()->getLocalRepository();
5252
5253 if ($input->getOption('no-dev')) {
5254 $packages = $this->filterRequiredPackages($repo, $root);
5255 } else {
5256 $packages = $this->appendPackages($repo->getPackages(), array());
5257 }
5258
5259 ksort($packages);
5260 $io = $this->getIO();
5261
5262 switch ($format = $input->getOption('format')) {
5263 case 'text':
5264 $io->write('Name: <comment>'.$root->getPrettyName().'</comment>');
5265 $io->write('Version: <comment>'.$root->getFullPrettyVersion().'</comment>');
5266 $io->write('Licenses: <comment>'.(implode(', ', $root->getLicense()) ?: 'none').'</comment>');
5267 $io->write('Dependencies:');
5268 $io->write('');
5269
5270 $table = new Table($output);
5271 $table->setStyle('compact');
5272 $table->getStyle()->setVerticalBorderChar('');
5273 $table->getStyle()->setCellRowContentFormat('%s  ');
5274 $table->setHeaders(array('Name', 'Version', 'License'));
5275 foreach ($packages as $package) {
5276 $table->addRow(array(
5277 $package->getPrettyName(),
5278 $package->getFullPrettyVersion(),
5279 implode(', ', $package->getLicense()) ?: 'none',
5280 ));
5281 }
5282 $table->render();
5283 break;
5284
5285 case 'json':
5286 $dependencies = array();
5287 foreach ($packages as $package) {
5288 $dependencies[$package->getPrettyName()] = array(
5289 'version' => $package->getFullPrettyVersion(),
5290 'license' => $package->getLicense(),
5291 );
5292 }
5293
5294 $io->write(JsonFile::encode(array(
5295 'name' => $root->getPrettyName(),
5296 'version' => $root->getFullPrettyVersion(),
5297 'license' => $root->getLicense(),
5298 'dependencies' => $dependencies,
5299 )));
5300 break;
5301
5302 default:
5303 throw new \RuntimeException(sprintf('Unsupported format "%s".  See help for supported formats.', $format));
5304 }
5305 }
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315 private function filterRequiredPackages(RepositoryInterface $repo, PackageInterface $package, $bucket = array())
5316 {
5317 $requires = array_keys($package->getRequires());
5318
5319 $packageListNames = array_keys($bucket);
5320 $packages = array_filter(
5321 $repo->getPackages(),
5322 function ($package) use ($requires, $packageListNames) {
5323 return in_array($package->getName(), $requires) && !in_array($package->getName(), $packageListNames);
5324 }
5325 );
5326
5327 $bucket = $this->appendPackages($packages, $bucket);
5328
5329 foreach ($packages as $package) {
5330 $bucket = $this->filterRequiredPackages($repo, $package, $bucket);
5331 }
5332
5333 return $bucket;
5334 }
5335
5336
5337
5338
5339
5340
5341
5342
5343 public function appendPackages(array $packages, array $bucket)
5344 {
5345 foreach ($packages as $package) {
5346 $bucket[$package->getName()] = $package;
5347 }
5348
5349 return $bucket;
5350 }
5351 }
5352 <?php
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364 namespace Composer\Command;
5365
5366 use Symfony\Component\Console\Input\InputInterface;
5367 use Symfony\Component\Console\Input\InputArgument;
5368 use Symfony\Component\Console\Input\ArrayInput;
5369 use Symfony\Component\Console\Input\InputOption;
5370 use Symfony\Component\Console\Output\OutputInterface;
5371
5372
5373
5374
5375 class OutdatedCommand extends ShowCommand
5376 {
5377 protected function configure()
5378 {
5379 $this
5380 ->setName('outdated')
5381 ->setDescription('Shows a list of installed packages that have updates available, including their latest version.')
5382 ->setDefinition(array(
5383 new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
5384 new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show only packages that are outdated (this is the default, but present here for compat with `show`'),
5385 new InputOption('all', 'a', InputOption::VALUE_NONE, 'Show all installed packages with their latest versions'),
5386 new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
5387 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
5388 new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
5389 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
5390 ))
5391 ->setHelp(<<<EOT
5392 The outdated command is just a proxy for `composer show -l`
5393
5394 The color coding (or signage if you have ANSI colors disabled) for dependency versions is as such:
5395
5396 - <info>green</info> (=): Dependency is in the latest version and is up to date.
5397 - <comment>yellow</comment> (~): Dependency has a new version available that includes backwards
5398   compatibility breaks according to semver, so upgrade when you can but it
5399   may involve work.
5400 - <highlight>red</highlight> (!): Dependency has a new version that is semver-compatible and you should upgrade it.
5401
5402
5403 EOT
5404 )
5405 ;
5406 }
5407
5408 protected function execute(InputInterface $input, OutputInterface $output)
5409 {
5410 $args = array(
5411 'show',
5412 '--latest' => true,
5413 );
5414 if (!$input->getOption('all')) {
5415 $args['--outdated'] = true;
5416 }
5417 if ($input->getOption('direct')) {
5418 $args['--direct'] = true;
5419 }
5420 if ($input->getArgument('package')) {
5421 $args['package'] = $input->getArgument('package');
5422 }
5423 if ($input->getOption('strict')) {
5424 $args['--strict'] = true;
5425 }
5426 if ($input->getOption('minor-only')) {
5427 $args['--minor-only'] = true;
5428 }
5429 $args['--format'] = $input->getOption('format');
5430
5431 $input = new ArrayInput($args);
5432
5433 return $this->getApplication()->run($input, $output);
5434 }
5435
5436
5437
5438
5439 public function isProxyCommand()
5440 {
5441 return true;
5442 }
5443 }
5444 <?php
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456 namespace Composer\Command;
5457
5458 use Symfony\Component\Console\Input\InputInterface;
5459 use Symfony\Component\Console\Output\OutputInterface;
5460
5461
5462
5463
5464 class ProhibitsCommand extends BaseDependencyCommand
5465 {
5466
5467
5468
5469 protected function configure()
5470 {
5471 parent::configure();
5472
5473 $this
5474 ->setName('prohibits')
5475 ->setAliases(array('why-not'))
5476 ->setDescription('Shows which packages prevent the given package from being installed.')
5477 ->setHelp(<<<EOT
5478 Displays detailed information about why a package cannot be installed.
5479
5480 <info>php composer.phar prohibits composer/composer</info>
5481
5482 EOT
5483 )
5484 ;
5485 }
5486
5487
5488
5489
5490
5491
5492
5493
5494 protected function execute(InputInterface $input, OutputInterface $output)
5495 {
5496 return parent::doExecute($input, $output, true);
5497 }
5498 }
5499 <?php
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511 namespace Composer\Command;
5512
5513 use Composer\Config\JsonConfigSource;
5514 use Composer\Installer;
5515 use Composer\Plugin\CommandEvent;
5516 use Composer\Plugin\PluginEvents;
5517 use Composer\Json\JsonFile;
5518 use Composer\Factory;
5519 use Symfony\Component\Console\Input\InputInterface;
5520 use Symfony\Component\Console\Input\InputOption;
5521 use Symfony\Component\Console\Input\InputArgument;
5522 use Symfony\Component\Console\Output\OutputInterface;
5523
5524
5525
5526
5527
5528 class RemoveCommand extends BaseCommand
5529 {
5530 protected function configure()
5531 {
5532 $this
5533 ->setName('remove')
5534 ->setDescription('Removes a package from the require or require-dev.')
5535 ->setDefinition(array(
5536 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'Packages that should be removed.'),
5537 new InputOption('dev', null, InputOption::VALUE_NONE, 'Removes a package from the require-dev section.'),
5538 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
5539 new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
5540 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
5541 new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
5542 new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies. (Deprecrated, is now default behavior)'),
5543 new InputOption('no-update-with-dependencies', null, InputOption::VALUE_NONE, 'Does not allow inherited dependencies to be updated with explicit dependencies.'),
5544 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
5545 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
5546 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
5547 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
5548 ))
5549 ->setHelp(<<<EOT
5550 The <info>remove</info> command removes a package from the current
5551 list of installed packages
5552
5553 <info>php composer.phar remove</info>
5554
5555 EOT
5556 )
5557 ;
5558 }
5559
5560 protected function execute(InputInterface $input, OutputInterface $output)
5561 {
5562 $packages = $input->getArgument('packages');
5563 $packages = array_map('strtolower', $packages);
5564
5565 $file = Factory::getComposerFile();
5566
5567 $jsonFile = new JsonFile($file);
5568 $composer = $jsonFile->read();
5569 $composerBackup = file_get_contents($jsonFile->getPath());
5570
5571 $json = new JsonConfigSource($jsonFile);
5572
5573 $type = $input->getOption('dev') ? 'require-dev' : 'require';
5574 $altType = !$input->getOption('dev') ? 'require-dev' : 'require';
5575 $io = $this->getIO();
5576
5577 if ($input->getOption('update-with-dependencies')) {
5578 $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>');
5579 }
5580
5581
5582  foreach (array('require', 'require-dev') as $linkType) {
5583 if (isset($composer[$linkType])) {
5584 foreach ($composer[$linkType] as $name => $version) {
5585 $composer[$linkType][strtolower($name)] = $name;
5586 }
5587 }
5588 }
5589
5590 foreach ($packages as $package) {
5591 if (isset($composer[$type][$package])) {
5592 $json->removeLink($type, $composer[$type][$package]);
5593 } elseif (isset($composer[$altType][$package])) {
5594 $io->writeError('<warning>'.$composer[$altType][$package].' could not be found in '.$type.' but it is present in '.$altType.'</warning>');
5595 if ($io->isInteractive()) {
5596 if ($io->askConfirmation('Do you want to remove it from '.$altType.' [<comment>yes</comment>]? ', true)) {
5597 $json->removeLink($altType, $composer[$altType][$package]);
5598 }
5599 }
5600 } else {
5601 $io->writeError('<warning>'.$package.' is not required in your composer.json and has not been removed</warning>');
5602 }
5603 }
5604
5605 if ($input->getOption('no-update')) {
5606 return 0;
5607 }
5608
5609
5610  $this->resetComposer();
5611 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
5612 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
5613
5614 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'remove', $input, $output);
5615 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5616
5617 $install = Installer::create($io, $composer);
5618
5619 $updateDevMode = !$input->getOption('update-no-dev');
5620 $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
5621 $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
5622 $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
5623
5624 $install
5625 ->setVerbose($input->getOption('verbose'))
5626 ->setDevMode($updateDevMode)
5627 ->setOptimizeAutoloader($optimize)
5628 ->setClassMapAuthoritative($authoritative)
5629 ->setApcuAutoloader($apcu)
5630 ->setUpdate(true)
5631 ->setUpdateWhitelist($packages)
5632 ->setWhitelistDependencies(!$input->getOption('no-update-with-dependencies'))
5633 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
5634 ->setRunScripts(!$input->getOption('no-scripts'))
5635 ;
5636
5637 $exception = null;
5638 try {
5639 $status = $install->run();
5640 } catch (\Exception $exception) {
5641 $status = 1;
5642 }
5643 if ($status !== 0) {
5644 $io->writeError("\n".'<error>Removal failed, reverting '.$file.' to its original content.</error>');
5645 file_put_contents($jsonFile->getPath(), $composerBackup);
5646 }
5647 if ($exception) {
5648 throw $exception;
5649 }
5650
5651 return $status;
5652 }
5653 }
5654 <?php
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666 namespace Composer\Command;
5667
5668 use Symfony\Component\Console\Input\InputInterface;
5669 use Symfony\Component\Console\Input\InputArgument;
5670 use Symfony\Component\Console\Input\InputOption;
5671 use Symfony\Component\Console\Output\OutputInterface;
5672 use Composer\Factory;
5673 use Composer\Installer;
5674 use Composer\Json\JsonFile;
5675 use Composer\Json\JsonManipulator;
5676 use Composer\Package\Version\VersionParser;
5677 use Composer\Plugin\CommandEvent;
5678 use Composer\Plugin\PluginEvents;
5679 use Composer\Repository\CompositeRepository;
5680 use Composer\Repository\PlatformRepository;
5681
5682
5683
5684
5685
5686 class RequireCommand extends InitCommand
5687 {
5688 protected function configure()
5689 {
5690 $this
5691 ->setName('require')
5692 ->setDescription('Adds required packages to your composer.json and installs them.')
5693 ->setDefinition(array(
5694 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"'),
5695 new InputOption('dev', null, InputOption::VALUE_NONE, 'Add requirement to require-dev.'),
5696 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
5697 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
5698 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
5699 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
5700 new InputOption('no-update', null, InputOption::VALUE_NONE, 'Disables the automatic update of the dependencies.'),
5701 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
5702 new InputOption('update-no-dev', null, InputOption::VALUE_NONE, 'Run the dependency update with the --no-dev option.'),
5703 new InputOption('update-with-dependencies', null, InputOption::VALUE_NONE, 'Allows inherited dependencies to be updated with explicit dependencies.'),
5704 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
5705 new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
5706 new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
5707 new InputOption('sort-packages', null, InputOption::VALUE_NONE, 'Sorts packages when adding/updating a new dependency'),
5708 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump'),
5709 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
5710 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
5711 ))
5712 ->setHelp(<<<EOT
5713 The require command adds required packages to your composer.json and installs them.
5714
5715 If you do not specify a version constraint, composer will choose a suitable one based on the available package versions.
5716
5717 If you do not want to install the new dependencies immediately you can call it with --no-update
5718
5719 EOT
5720 )
5721 ;
5722 }
5723
5724 protected function execute(InputInterface $input, OutputInterface $output)
5725 {
5726 $file = Factory::getComposerFile();
5727 $io = $this->getIO();
5728
5729 $newlyCreated = !file_exists($file);
5730 if ($newlyCreated && !file_put_contents($file, "{\n}\n")) {
5731 $io->writeError('<error>'.$file.' could not be created.</error>');
5732
5733 return 1;
5734 }
5735 if (!is_readable($file)) {
5736 $io->writeError('<error>'.$file.' is not readable.</error>');
5737
5738 return 1;
5739 }
5740 if (!is_writable($file)) {
5741 $io->writeError('<error>'.$file.' is not writable.</error>');
5742
5743 return 1;
5744 }
5745
5746 if (filesize($file) === 0) {
5747 file_put_contents($file, "{\n}\n");
5748 }
5749
5750 $json = new JsonFile($file);
5751 $composerBackup = file_get_contents($json->getPath());
5752
5753 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
5754 $repos = $composer->getRepositoryManager()->getRepositories();
5755
5756 $platformOverrides = $composer->getConfig()->get('platform') ?: array();
5757
5758  $this->repos = new CompositeRepository(array_merge(
5759 array(new PlatformRepository(array(), $platformOverrides)),
5760 $repos
5761 ));
5762
5763 if ($composer->getPackage()->getPreferStable()) {
5764 $preferredStability = 'stable';
5765 } else {
5766 $preferredStability = $composer->getPackage()->getMinimumStability();
5767 }
5768
5769 $phpVersion = $this->repos->findPackage('php', '*')->getVersion();
5770 $requirements = $this->determineRequirements($input, $output, $input->getArgument('packages'), $phpVersion, $preferredStability);
5771
5772 $requireKey = $input->getOption('dev') ? 'require-dev' : 'require';
5773 $removeKey = $input->getOption('dev') ? 'require' : 'require-dev';
5774 $requirements = $this->formatRequirements($requirements);
5775
5776
5777  $versionParser = new VersionParser();
5778 foreach ($requirements as $constraint) {
5779 $versionParser->parseConstraints($constraint);
5780 }
5781
5782 $sortPackages = $input->getOption('sort-packages') || $composer->getConfig()->get('sort-packages');
5783
5784 if (!$this->updateFileCleanly($json, $requirements, $requireKey, $removeKey, $sortPackages)) {
5785 $composerDefinition = $json->read();
5786 foreach ($requirements as $package => $version) {
5787 $composerDefinition[$requireKey][$package] = $version;
5788 unset($composerDefinition[$removeKey][$package]);
5789 }
5790 $json->write($composerDefinition);
5791 }
5792
5793 $io->writeError('<info>'.$file.' has been '.($newlyCreated ? 'created' : 'updated').'</info>');
5794
5795 if ($input->getOption('no-update')) {
5796 return 0;
5797 }
5798 $updateDevMode = !$input->getOption('update-no-dev');
5799 $optimize = $input->getOption('optimize-autoloader') || $composer->getConfig()->get('optimize-autoloader');
5800 $authoritative = $input->getOption('classmap-authoritative') || $composer->getConfig()->get('classmap-authoritative');
5801 $apcu = $input->getOption('apcu-autoloader') || $composer->getConfig()->get('apcu-autoloader');
5802
5803
5804  $this->resetComposer();
5805 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
5806 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
5807
5808 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'require', $input, $output);
5809 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
5810
5811 $install = Installer::create($io, $composer);
5812
5813 $install
5814 ->setVerbose($input->getOption('verbose'))
5815 ->setPreferSource($input->getOption('prefer-source'))
5816 ->setPreferDist($input->getOption('prefer-dist'))
5817 ->setDevMode($updateDevMode)
5818 ->setRunScripts(!$input->getOption('no-scripts'))
5819 ->setSkipSuggest($input->getOption('no-suggest'))
5820 ->setOptimizeAutoloader($optimize)
5821 ->setClassMapAuthoritative($authoritative)
5822 ->setApcuAutoloader($apcu)
5823 ->setUpdate(true)
5824 ->setUpdateWhitelist(array_keys($requirements))
5825 ->setWhitelistDependencies($input->getOption('update-with-dependencies'))
5826 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
5827 ->setPreferStable($input->getOption('prefer-stable'))
5828 ->setPreferLowest($input->getOption('prefer-lowest'))
5829 ;
5830
5831 $exception = null;
5832 try {
5833 $status = $install->run();
5834 } catch (\Exception $exception) {
5835 $status = 1;
5836 }
5837 if ($status !== 0) {
5838 if ($newlyCreated) {
5839 $io->writeError("\n".'<error>Installation failed, deleting '.$file.'.</error>');
5840 unlink($json->getPath());
5841 } else {
5842 $io->writeError("\n".'<error>Installation failed, reverting '.$file.' to its original content.</error>');
5843 file_put_contents($json->getPath(), $composerBackup);
5844 }
5845 }
5846 if ($exception) {
5847 throw $exception;
5848 }
5849
5850 return $status;
5851 }
5852
5853 private function updateFileCleanly($json, array $new, $requireKey, $removeKey, $sortPackages)
5854 {
5855 $contents = file_get_contents($json->getPath());
5856
5857 $manipulator = new JsonManipulator($contents);
5858
5859 foreach ($new as $package => $constraint) {
5860 if (!$manipulator->addLink($requireKey, $package, $constraint, $sortPackages)) {
5861 return false;
5862 }
5863 if (!$manipulator->removeSubNode($removeKey, $package)) {
5864 return false;
5865 }
5866 }
5867
5868 file_put_contents($json->getPath(), $manipulator->getContents());
5869
5870 return true;
5871 }
5872
5873 protected function interact(InputInterface $input, OutputInterface $output)
5874 {
5875 return;
5876 }
5877 }
5878 <?php
5879
5880
5881
5882
5883
5884
5885
5886
5887
5888
5889
5890 namespace Composer\Command;
5891
5892 use Composer\Script\Event as ScriptEvent;
5893 use Composer\Script\ScriptEvents;
5894 use Composer\Util\ProcessExecutor;
5895 use Symfony\Component\Console\Input\InputInterface;
5896 use Symfony\Component\Console\Input\InputOption;
5897 use Symfony\Component\Console\Input\InputArgument;
5898 use Symfony\Component\Console\Output\OutputInterface;
5899
5900
5901
5902
5903 class RunScriptCommand extends BaseCommand
5904 {
5905
5906
5907
5908 protected $scriptEvents = array(
5909 ScriptEvents::PRE_INSTALL_CMD,
5910 ScriptEvents::POST_INSTALL_CMD,
5911 ScriptEvents::PRE_UPDATE_CMD,
5912 ScriptEvents::POST_UPDATE_CMD,
5913 ScriptEvents::PRE_STATUS_CMD,
5914 ScriptEvents::POST_STATUS_CMD,
5915 ScriptEvents::POST_ROOT_PACKAGE_INSTALL,
5916 ScriptEvents::POST_CREATE_PROJECT_CMD,
5917 ScriptEvents::PRE_ARCHIVE_CMD,
5918 ScriptEvents::POST_ARCHIVE_CMD,
5919 ScriptEvents::PRE_AUTOLOAD_DUMP,
5920 ScriptEvents::POST_AUTOLOAD_DUMP,
5921 );
5922
5923 protected function configure()
5924 {
5925 $this
5926 ->setName('run-script')
5927 ->setDescription('Runs the scripts defined in composer.json.')
5928 ->setDefinition(array(
5929 new InputArgument('script', InputArgument::OPTIONAL, 'Script name to run.'),
5930 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
5931 new InputOption('timeout', null, InputOption::VALUE_REQUIRED, 'Sets script timeout in seconds, or 0 for never.'),
5932 new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
5933 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
5934 new InputOption('list', 'l', InputOption::VALUE_NONE, 'List scripts.'),
5935 ))
5936 ->setHelp(<<<EOT
5937 The <info>run-script</info> command runs scripts defined in composer.json:
5938
5939 <info>php composer.phar run-script post-update-cmd</info>
5940 EOT
5941 )
5942 ;
5943 }
5944
5945 protected function execute(InputInterface $input, OutputInterface $output)
5946 {
5947 if ($input->getOption('list')) {
5948 return $this->listScripts();
5949 } elseif (!$input->getArgument('script')) {
5950 throw new \RuntimeException('Missing required argument "script"');
5951 }
5952
5953 $script = $input->getArgument('script');
5954 if (!in_array($script, $this->scriptEvents)) {
5955 if (defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
5956 throw new \InvalidArgumentException(sprintf('Script "%s" cannot be run with this command', $script));
5957 }
5958 }
5959
5960 $composer = $this->getComposer();
5961 $devMode = $input->getOption('dev') || !$input->getOption('no-dev');
5962 $event = new ScriptEvent($script, $composer, $this->getIO(), $devMode);
5963 $hasListeners = $composer->getEventDispatcher()->hasEventListeners($event);
5964 if (!$hasListeners) {
5965 throw new \InvalidArgumentException(sprintf('Script "%s" is not defined in this package', $script));
5966 }
5967
5968 $args = $input->getArgument('args');
5969
5970 if (!is_null($timeout = $input->getOption('timeout'))) {
5971 if (!ctype_digit($timeout)) {
5972 throw new \RuntimeException('Timeout value must be numeric and positive if defined, or 0 for forever');
5973 }
5974
5975  ProcessExecutor::setTimeout((int) $timeout);
5976 }
5977
5978 return $composer->getEventDispatcher()->dispatchScript($script, $devMode, $args);
5979 }
5980
5981 protected function listScripts()
5982 {
5983 $scripts = $this->getComposer()->getPackage()->getScripts();
5984
5985 if (!count($scripts)) {
5986 return 0;
5987 }
5988
5989 $io = $this->getIO();
5990 $io->writeError('<info>scripts:</info>');
5991 foreach ($scripts as $name => $script) {
5992 $io->write('  ' . $name);
5993 }
5994
5995 return 0;
5996 }
5997 }
5998 <?php
5999
6000
6001
6002
6003
6004
6005
6006
6007
6008
6009
6010 namespace Composer\Command;
6011
6012 use Symfony\Component\Console\Input\InputInterface;
6013 use Symfony\Component\Console\Input\InputOption;
6014 use Symfony\Component\Console\Input\InputArgument;
6015 use Symfony\Component\Console\Output\OutputInterface;
6016
6017
6018
6019
6020 class ScriptAliasCommand extends BaseCommand
6021 {
6022 private $script;
6023
6024 public function __construct($script)
6025 {
6026 $this->script = $script;
6027
6028 parent::__construct();
6029 }
6030
6031 protected function configure()
6032 {
6033 $this
6034 ->setName($this->script)
6035 ->setDescription('Runs the '.$this->script.' script as defined in composer.json.')
6036 ->setDefinition(array(
6037 new InputOption('dev', null, InputOption::VALUE_NONE, 'Sets the dev mode.'),
6038 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables the dev mode.'),
6039 new InputArgument('args', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, ''),
6040 ))
6041 ->setHelp(<<<EOT
6042 The <info>run-script</info> command runs scripts defined in composer.json:
6043
6044 <info>php composer.phar run-script post-update-cmd</info>
6045 EOT
6046 )
6047 ;
6048 }
6049
6050 protected function execute(InputInterface $input, OutputInterface $output)
6051 {
6052 $composer = $this->getComposer();
6053
6054 $args = $input->getArguments();
6055
6056 return $composer->getEventDispatcher()->dispatchScript($this->script, $input->getOption('dev') || !$input->getOption('no-dev'), $args['args']);
6057 }
6058 }
6059 <?php
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071 namespace Composer\Command;
6072
6073 use Composer\Factory;
6074 use Symfony\Component\Console\Input\InputInterface;
6075 use Symfony\Component\Console\Input\InputArgument;
6076 use Symfony\Component\Console\Input\InputOption;
6077 use Symfony\Component\Console\Output\OutputInterface;
6078 use Composer\Repository\CompositeRepository;
6079 use Composer\Repository\PlatformRepository;
6080 use Composer\Repository\RepositoryInterface;
6081 use Composer\Plugin\CommandEvent;
6082 use Composer\Plugin\PluginEvents;
6083
6084
6085
6086
6087 class SearchCommand extends BaseCommand
6088 {
6089 protected $matches;
6090 protected $lowMatches = array();
6091 protected $tokens;
6092 protected $output;
6093 protected $onlyName;
6094
6095 protected function configure()
6096 {
6097 $this
6098 ->setName('search')
6099 ->setDescription('Searches for packages.')
6100 ->setDefinition(array(
6101 new InputOption('only-name', 'N', InputOption::VALUE_NONE, 'Search only in name'),
6102 new InputOption('type', 't', InputOption::VALUE_REQUIRED, 'Search for a specific package type'),
6103 new InputArgument('tokens', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'tokens to search for'),
6104 ))
6105 ->setHelp(<<<EOT
6106 The search command searches for packages by its name
6107 <info>php composer.phar search symfony composer</info>
6108
6109 EOT
6110 )
6111 ;
6112 }
6113
6114 protected function execute(InputInterface $input, OutputInterface $output)
6115 {
6116
6117  $platformRepo = new PlatformRepository;
6118 $io = $this->getIO();
6119 if (!($composer = $this->getComposer(false))) {
6120 $composer = Factory::create($this->getIO(), array());
6121 }
6122 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
6123 $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
6124 $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
6125
6126 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'search', $input, $output);
6127 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6128
6129 $onlyName = $input->getOption('only-name');
6130 $type = $input->getOption('type') ?: null;
6131
6132 $flags = $onlyName ? RepositoryInterface::SEARCH_NAME : RepositoryInterface::SEARCH_FULLTEXT;
6133 $results = $repos->search(implode(' ', $input->getArgument('tokens')), $flags, $type);
6134
6135 foreach ($results as $result) {
6136 $io->write($result['name'] . (isset($result['description']) ? ' '. $result['description'] : ''));
6137 }
6138 }
6139 }
6140 <?php
6141
6142
6143
6144
6145
6146
6147
6148
6149
6150
6151
6152 namespace Composer\Command;
6153
6154 use Composer\Composer;
6155 use Composer\Factory;
6156 use Composer\Config;
6157 use Composer\Util\Filesystem;
6158 use Composer\SelfUpdate\Keys;
6159 use Composer\SelfUpdate\Versions;
6160 use Composer\IO\IOInterface;
6161 use Composer\Downloader\FilesystemException;
6162 use Symfony\Component\Console\Input\InputInterface;
6163 use Symfony\Component\Console\Input\InputOption;
6164 use Symfony\Component\Console\Input\InputArgument;
6165 use Symfony\Component\Console\Output\OutputInterface;
6166 use Symfony\Component\Finder\Finder;
6167
6168
6169
6170
6171
6172
6173 class SelfUpdateCommand extends BaseCommand
6174 {
6175 const HOMEPAGE = 'getcomposer.org';
6176 const OLD_INSTALL_EXT = '-old.phar';
6177
6178 protected function configure()
6179 {
6180 $this
6181 ->setName('self-update')
6182 ->setAliases(array('selfupdate'))
6183 ->setDescription('Updates composer.phar to the latest version.')
6184 ->setDefinition(array(
6185 new InputOption('rollback', 'r', InputOption::VALUE_NONE, 'Revert to an older installation of composer'),
6186 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'),
6187 new InputArgument('version', InputArgument::OPTIONAL, 'The version to update to'),
6188 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
6189 new InputOption('update-keys', null, InputOption::VALUE_NONE, 'Prompt user for a key update'),
6190 new InputOption('stable', null, InputOption::VALUE_NONE, 'Force an update to the stable channel'),
6191 new InputOption('preview', null, InputOption::VALUE_NONE, 'Force an update to the preview channel'),
6192 new InputOption('snapshot', null, InputOption::VALUE_NONE, 'Force an update to the snapshot channel'),
6193 new InputOption('set-channel-only', null, InputOption::VALUE_NONE, 'Only store the channel as the default one and then exit'),
6194 ))
6195 ->setHelp(<<<EOT
6196 The <info>self-update</info> command checks getcomposer.org for newer
6197 versions of composer and if found, installs the latest.
6198
6199 <info>php composer.phar self-update</info>
6200
6201 EOT
6202 )
6203 ;
6204 }
6205
6206 protected function execute(InputInterface $input, OutputInterface $output)
6207 {
6208 $config = Factory::createConfig();
6209
6210 if ($config->get('disable-tls') === true) {
6211 $baseUrl = 'http://' . self::HOMEPAGE;
6212 } else {
6213 $baseUrl = 'https://' . self::HOMEPAGE;
6214 }
6215
6216 $io = $this->getIO();
6217 $remoteFilesystem = Factory::createRemoteFilesystem($io, $config);
6218
6219 $versionsUtil = new Versions($config, $remoteFilesystem);
6220
6221
6222  foreach (array('stable', 'preview', 'snapshot') as $channel) {
6223 if ($input->getOption($channel)) {
6224 $versionsUtil->setChannel($channel);
6225 }
6226 }
6227
6228 if ($input->getOption('set-channel-only')) {
6229 return 0;
6230 }
6231
6232 $cacheDir = $config->get('cache-dir');
6233 $rollbackDir = $config->get('data-dir');
6234 $home = $config->get('home');
6235 $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0];
6236
6237 if ($input->getOption('update-keys')) {
6238 return $this->fetchKeys($io, $config);
6239 }
6240
6241
6242  $tmpDir = is_writable(dirname($localFilename)) ? dirname($localFilename) : $cacheDir;
6243
6244
6245  if (!is_writable($tmpDir)) {
6246 throw new FilesystemException('Composer update failed: the "'.$tmpDir.'" directory used to download the temp file could not be written');
6247 }
6248
6249 if ($input->getOption('rollback')) {
6250 return $this->rollback($output, $rollbackDir, $localFilename);
6251 }
6252
6253 $latest = $versionsUtil->getLatest();
6254 $latestVersion = $latest['version'];
6255 $updateVersion = $input->getArgument('version') ?: $latestVersion;
6256
6257 if (preg_match('{^[0-9a-f]{40}$}', $updateVersion) && $updateVersion !== $latestVersion) {
6258 $io->writeError('<error>You can not update to a specific SHA-1 as those phars are not available for download</error>');
6259
6260 return 1;
6261 }
6262
6263 if (Composer::VERSION === $updateVersion) {
6264 $io->writeError(sprintf('<info>You are already using composer version %s (%s channel).</info>', $updateVersion, $versionsUtil->getChannel()));
6265
6266
6267  if ($input->getOption('clean-backups')) {
6268 $this->cleanBackups($rollbackDir, $this->getLastBackupVersion($rollbackDir));
6269 }
6270
6271 return 0;
6272 }
6273
6274 $tempFilename = $tmpDir . '/' . basename($localFilename, '.phar').'-temp.phar';
6275 $backupFile = sprintf(
6276 '%s/%s-%s%s',
6277 $rollbackDir,
6278 strtr(Composer::RELEASE_DATE, ' :', '_-'),
6279 preg_replace('{^([0-9a-f]{7})[0-9a-f]{33}$}', '$1', Composer::VERSION),
6280 self::OLD_INSTALL_EXT
6281 );
6282
6283 $updatingToTag = !preg_match('{^[0-9a-f]{40}$}', $updateVersion);
6284
6285 $io->write(sprintf("Updating to version <info>%s</info> (%s channel).", $updateVersion, $versionsUtil->getChannel()));
6286 $remoteFilename = $baseUrl . ($updatingToTag ? "/download/{$updateVersion}/composer.phar" : '/composer.phar');
6287 $signature = $remoteFilesystem->getContents(self::HOMEPAGE, $remoteFilename.'.sig', false);
6288 $io->writeError('   ', false);
6289 $remoteFilesystem->copy(self::HOMEPAGE, $remoteFilename, $tempFilename, !$input->getOption('no-progress'));
6290 $io->writeError('');
6291
6292 if (!file_exists($tempFilename) || !$signature) {
6293 $io->writeError('<error>The download of the new composer version failed for an unexpected reason</error>');
6294
6295 return 1;
6296 }
6297
6298
6299  if (!extension_loaded('openssl') && $config->get('disable-tls')) {
6300 $io->writeError('<warning>Skipping phar signature verification as you have disabled OpenSSL via config.disable-tls</warning>');
6301 } else {
6302 if (!extension_loaded('openssl')) {
6303 throw new \RuntimeException('The openssl extension is required for phar signatures to be verified but it is not available. '
6304 . '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.');
6305 }
6306
6307 $sigFile = 'file://'.$home.'/' . ($updatingToTag ? 'keys.tags.pub' : 'keys.dev.pub');
6308 if (!file_exists($sigFile)) {
6309 file_put_contents($home.'/keys.dev.pub', <<<DEVPUBKEY
6310 -----BEGIN PUBLIC KEY-----
6311 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAnBDHjZS6e0ZMoK3xTD7f
6312 FNCzlXjX/Aie2dit8QXA03pSrOTbaMnxON3hUL47Lz3g1SC6YJEMVHr0zYq4elWi
6313 i3ecFEgzLcj+pZM5X6qWu2Ozz4vWx3JYo1/a/HYdOuW9e3lwS8VtS0AVJA+U8X0A
6314 hZnBmGpltHhO8hPKHgkJtkTUxCheTcbqn4wGHl8Z2SediDcPTLwqezWKUfrYzu1f
6315 o/j3WFwFs6GtK4wdYtiXr+yspBZHO3y1udf8eFFGcb2V3EaLOrtfur6XQVizjOuk
6316 8lw5zzse1Qp/klHqbDRsjSzJ6iL6F4aynBc6Euqt/8ccNAIz0rLjLhOraeyj4eNn
6317 8iokwMKiXpcrQLTKH+RH1JCuOVxQ436bJwbSsp1VwiqftPQieN+tzqy+EiHJJmGf
6318 TBAbWcncicCk9q2md+AmhNbvHO4PWbbz9TzC7HJb460jyWeuMEvw3gNIpEo2jYa9
6319 pMV6cVqnSa+wOc0D7pC9a6bne0bvLcm3S+w6I5iDB3lZsb3A9UtRiSP7aGSo7D72
6320 8tC8+cIgZcI7k9vjvOqH+d7sdOU2yPCnRY6wFh62/g8bDnUpr56nZN1G89GwM4d4
6321 r/TU7BQQIzsZgAiqOGXvVklIgAMiV0iucgf3rNBLjjeNEwNSTTG9F0CtQ+7JLwaE
6322 wSEuAuRm+pRqi8BRnQ/GKUcCAwEAAQ==
6323 -----END PUBLIC KEY-----
6324 DEVPUBKEY
6325 );
6326 file_put_contents($home.'/keys.tags.pub', <<<TAGSPUBKEY
6327 -----BEGIN PUBLIC KEY-----
6328 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0Vi/2K6apCVj76nCnCl2
6329 MQUPdK+A9eqkYBacXo2wQBYmyVlXm2/n/ZsX6pCLYPQTHyr5jXbkQzBw8SKqPdlh
6330 vA7NpbMeNCz7wP/AobvUXM8xQuXKbMDTY2uZ4O7sM+PfGbptKPBGLe8Z8d2sUnTO
6331 bXtX6Lrj13wkRto7st/w/Yp33RHe9SlqkiiS4MsH1jBkcIkEHsRaveZzedUaxY0M
6332 mba0uPhGUInpPzEHwrYqBBEtWvP97t2vtfx8I5qv28kh0Y6t+jnjL1Urid2iuQZf
6333 noCMFIOu4vksK5HxJxxrN0GOmGmwVQjOOtxkwikNiotZGPR4KsVj8NnBrLX7oGuM
6334 nQvGciiu+KoC2r3HDBrpDeBVdOWxDzT5R4iI0KoLzFh2pKqwbY+obNPS2bj+2dgJ
6335 rV3V5Jjry42QOCBN3c88wU1PKftOLj2ECpewY6vnE478IipiEu7EAdK8Zwj2LmTr
6336 RKQUSa9k7ggBkYZWAeO/2Ag0ey3g2bg7eqk+sHEq5ynIXd5lhv6tC5PBdHlWipDK
6337 tl2IxiEnejnOmAzGVivE1YGduYBjN+mjxDVy8KGBrjnz1JPgAvgdwJ2dYw4Rsc/e
6338 TzCFWGk/HM6a4f0IzBWbJ5ot0PIi4amk07IotBXDWwqDiQTwyuGCym5EqWQ2BD95
6339 RGv89BPD+2DLnJysngsvVaUCAwEAAQ==
6340 -----END PUBLIC KEY-----
6341 TAGSPUBKEY
6342 );
6343 }
6344
6345 $pubkeyid = openssl_pkey_get_public($sigFile);
6346 $algo = defined('OPENSSL_ALGO_SHA384') ? OPENSSL_ALGO_SHA384 : 'SHA384';
6347 if (!in_array('SHA384', openssl_get_md_methods())) {
6348 throw new \RuntimeException('SHA384 is not supported by your openssl extension, could not verify the phar file integrity');
6349 }
6350 $signature = json_decode($signature, true);
6351 $signature = base64_decode($signature['sha384']);
6352 $verified = 1 === openssl_verify(file_get_contents($tempFilename), $signature, $pubkeyid, $algo);
6353 openssl_free_key($pubkeyid);
6354 if (!$verified) {
6355 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');
6356 }
6357 }
6358
6359
6360  if ($input->getOption('clean-backups')) {
6361 $this->cleanBackups($rollbackDir);
6362 }
6363
6364 if ($err = $this->setLocalPhar($localFilename, $tempFilename, $backupFile)) {
6365 @unlink($tempFilename);
6366 $io->writeError('<error>The file is corrupted ('.$err->getMessage().').</error>');
6367 $io->writeError('<error>Please re-run the self-update command to try again.</error>');
6368
6369 return 1;
6370 }
6371
6372 if (file_exists($backupFile)) {
6373 $io->writeError('Use <info>composer self-update --rollback</info> to return to version '.Composer::VERSION);
6374 } else {
6375 $io->writeError('<warning>A backup of the current version could not be written to '.$backupFile.', no rollback possible</warning>');
6376 }
6377 }
6378
6379 protected function fetchKeys(IOInterface $io, Config $config)
6380 {
6381 if (!$io->isInteractive()) {
6382 throw new \RuntimeException('Public keys can not be fetched in non-interactive mode, please run Composer interactively');
6383 }
6384
6385 $io->write('Open <info>https://composer.github.io/pubkeys.html</info> to find the latest keys');
6386
6387 $validator = function ($value) {
6388 if (!preg_match('{^-----BEGIN PUBLIC KEY-----$}', trim($value))) {
6389 throw new \UnexpectedValueException('Invalid input');
6390 }
6391
6392 return trim($value)."\n";
6393 };
6394
6395 $devKey = '';
6396 while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $devKey, $match)) {
6397 $devKey = $io->askAndValidate('Enter Dev / Snapshot Public Key (including lines with -----): ', $validator);
6398 while ($line = $io->ask('')) {
6399 $devKey .= trim($line)."\n";
6400 if (trim($line) === '-----END PUBLIC KEY-----') {
6401 break;
6402 }
6403 }
6404 }
6405 file_put_contents($keyPath = $config->get('home').'/keys.dev.pub', $match[0]);
6406 $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
6407
6408 $tagsKey = '';
6409 while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $tagsKey, $match)) {
6410 $tagsKey = $io->askAndValidate('Enter Tags Public Key (including lines with -----): ', $validator);
6411 while ($line = $io->ask('')) {
6412 $tagsKey .= trim($line)."\n";
6413 if (trim($line) === '-----END PUBLIC KEY-----') {
6414 break;
6415 }
6416 }
6417 }
6418 file_put_contents($keyPath = $config->get('home').'/keys.tags.pub', $match[0]);
6419 $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath));
6420
6421 $io->write('Public keys stored in '.$config->get('home'));
6422 }
6423
6424 protected function rollback(OutputInterface $output, $rollbackDir, $localFilename)
6425 {
6426 $rollbackVersion = $this->getLastBackupVersion($rollbackDir);
6427 if (!$rollbackVersion) {
6428 throw new \UnexpectedValueException('Composer rollback failed: no installation to roll back to in "'.$rollbackDir.'"');
6429 }
6430
6431 $oldFile = $rollbackDir . '/' . $rollbackVersion . self::OLD_INSTALL_EXT;
6432
6433 if (!is_file($oldFile)) {
6434 throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be found');
6435 }
6436 if (!is_readable($oldFile)) {
6437 throw new FilesystemException('Composer rollback failed: "'.$oldFile.'" could not be read');
6438 }
6439
6440 $io = $this->getIO();
6441 $io->writeError(sprintf("Rolling back to version <info>%s</info>.", $rollbackVersion));
6442 if ($err = $this->setLocalPhar($localFilename, $oldFile)) {
6443 $io->writeError('<error>The backup file was corrupted ('.$err->getMessage().').</error>');
6444
6445 return 1;
6446 }
6447
6448 return 0;
6449 }
6450
6451
6452
6453
6454
6455
6456
6457
6458 protected function setLocalPhar($localFilename, $newFilename, $backupTarget = null)
6459 {
6460 try {
6461 @chmod($newFilename, fileperms($localFilename));
6462 if (!ini_get('phar.readonly')) {
6463
6464  $phar = new \Phar($newFilename);
6465
6466  unset($phar);
6467 }
6468
6469
6470  if ($backupTarget && file_exists($localFilename)) {
6471 @copy($localFilename, $backupTarget);
6472 }
6473
6474 rename($newFilename, $localFilename);
6475
6476 return null;
6477 } catch (\Exception $e) {
6478 if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) {
6479 throw $e;
6480 }
6481
6482 return $e;
6483 }
6484 }
6485
6486 protected function cleanBackups($rollbackDir, $except = null)
6487 {
6488 $finder = $this->getOldInstallationFinder($rollbackDir);
6489 $io = $this->getIO();
6490 $fs = new Filesystem;
6491
6492 foreach ($finder as $file) {
6493 if ($except && $file->getBasename(self::OLD_INSTALL_EXT) === $except) {
6494 continue;
6495 }
6496 $file = (string) $file;
6497 $io->writeError('<info>Removing: '.$file.'</info>');
6498 $fs->remove($file);
6499 }
6500 }
6501
6502 protected function getLastBackupVersion($rollbackDir)
6503 {
6504 $finder = $this->getOldInstallationFinder($rollbackDir);
6505 $finder->sortByName();
6506 $files = iterator_to_array($finder);
6507
6508 if (count($files)) {
6509 return basename(end($files), self::OLD_INSTALL_EXT);
6510 }
6511
6512 return false;
6513 }
6514
6515 protected function getOldInstallationFinder($rollbackDir)
6516 {
6517 $finder = Finder::create()
6518 ->depth(0)
6519 ->files()
6520 ->name('*' . self::OLD_INSTALL_EXT)
6521 ->in($rollbackDir);
6522
6523 return $finder;
6524 }
6525 }
6526 <?php
6527
6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538 namespace Composer\Command;
6539
6540 use Composer\DependencyResolver\Pool;
6541 use Composer\DependencyResolver\DefaultPolicy;
6542 use Composer\Json\JsonFile;
6543 use Composer\Package\CompletePackageInterface;
6544 use Composer\Package\Version\VersionParser;
6545 use Composer\Package\BasePackage;
6546 use Composer\Package\Version\VersionSelector;
6547 use Composer\Plugin\CommandEvent;
6548 use Composer\Plugin\PluginEvents;
6549 use Composer\Package\PackageInterface;
6550 use Composer\Semver\Constraint\ConstraintInterface;
6551 use Composer\Util\Platform;
6552 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
6553 use Symfony\Component\Console\Input\InputInterface;
6554 use Symfony\Component\Console\Input\InputArgument;
6555 use Symfony\Component\Console\Input\InputOption;
6556 use Symfony\Component\Console\Output\OutputInterface;
6557 use Composer\Repository\ArrayRepository;
6558 use Composer\Repository\CompositeRepository;
6559 use Composer\Repository\ComposerRepository;
6560 use Composer\Repository\PlatformRepository;
6561 use Composer\Repository\RepositoryInterface;
6562 use Composer\Repository\RepositoryFactory;
6563 use Composer\Spdx\SpdxLicenses;
6564 use Composer\Composer;
6565 use Composer\Semver\Semver;
6566
6567
6568
6569
6570
6571
6572 class ShowCommand extends BaseCommand
6573 {
6574
6575 protected $versionParser;
6576 protected $colors;
6577
6578
6579 private $pool;
6580
6581 protected function configure()
6582 {
6583 $this
6584 ->setName('show')
6585 ->setAliases(array('info'))
6586 ->setDescription('Shows information about packages.')
6587 ->setDefinition(array(
6588 new InputArgument('package', InputArgument::OPTIONAL, 'Package to inspect. Or a name including a wildcard (*) to filter lists of packages instead.'),
6589 new InputArgument('version', InputArgument::OPTIONAL, 'Version or version constraint to inspect'),
6590 new InputOption('all', null, InputOption::VALUE_NONE, 'List all packages'),
6591 new InputOption('installed', 'i', InputOption::VALUE_NONE, 'List installed packages only (enabled by default, only present for BC).'),
6592 new InputOption('platform', 'p', InputOption::VALUE_NONE, 'List platform packages only'),
6593 new InputOption('available', 'a', InputOption::VALUE_NONE, 'List available packages only'),
6594 new InputOption('self', 's', InputOption::VALUE_NONE, 'Show the root package information'),
6595 new InputOption('name-only', 'N', InputOption::VALUE_NONE, 'List package names only'),
6596 new InputOption('path', 'P', InputOption::VALUE_NONE, 'Show package paths'),
6597 new InputOption('tree', 't', InputOption::VALUE_NONE, 'List the dependencies as a tree'),
6598 new InputOption('latest', 'l', InputOption::VALUE_NONE, 'Show the latest version'),
6599 new InputOption('outdated', 'o', InputOption::VALUE_NONE, 'Show the latest version but only for packages that are outdated'),
6600 new InputOption('minor-only', 'm', InputOption::VALUE_NONE, 'Show only packages that have minor SemVer-compatible updates. Use with the --outdated option.'),
6601 new InputOption('direct', 'D', InputOption::VALUE_NONE, 'Shows only packages that are directly required by the root package'),
6602 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code when there are outdated packages'),
6603 new InputOption('format', 'f', InputOption::VALUE_REQUIRED, 'Format of the output: text or json', 'text'),
6604 ))
6605 ->setHelp(<<<EOT
6606 The show command displays detailed information about a package, or
6607 lists all packages available.
6608
6609 EOT
6610 )
6611 ;
6612 }
6613
6614 protected function execute(InputInterface $input, OutputInterface $output)
6615 {
6616 $this->versionParser = new VersionParser;
6617 if ($input->getOption('tree')) {
6618 $this->initStyles($output);
6619 }
6620
6621 $composer = $this->getComposer(false);
6622 $io = $this->getIO();
6623
6624 if ($input->getOption('installed')) {
6625 $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>');
6626 }
6627
6628 if ($input->getOption('outdated')) {
6629 $input->setOption('latest', true);
6630 }
6631
6632 if ($input->getOption('direct') && ($input->getOption('all') || $input->getOption('available') || $input->getOption('platform'))) {
6633 $io->writeError('The --direct (-D) option is not usable in combination with --all, --platform (-p) or --available (-a)');
6634
6635 return 1;
6636 }
6637
6638 if ($input->getOption('tree') && ($input->getOption('all') || $input->getOption('available'))) {
6639 $io->writeError('The --tree (-t) option is not usable in combination with --all or --available (-a)');
6640
6641 return 1;
6642 }
6643
6644 $format = $input->getOption('format');
6645 if (!in_array($format, array('text', 'json'))) {
6646 $io->writeError(sprintf('Unsupported format "%s". See help for supported formats.', $format));
6647
6648 return 1;
6649 }
6650
6651
6652  $platformOverrides = array();
6653 if ($composer) {
6654 $platformOverrides = $composer->getConfig()->get('platform') ?: array();
6655 }
6656 $platformRepo = new PlatformRepository(array(), $platformOverrides);
6657 $phpVersion = $platformRepo->findPackage('php', '*')->getVersion();
6658
6659 if ($input->getOption('self')) {
6660 $package = $this->getComposer()->getPackage();
6661 $repos = $installedRepo = new ArrayRepository(array($package));
6662 } elseif ($input->getOption('platform')) {
6663 $repos = $installedRepo = $platformRepo;
6664 } elseif ($input->getOption('available')) {
6665 $installedRepo = $platformRepo;
6666 if ($composer) {
6667 $repos = new CompositeRepository($composer->getRepositoryManager()->getRepositories());
6668 } else {
6669 $defaultRepos = RepositoryFactory::defaultRepos($io);
6670 $repos = new CompositeRepository($defaultRepos);
6671 $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
6672 }
6673 } elseif ($input->getOption('all') && $composer) {
6674 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
6675 $installedRepo = new CompositeRepository(array($localRepo, $platformRepo));
6676 $repos = new CompositeRepository(array_merge(array($installedRepo), $composer->getRepositoryManager()->getRepositories()));
6677 } elseif ($input->getOption('all')) {
6678 $defaultRepos = RepositoryFactory::defaultRepos($io);
6679 $io->writeError('No composer.json found in the current directory, showing available packages from ' . implode(', ', array_keys($defaultRepos)));
6680 $installedRepo = $platformRepo;
6681 $repos = new CompositeRepository(array_merge(array($installedRepo), $defaultRepos));
6682 } else {
6683 $repos = $installedRepo = $this->getComposer()->getRepositoryManager()->getLocalRepository();
6684 }
6685
6686 if ($composer) {
6687 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'show', $input, $output);
6688 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
6689 }
6690
6691 if ($input->getOption('latest') && null === $composer) {
6692 $io->writeError('No composer.json found in the current directory, disabling "latest" option');
6693 $input->setOption('latest', false);
6694 }
6695
6696 $packageFilter = $input->getArgument('package');
6697
6698
6699  if (($packageFilter && false === strpos($packageFilter, '*')) || !empty($package)) {
6700 if ('json' === $format) {
6701 $io->writeError('Format "json" is only supported for package listings, falling back to format "text"');
6702 }
6703 if (empty($package)) {
6704 list($package, $versions) = $this->getPackage($installedRepo, $repos, $input->getArgument('package'), $input->getArgument('version'));
6705
6706 if (empty($package)) {
6707 $options = $input->getOptions();
6708 if (!isset($options['working-dir']) || !file_exists('composer.json')) {
6709 throw new \InvalidArgumentException('Package ' . $packageFilter . ' not found');
6710 }
6711
6712 $io->writeError('Package ' . $packageFilter . ' not found in ' . $options['working-dir'] . '/composer.json');
6713
6714 return 1;
6715 }
6716 } else {
6717 $versions = array($package->getPrettyVersion() => $package->getVersion());
6718 }
6719
6720 if ($input->getOption('tree')) {
6721 $this->displayPackageTree($package, $installedRepo, $repos);
6722 } else {
6723 $latestPackage = null;
6724 if ($input->getOption('latest')) {
6725 $latestPackage = $this->findLatestPackage($package, $composer, $phpVersion);
6726 }
6727 $this->printMeta($package, $versions, $installedRepo, $latestPackage ?: null);
6728 $this->printLinks($package, 'requires');
6729 $this->printLinks($package, 'devRequires', 'requires (dev)');
6730 if ($package->getSuggests()) {
6731 $io->write("\n<info>suggests</info>");
6732 foreach ($package->getSuggests() as $suggested => $reason) {
6733 $io->write($suggested . ' <comment>' . $reason . '</comment>');
6734 }
6735 }
6736 $this->printLinks($package, 'provides');
6737 $this->printLinks($package, 'conflicts');
6738 $this->printLinks($package, 'replaces');
6739 }
6740
6741 return;
6742 }
6743
6744
6745  if ($input->getOption('tree')) {
6746 if ('json' === $format) {
6747 $io->writeError('Format "json" is only supported for package listings, falling back to format "text"');
6748 }
6749 $rootRequires = $this->getRootRequires();
6750 foreach ($installedRepo->getPackages() as $package) {
6751 if (in_array($package->getName(), $rootRequires, true)) {
6752 $this->displayPackageTree($package, $installedRepo, $repos);
6753 }
6754 }
6755
6756 return 0;
6757 }
6758
6759 if ($repos instanceof CompositeRepository) {
6760 $repos = $repos->getRepositories();
6761 } elseif (!is_array($repos)) {
6762 $repos = array($repos);
6763 }
6764
6765
6766  $packages = array();
6767 if (null !== $packageFilter) {
6768 $packageFilter = '{^'.str_replace('\\*', '.*?', preg_quote($packageFilter)).'$}i';
6769 }
6770
6771 $packageListFilter = array();
6772 if ($input->getOption('direct')) {
6773 $packageListFilter = $this->getRootRequires();
6774 }
6775
6776 list($width) = $this->getApplication()->getTerminalDimensions();
6777 if (null === $width) {
6778
6779  
6780  $width = PHP_INT_MAX;
6781 }
6782 if (Platform::isWindows()) {
6783 $width--;
6784 } else {
6785 $width = max(80, $width);
6786 }
6787
6788 if ($input->getOption('path') && null === $composer) {
6789 $io->writeError('No composer.json found in the current directory, disabling "path" option');
6790 $input->setOption('path', false);
6791 }
6792
6793 foreach ($repos as $repo) {
6794 if ($repo === $platformRepo) {
6795 $type = 'platform';
6796 } elseif (
6797 $repo === $installedRepo
6798 || ($installedRepo instanceof CompositeRepository && in_array($repo, $installedRepo->getRepositories(), true))
6799 ) {
6800 $type = 'installed';
6801 } else {
6802 $type = 'available';
6803 }
6804 if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
6805 foreach ($repo->getProviderNames() as $name) {
6806 if (!$packageFilter || preg_match($packageFilter, $name)) {
6807 $packages[$type][$name] = $name;
6808 }
6809 }
6810 } else {
6811 foreach ($repo->getPackages() as $package) {
6812 if (!isset($packages[$type][$package->getName()])
6813 || !is_object($packages[$type][$package->getName()])
6814 || version_compare($packages[$type][$package->getName()]->getVersion(), $package->getVersion(), '<')
6815 ) {
6816 if (!$packageFilter || preg_match($packageFilter, $package->getName())) {
6817 if (!$packageListFilter || in_array($package->getName(), $packageListFilter, true)) {
6818 $packages[$type][$package->getName()] = $package;
6819 }
6820 }
6821 }
6822 }
6823 }
6824 }
6825
6826 $showAllTypes = $input->getOption('all');
6827 $showLatest = $input->getOption('latest');
6828 $showMinorOnly = $input->getOption('minor-only');
6829 $indent = $showAllTypes ? '  ' : '';
6830 $latestPackages = array();
6831 $exitCode = 0;
6832 $viewData = array();
6833 $viewMetaData = array();
6834 foreach (array('platform' => true, 'available' => false, 'installed' => true) as $type => $showVersion) {
6835 if (isset($packages[$type])) {
6836 ksort($packages[$type]);
6837
6838 $nameLength = $versionLength = $latestLength = 0;
6839 foreach ($packages[$type] as $package) {
6840 if (is_object($package)) {
6841 $nameLength = max($nameLength, strlen($package->getPrettyName()));
6842 if ($showVersion) {
6843 $versionLength = max($versionLength, strlen($package->getFullPrettyVersion()));
6844 if ($showLatest) {
6845 $latestPackage = $this->findLatestPackage($package, $composer, $phpVersion, $showMinorOnly);
6846 if ($latestPackage === false) {
6847 continue;
6848 }
6849
6850 $latestPackages[$package->getPrettyName()] = $latestPackage;
6851 $latestLength = max($latestLength, strlen($latestPackage->getFullPrettyVersion()));
6852 }
6853 }
6854 } else {
6855 $nameLength = max($nameLength, strlen($package));
6856 }
6857 }
6858
6859 $writePath = !$input->getOption('name-only') && $input->getOption('path');
6860 $writeVersion = !$input->getOption('name-only') && !$input->getOption('path') && $showVersion;
6861 $writeLatest = $writeVersion && $showLatest;
6862 $writeDescription = !$input->getOption('name-only') && !$input->getOption('path');
6863
6864 $hasOutdatedPackages = false;
6865
6866 $viewData[$type] = array();
6867 $viewMetaData[$type] = array(
6868 'nameLength' => $nameLength,
6869 'versionLength' => $versionLength,
6870 'latestLength' => $latestLength,
6871 );
6872 foreach ($packages[$type] as $package) {
6873 $packageViewData = array();
6874 if (is_object($package)) {
6875 $latestPackage = null;
6876 if ($showLatest && isset($latestPackages[$package->getPrettyName()])) {
6877 $latestPackage = $latestPackages[$package->getPrettyName()];
6878 }
6879 if ($input->getOption('outdated') && $latestPackage && $latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion() && !$latestPackage->isAbandoned()) {
6880 continue;
6881 } elseif ($input->getOption('outdated') || $input->getOption('strict')) {
6882 $hasOutdatedPackages = true;
6883 }
6884
6885 $packageViewData['name'] = $package->getPrettyName();
6886 if ($writeVersion) {
6887 $packageViewData['version'] = $package->getFullPrettyVersion();
6888 }
6889 if ($writeLatest && $latestPackage) {
6890 $packageViewData['latest'] = $latestPackage->getFullPrettyVersion();
6891 $packageViewData['latest-status'] = $this->getUpdateStatus($latestPackage, $package);
6892 }
6893 if ($writeDescription) {
6894 $packageViewData['description'] = $package->getDescription();
6895 }
6896 if ($writePath) {
6897 $packageViewData['path'] = strtok(realpath($composer->getInstallationManager()->getInstallPath($package)), "\r\n");
6898 }
6899
6900 if ($latestPackage && $latestPackage->isAbandoned()) {
6901 $replacement = (is_string($latestPackage->getReplacementPackage()))
6902 ? 'Use ' . $latestPackage->getReplacementPackage() . ' instead'
6903 : 'No replacement was suggested';
6904 $packageWarning = sprintf(
6905 'Package %s is abandoned, you should avoid using it. %s.',
6906 $package->getPrettyName(),
6907 $replacement
6908 );
6909 $packageViewData['warning'] = $packageWarning;
6910 }
6911 } else {
6912 $packageViewData['name'] = $package;
6913 }
6914 $viewData[$type][] = $packageViewData;
6915 }
6916 if ($input->getOption('strict') && $hasOutdatedPackages) {
6917 $exitCode = 1;
6918 break;
6919 }
6920 }
6921 }
6922
6923 if ('json' === $format) {
6924 $io->write(JsonFile::encode($viewData));
6925 } else {
6926 foreach ($viewData as $type => $packages) {
6927 $nameLength = $viewMetaData[$type]['nameLength'];
6928 $versionLength = $viewMetaData[$type]['versionLength'];
6929 $latestLength = $viewMetaData[$type]['latestLength'];
6930
6931 $writeVersion = $nameLength + $versionLength + 3 <= $width;
6932 $writeLatest = $nameLength + $versionLength + $latestLength + 3 <= $width;
6933 $writeDescription = $nameLength + $versionLength + $latestLength + 24 <= $width;
6934
6935 if ($writeLatest && !$io->isDecorated()) {
6936 $latestLength += 2;
6937 }
6938
6939 if ($showAllTypes) {
6940 if ('available' === $type) {
6941 $io->write('<comment>' . $type . '</comment>:');
6942 } else {
6943 $io->write('<info>' . $type . '</info>:');
6944 }
6945 }
6946
6947 foreach ($packages as $package) {
6948 $io->write($indent . str_pad($package['name'], $nameLength, ' '), false);
6949 if (isset($package['version']) && $writeVersion) {
6950 $io->write(' ' . str_pad($package['version'], $versionLength, ' '), false);
6951 }
6952 if (isset($package['latest']) && $writeLatest) {
6953 $latestVersion = $package['latest'];
6954 $updateStatus = $package['latest-status'];
6955 $style = $this->updateStatusToVersionStyle($updateStatus);
6956 if (!$io->isDecorated()) {
6957 $latestVersion = str_replace(array('up-to-date', 'semver-safe-update', 'update-possible'), array('=', '!', '~'), $updateStatus) . ' ' . $latestVersion;
6958 }
6959 $io->write(' <' . $style . '>' . str_pad($latestVersion, $latestLength, ' ') . '</' . $style . '>', false);
6960 }
6961 if (isset($package['description']) && $writeDescription) {
6962 $description = strtok($package['description'], "\r\n");
6963 $remaining = $width - $nameLength - $versionLength - 4;
6964 if ($writeLatest) {
6965 $remaining -= $latestLength;
6966 }
6967 if (strlen($description) > $remaining) {
6968 $description = substr($description, 0, $remaining - 3) . '...';
6969 }
6970 $io->write(' ' . $description, false);
6971 }
6972 if (isset($package['path'])) {
6973 $io->write(' ' . $package['path'], false);
6974 }
6975 $io->write('');
6976 if (isset($package['warning'])) {
6977 $io->write('<warning>' . $package['warning'] . '</warning>');
6978 }
6979 }
6980
6981 if ($showAllTypes) {
6982 $io->write('');
6983 }
6984 }
6985 }
6986
6987 return $exitCode;
6988 }
6989
6990 protected function getRootRequires()
6991 {
6992 $rootPackage = $this->getComposer()->getPackage();
6993
6994 return array_map(
6995 'strtolower',
6996 array_keys(array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()))
6997 );
6998 }
6999
7000 protected function getVersionStyle(PackageInterface $latestPackage, PackageInterface $package)
7001 {
7002 return $this->updateStatusToVersionStyle($this->getUpdateStatus($latestPackage, $package));
7003 }
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015 protected function getPackage(RepositoryInterface $installedRepo, RepositoryInterface $repos, $name, $version = null)
7016 {
7017 $name = strtolower($name);
7018 $constraint = is_string($version) ? $this->versionParser->parseConstraints($version) : $version;
7019
7020 $policy = new DefaultPolicy();
7021 $pool = new Pool('dev');
7022 $pool->addRepository($repos);
7023
7024 $matchedPackage = null;
7025 $versions = array();
7026 $matches = $pool->whatProvides($name, $constraint);
7027 foreach ($matches as $index => $package) {
7028
7029  if ($package->getName() !== $name) {
7030 unset($matches[$index]);
7031 continue;
7032 }
7033
7034
7035  if (null === $version && $installedRepo->hasPackage($package)) {
7036 $matchedPackage = $package;
7037 }
7038
7039 $versions[$package->getPrettyVersion()] = $package->getVersion();
7040 $matches[$index] = $package->getId();
7041 }
7042
7043
7044  if (!$matchedPackage && $matches && $preferred = $policy->selectPreferredPackages($pool, array(), $matches)) {
7045 $matchedPackage = $pool->literalToPackage($preferred[0]);
7046 }
7047
7048 return array($matchedPackage, $versions);
7049 }
7050
7051
7052
7053
7054
7055
7056
7057
7058 protected function printMeta(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo, PackageInterface $latestPackage = null)
7059 {
7060 $io = $this->getIO();
7061 $io->write('<info>name</info>     : ' . $package->getPrettyName());
7062 $io->write('<info>descrip.</info> : ' . $package->getDescription());
7063 $io->write('<info>keywords</info> : ' . implode(', ', $package->getKeywords() ?: array()));
7064 $this->printVersions($package, $versions, $installedRepo);
7065 if ($latestPackage) {
7066 $style = $this->getVersionStyle($latestPackage, $package);
7067 $io->write('<info>latest</info>   : <'.$style.'>' . $latestPackage->getPrettyVersion() . '</'.$style.'>');
7068 } else {
7069 $latestPackage = $package;
7070 }
7071 $io->write('<info>type</info>     : ' . $package->getType());
7072 $this->printLicenses($package);
7073 $io->write('<info>source</info>   : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getSourceType(), $package->getSourceUrl(), $package->getSourceReference()));
7074 $io->write('<info>dist</info>     : ' . sprintf('[%s] <comment>%s</comment> %s', $package->getDistType(), $package->getDistUrl(), $package->getDistReference()));
7075 $io->write('<info>names</info>    : ' . implode(', ', $package->getNames()));
7076
7077 if ($latestPackage->isAbandoned()) {
7078 $replacement = ($latestPackage->getReplacementPackage() !== null)
7079 ? ' The author suggests using the ' . $latestPackage->getReplacementPackage(). ' package instead.'
7080 : null;
7081
7082 $io->writeError(
7083 sprintf('<warning>Attention: This package is abandoned and no longer maintained.%s</warning>', $replacement)
7084 );
7085 }
7086
7087 if ($package->getSupport()) {
7088 $io->write("\n<info>support</info>");
7089 foreach ($package->getSupport() as $type => $value) {
7090 $io->write('<comment>' . $type . '</comment> : '.$value);
7091 }
7092 }
7093
7094 if ($package->getAutoload()) {
7095 $io->write("\n<info>autoload</info>");
7096 foreach ($package->getAutoload() as $type => $autoloads) {
7097 $io->write('<comment>' . $type . '</comment>');
7098
7099 if ($type === 'psr-0') {
7100 foreach ($autoloads as $name => $path) {
7101 $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
7102 }
7103 } elseif ($type === 'psr-4') {
7104 foreach ($autoloads as $name => $path) {
7105 $io->write(($name ?: '*') . ' => ' . (is_array($path) ? implode(', ', $path) : ($path ?: '.')));
7106 }
7107 } elseif ($type === 'classmap') {
7108 $io->write(implode(', ', $autoloads));
7109 }
7110 }
7111 if ($package->getIncludePaths()) {
7112 $io->write('<comment>include-path</comment>');
7113 $io->write(implode(', ', $package->getIncludePaths()));
7114 }
7115 }
7116 }
7117
7118
7119
7120
7121
7122
7123
7124
7125 protected function printVersions(CompletePackageInterface $package, array $versions, RepositoryInterface $installedRepo)
7126 {
7127 uasort($versions, 'version_compare');
7128 $versions = array_keys(array_reverse($versions));
7129
7130
7131  if ($installedRepo->hasPackage($package)) {
7132 $installedVersion = $package->getPrettyVersion();
7133 $key = array_search($installedVersion, $versions);
7134 if (false !== $key) {
7135 $versions[$key] = '<info>* ' . $installedVersion . '</info>';
7136 }
7137 }
7138
7139 $versions = implode(', ', $versions);
7140
7141 $this->getIO()->write('<info>versions</info> : ' . $versions);
7142 }
7143
7144
7145
7146
7147
7148
7149
7150
7151 protected function printLinks(CompletePackageInterface $package, $linkType, $title = null)
7152 {
7153 $title = $title ?: $linkType;
7154 $io = $this->getIO();
7155 if ($links = $package->{'get'.ucfirst($linkType)}()) {
7156 $io->write("\n<info>" . $title . "</info>");
7157
7158 foreach ($links as $link) {
7159 $io->write($link->getTarget() . ' <comment>' . $link->getPrettyConstraint() . '</comment>');
7160 }
7161 }
7162 }
7163
7164
7165
7166
7167
7168
7169 protected function printLicenses(CompletePackageInterface $package)
7170 {
7171 $spdxLicenses = new SpdxLicenses();
7172
7173 $licenses = $package->getLicense();
7174 $io = $this->getIO();
7175
7176 foreach ($licenses as $licenseId) {
7177 $license = $spdxLicenses->getLicenseByIdentifier($licenseId); 
7178
7179 if (!$license) {
7180 $out = $licenseId;
7181 } else {
7182
7183  if ($license[1] === true) {
7184 $out = sprintf('%s (%s) (OSI approved) %s', $license[0], $licenseId, $license[2]);
7185 } else {
7186 $out = sprintf('%s (%s) %s', $license[0], $licenseId, $license[2]);
7187 }
7188 }
7189
7190 $io->write('<info>license</info>  : ' . $out);
7191 }
7192 }
7193
7194
7195
7196
7197
7198
7199 protected function initStyles(OutputInterface $output)
7200 {
7201 $this->colors = array(
7202 'green',
7203 'yellow',
7204 'cyan',
7205 'magenta',
7206 'blue',
7207 );
7208
7209 foreach ($this->colors as $color) {
7210 $style = new OutputFormatterStyle($color);
7211 $output->getFormatter()->setStyle($color, $style);
7212 }
7213 }
7214
7215
7216
7217
7218
7219
7220
7221
7222 protected function displayPackageTree(PackageInterface $package, RepositoryInterface $installedRepo, RepositoryInterface $distantRepos)
7223 {
7224 $io = $this->getIO();
7225 $io->write(sprintf('<info>%s</info>', $package->getPrettyName()), false);
7226 $io->write(' ' . $package->getPrettyVersion(), false);
7227 $io->write(' ' . strtok($package->getDescription(), "\r\n"));
7228
7229 if (is_object($package)) {
7230 $requires = $package->getRequires();
7231 $treeBar = '├';
7232 $j = 0;
7233 $total = count($requires);
7234 foreach ($requires as $requireName => $require) {
7235 $j++;
7236 if ($j == 0) {
7237 $this->writeTreeLine($treeBar);
7238 }
7239 if ($j == $total) {
7240 $treeBar = '└';
7241 }
7242 $level = 1;
7243 $color = $this->colors[$level];
7244 $info = sprintf('%s──<%s>%s</%s> %s', $treeBar, $color, $requireName, $color, $require->getPrettyConstraint());
7245 $this->writeTreeLine($info);
7246
7247 $treeBar = str_replace('└', ' ', $treeBar);
7248 $packagesInTree = array($package->getName(), $requireName);
7249
7250 $this->displayTree($requireName, $require, $installedRepo, $distantRepos, $packagesInTree, $treeBar, $level + 1);
7251 }
7252 }
7253 }
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266 protected function displayTree($name, $package, RepositoryInterface $installedRepo, RepositoryInterface $distantRepos, array $packagesInTree, $previousTreeBar = '├', $level = 1)
7267 {
7268 $previousTreeBar = str_replace('├', '│', $previousTreeBar);
7269 list($package, $versions) = $this->getPackage($installedRepo, $distantRepos, $name, $package->getPrettyConstraint() === 'self.version' ? $package->getConstraint() : $package->getPrettyConstraint());
7270 if (is_object($package)) {
7271 $requires = $package->getRequires();
7272 $treeBar = $previousTreeBar . '  ├';
7273 $i = 0;
7274 $total = count($requires);
7275 foreach ($requires as $requireName => $require) {
7276 $currentTree = $packagesInTree;
7277 $i++;
7278 if ($i == $total) {
7279 $treeBar = $previousTreeBar . '  └';
7280 }
7281 $colorIdent = $level % count($this->colors);
7282 $color = $this->colors[$colorIdent];
7283
7284 $circularWarn = in_array($requireName, $currentTree) ? '(circular dependency aborted here)' : '';
7285 $info = rtrim(sprintf('%s──<%s>%s</%s> %s %s', $treeBar, $color, $requireName, $color, $require->getPrettyConstraint(), $circularWarn));
7286 $this->writeTreeLine($info);
7287
7288 $treeBar = str_replace('└', ' ', $treeBar);
7289 if (!in_array($requireName, $currentTree)) {
7290 $currentTree[] = $requireName;
7291 $this->displayTree($requireName, $require, $installedRepo, $distantRepos, $currentTree, $treeBar, $level + 1);
7292 }
7293 }
7294 }
7295 }
7296
7297 private function updateStatusToVersionStyle($updateStatus)
7298 {
7299
7300  
7301  
7302  return str_replace(array('up-to-date', 'semver-safe-update', 'update-possible'), array('info', 'highlight', 'comment'), $updateStatus);
7303 }
7304
7305 private function getUpdateStatus(PackageInterface $latestPackage, PackageInterface $package)
7306 {
7307 if ($latestPackage->getFullPrettyVersion() === $package->getFullPrettyVersion()) {
7308 return 'up-to-date';
7309 }
7310
7311 $constraint = $package->getVersion();
7312 if (0 !== strpos($constraint, 'dev-')) {
7313 $constraint = '^'.$constraint;
7314 }
7315 if ($latestPackage->getVersion() && Semver::satisfies($latestPackage->getVersion(), $constraint)) {
7316
7317  return 'semver-safe-update';
7318 }
7319
7320
7321  return 'update-possible';
7322 }
7323
7324 private function writeTreeLine($line)
7325 {
7326 $io = $this->getIO();
7327 if (!$io->isDecorated()) {
7328 $line = str_replace(array('└', '├', '──', '│'), array('`-', '|-', '-', '|'), $line);
7329 }
7330
7331 $io->write($line);
7332 }
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344 private function findLatestPackage(PackageInterface $package, Composer $composer, $phpVersion, $minorOnly = false)
7345 {
7346
7347  $name = $package->getName();
7348 $versionSelector = new VersionSelector($this->getPool($composer));
7349 $stability = $composer->getPackage()->getMinimumStability();
7350 $flags = $composer->getPackage()->getStabilityFlags();
7351 if (isset($flags[$name])) {
7352 $stability = array_search($flags[$name], BasePackage::$stabilities, true);
7353 }
7354
7355 $bestStability = $stability;
7356 if ($composer->getPackage()->getPreferStable()) {
7357 $bestStability = $package->getStability();
7358 }
7359
7360 $targetVersion = null;
7361 if (0 === strpos($package->getVersion(), 'dev-')) {
7362 $targetVersion = $package->getVersion();
7363 }
7364
7365 if ($targetVersion === null && $minorOnly) {
7366 $targetVersion = '^' . $package->getVersion();
7367 }
7368
7369 return $versionSelector->findBestCandidate($name, $targetVersion, $phpVersion, $bestStability);
7370 }
7371
7372 private function getPool(Composer $composer)
7373 {
7374 if (!$this->pool) {
7375 $this->pool = new Pool($composer->getPackage()->getMinimumStability(), $composer->getPackage()->getStabilityFlags());
7376 $this->pool->addRepository(new CompositeRepository($composer->getRepositoryManager()->getRepositories()));
7377 }
7378
7379 return $this->pool;
7380 }
7381 }
7382 <?php
7383
7384
7385
7386
7387
7388
7389
7390
7391
7392
7393
7394 namespace Composer\Command;
7395
7396 use Symfony\Component\Console\Input\InputInterface;
7397 use Symfony\Component\Console\Input\InputOption;
7398 use Symfony\Component\Console\Output\OutputInterface;
7399 use Composer\Downloader\ChangeReportInterface;
7400 use Composer\Downloader\DvcsDownloaderInterface;
7401 use Composer\Downloader\VcsCapableDownloaderInterface;
7402 use Composer\Package\Dumper\ArrayDumper;
7403 use Composer\Package\Version\VersionGuesser;
7404 use Composer\Package\Version\VersionParser;
7405 use Composer\Plugin\CommandEvent;
7406 use Composer\Plugin\PluginEvents;
7407 use Composer\Script\ScriptEvents;
7408 use Composer\Util\ProcessExecutor;
7409
7410
7411
7412
7413
7414 class StatusCommand extends BaseCommand
7415 {
7416 const EXIT_CODE_ERRORS = 1;
7417 const EXIT_CODE_UNPUSHED_CHANGES = 2;
7418 const EXIT_CODE_VERSION_CHANGES = 4;
7419
7420 protected function configure()
7421 {
7422 $this
7423 ->setName('status')
7424 ->setDescription('Shows a list of locally modified packages.')
7425 ->setDefinition(array(
7426 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Show modified files for each directory that contains changes.'),
7427 ))
7428 ->setHelp(<<<EOT
7429 The status command displays a list of dependencies that have
7430 been modified locally.
7431
7432 EOT
7433 )
7434 ;
7435 }
7436
7437 protected function execute(InputInterface $input, OutputInterface $output)
7438 {
7439
7440  $composer = $this->getComposer();
7441
7442 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'status', $input, $output);
7443 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
7444
7445 $installedRepo = $composer->getRepositoryManager()->getLocalRepository();
7446
7447 $dm = $composer->getDownloadManager();
7448 $im = $composer->getInstallationManager();
7449
7450
7451  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::PRE_STATUS_CMD, true);
7452
7453 $errors = array();
7454 $io = $this->getIO();
7455 $unpushedChanges = array();
7456 $vcsVersionChanges = array();
7457
7458 $parser = new VersionParser;
7459 $guesser = new VersionGuesser($composer->getConfig(), new ProcessExecutor($io), $parser);
7460 $dumper = new ArrayDumper;
7461
7462
7463  foreach ($installedRepo->getCanonicalPackages() as $package) {
7464 $downloader = $dm->getDownloaderForInstalledPackage($package);
7465 $targetDir = $im->getInstallPath($package);
7466
7467 if ($downloader instanceof ChangeReportInterface) {
7468 if (is_link($targetDir)) {
7469 $errors[$targetDir] = $targetDir . ' is a symbolic link.';
7470 }
7471
7472 if ($changes = $downloader->getLocalChanges($package, $targetDir)) {
7473 $errors[$targetDir] = $changes;
7474 }
7475 }
7476
7477 if ($downloader instanceof VcsCapableDownloaderInterface) {
7478 if ($currentRef = $downloader->getVcsReference($package, $targetDir)) {
7479 switch ($package->getInstallationSource()) {
7480 case 'source':
7481 $previousRef = $package->getSourceReference();
7482 break;
7483 case 'dist':
7484 $previousRef = $package->getDistReference();
7485 break;
7486 default:
7487 $previousRef = null;
7488 }
7489
7490 $currentVersion = $guesser->guessVersion($dumper->dump($package), $targetDir);
7491
7492 if ($previousRef && $currentVersion && $currentVersion['commit'] !== $previousRef) {
7493 $vcsVersionChanges[$targetDir] = array(
7494 'previous' => array(
7495 'version' => $package->getPrettyVersion(),
7496 'ref' => $previousRef,
7497 ),
7498 'current' => array(
7499 'version' => $currentVersion['pretty_version'],
7500 'ref' => $currentVersion['commit'],
7501 ),
7502 );
7503 }
7504 }
7505 }
7506
7507 if ($downloader instanceof DvcsDownloaderInterface) {
7508 if ($unpushed = $downloader->getUnpushedChanges($package, $targetDir)) {
7509 $unpushedChanges[$targetDir] = $unpushed;
7510 }
7511 }
7512 }
7513
7514
7515  if (!$errors && !$unpushedChanges && !$vcsVersionChanges) {
7516 $io->writeError('<info>No local changes</info>');
7517
7518 return 0;
7519 }
7520
7521 if ($errors) {
7522 $io->writeError('<error>You have changes in the following dependencies:</error>');
7523
7524 foreach ($errors as $path => $changes) {
7525 if ($input->getOption('verbose')) {
7526 $indentedChanges = implode("\n", array_map(function ($line) {
7527 return '    ' . ltrim($line);
7528 }, explode("\n", $changes)));
7529 $io->write('<info>'.$path.'</info>:');
7530 $io->write($indentedChanges);
7531 } else {
7532 $io->write($path);
7533 }
7534 }
7535 }
7536
7537 if ($unpushedChanges) {
7538 $io->writeError('<warning>You have unpushed changes on the current branch in the following dependencies:</warning>');
7539
7540 foreach ($unpushedChanges as $path => $changes) {
7541 if ($input->getOption('verbose')) {
7542 $indentedChanges = implode("\n", array_map(function ($line) {
7543 return '    ' . ltrim($line);
7544 }, explode("\n", $changes)));
7545 $io->write('<info>'.$path.'</info>:');
7546 $io->write($indentedChanges);
7547 } else {
7548 $io->write($path);
7549 }
7550 }
7551 }
7552
7553 if ($vcsVersionChanges) {
7554 $io->writeError('<warning>You have version variations in the following dependencies:</warning>');
7555
7556 foreach ($vcsVersionChanges as $path => $changes) {
7557 if ($input->getOption('verbose')) {
7558
7559  $currentVersion = $changes['current']['version'] ?: $changes['current']['ref'];
7560 $previousVersion = $changes['previous']['version'] ?: $changes['previous']['ref'];
7561
7562 if ($io->isVeryVerbose()) {
7563
7564  $currentVersion .= sprintf(' (%s)', $changes['current']['ref']);
7565 $previousVersion .= sprintf(' (%s)', $changes['previous']['ref']);
7566 }
7567
7568 $io->write('<info>'.$path.'</info>:');
7569 $io->write(sprintf('    From <comment>%s</comment> to <comment>%s</comment>', $previousVersion, $currentVersion));
7570 } else {
7571 $io->write($path);
7572 }
7573 }
7574 }
7575
7576 if (($errors || $unpushedChanges || $vcsVersionChanges) && !$input->getOption('verbose')) {
7577 $io->writeError('Use --verbose (-v) to see a list of files');
7578 }
7579
7580
7581  $composer->getEventDispatcher()->dispatchScript(ScriptEvents::POST_STATUS_CMD, true);
7582
7583 return ($errors ? self::EXIT_CODE_ERRORS : 0) + ($unpushedChanges ? self::EXIT_CODE_UNPUSHED_CHANGES : 0) + ($vcsVersionChanges ? self::EXIT_CODE_VERSION_CHANGES : 0);
7584 }
7585 }
7586 <?php
7587
7588
7589
7590
7591
7592
7593
7594
7595
7596
7597
7598 namespace Composer\Command;
7599
7600 use Composer\Repository\PlatformRepository;
7601 use Symfony\Component\Console\Input\InputArgument;
7602 use Symfony\Component\Console\Input\InputInterface;
7603 use Symfony\Component\Console\Input\InputOption;
7604 use Symfony\Component\Console\Output\OutputInterface;
7605
7606 class SuggestsCommand extends BaseCommand
7607 {
7608 protected function configure()
7609 {
7610 $this
7611 ->setName('suggests')
7612 ->setDescription('Shows package suggestions.')
7613 ->setDefinition(array(
7614 new InputOption('by-package', null, InputOption::VALUE_NONE, 'Groups output by suggesting package'),
7615 new InputOption('by-suggestion', null, InputOption::VALUE_NONE, 'Groups output by suggested package'),
7616 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Exclude suggestions from require-dev packages'),
7617 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that you want to list suggestions from.'),
7618 ))
7619 ->setHelp(<<<EOT
7620
7621 The <info>%command.name%</info> command shows a sorted list of suggested packages.
7622
7623 Enabling <info>-v</info> implies <info>--by-package --by-suggestion</info>, showing both lists.
7624
7625 EOT
7626 )
7627 ;
7628 }
7629
7630 protected function execute(InputInterface $input, OutputInterface $output)
7631 {
7632 $lock = $this->getComposer()->getLocker()->getLockData();
7633
7634 if (empty($lock)) {
7635 throw new \RuntimeException('Lockfile seems to be empty?');
7636 }
7637
7638 $packages = $lock['packages'];
7639
7640 if (!$input->getOption('no-dev')) {
7641 $packages += $lock['packages-dev'];
7642 }
7643
7644 $filter = $input->getArgument('packages');
7645
7646
7647  $installed = array();
7648 foreach ($packages as $package) {
7649 $installed[] = $package['name'];
7650
7651 if (!empty($package['provide'])) {
7652 $installed = array_merge($installed, array_keys($package['provide']));
7653 }
7654
7655 if (!empty($package['replace'])) {
7656 $installed = array_merge($installed, array_keys($package['replace']));
7657 }
7658 }
7659
7660
7661  $installed = array_flip($installed);
7662 ksort($installed);
7663
7664
7665  $platform = new PlatformRepository(array(), $this->getComposer()->getConfig()->get('platform') ?: array());
7666
7667
7668  $suggesters = array();
7669 $suggested = array();
7670 foreach ($packages as $package) {
7671 $packageName = $package['name'];
7672 if ((!empty($filter) && !in_array($packageName, $filter)) || empty($package['suggest'])) {
7673 continue;
7674 }
7675 foreach ($package['suggest'] as $suggestion => $reason) {
7676 if (false === strpos('/', $suggestion) && !is_null($platform->findPackage($suggestion, '*'))) {
7677 continue;
7678 }
7679 if (!isset($installed[$suggestion])) {
7680 $suggesters[$packageName][$suggestion] = $reason;
7681 $suggested[$suggestion][$packageName] = $reason;
7682 }
7683 }
7684 }
7685 ksort($suggesters);
7686 ksort($suggested);
7687
7688
7689  $mode = 0;
7690 $io = $this->getIO();
7691 if ($input->getOption('by-package') || $io->isVerbose()) {
7692 $mode |= 1;
7693 }
7694 if ($input->getOption('by-suggestion')) {
7695 $mode |= 2;
7696 }
7697
7698
7699  if ($mode === 0) {
7700 foreach (array_keys($suggested) as $suggestion) {
7701 $io->write(sprintf('<info>%s</info>', $suggestion));
7702 }
7703
7704 return;
7705 }
7706
7707
7708  if ($mode & 1) {
7709 foreach ($suggesters as $suggester => $suggestions) {
7710 $io->write(sprintf('<comment>%s</comment> suggests:', $suggester));
7711
7712 foreach ($suggestions as $suggestion => $reason) {
7713 $io->write(sprintf(' - <info>%s</info>: %s', $suggestion, $reason ?: '*'));
7714 }
7715 $io->write('');
7716 }
7717 }
7718
7719
7720  if ($mode & 2) {
7721
7722  if ($mode & 1) {
7723 $io->write(str_repeat('-', 78));
7724 }
7725 foreach ($suggested as $suggestion => $suggesters) {
7726 $io->write(sprintf('<comment>%s</comment> is suggested by:', $suggestion));
7727
7728 foreach ($suggesters as $suggester => $reason) {
7729 $io->write(sprintf(' - <info>%s</info>: %s', $suggester, $reason ?: '*'));
7730 }
7731 $io->write('');
7732 }
7733 }
7734 }
7735 }
7736 <?php
7737
7738
7739
7740
7741
7742
7743
7744
7745
7746
7747
7748 namespace Composer\Command;
7749
7750 use Composer\Composer;
7751 use Composer\Installer;
7752 use Composer\IO\IOInterface;
7753 use Composer\Plugin\CommandEvent;
7754 use Composer\Plugin\PluginEvents;
7755 use Symfony\Component\Console\Helper\Table;
7756 use Symfony\Component\Console\Input\InputInterface;
7757 use Symfony\Component\Console\Input\InputOption;
7758 use Symfony\Component\Console\Input\InputArgument;
7759 use Symfony\Component\Console\Output\OutputInterface;
7760 use Symfony\Component\Console\Question\Question;
7761
7762
7763
7764
7765
7766 class UpdateCommand extends BaseCommand
7767 {
7768 protected function configure()
7769 {
7770 $this
7771 ->setName('update')
7772 ->setAliases(array('upgrade'))
7773 ->setDescription('Upgrades your dependencies to the latest version according to composer.json, and updates the composer.lock file.')
7774 ->setDefinition(array(
7775 new InputArgument('packages', InputArgument::IS_ARRAY | InputArgument::OPTIONAL, 'Packages that should be updated, if not provided all packages are.'),
7776 new InputOption('prefer-source', null, InputOption::VALUE_NONE, 'Forces installation from package sources when possible, including VCS information.'),
7777 new InputOption('prefer-dist', null, InputOption::VALUE_NONE, 'Forces installation from package dist even for dev versions.'),
7778 new InputOption('dry-run', null, InputOption::VALUE_NONE, 'Outputs the operations but will not execute anything (implicitly enables --verbose).'),
7779 new InputOption('dev', null, InputOption::VALUE_NONE, 'Enables installation of require-dev packages (enabled by default, only present for BC).'),
7780 new InputOption('no-dev', null, InputOption::VALUE_NONE, 'Disables installation of require-dev packages.'),
7781 new InputOption('lock', null, InputOption::VALUE_NONE, 'Only updates the lock file hash to suppress warning about the lock file being out of date.'),
7782 new InputOption('no-custom-installers', null, InputOption::VALUE_NONE, 'DEPRECATED: Use no-plugins instead.'),
7783 new InputOption('no-autoloader', null, InputOption::VALUE_NONE, 'Skips autoloader generation'),
7784 new InputOption('no-scripts', null, InputOption::VALUE_NONE, 'Skips the execution of all scripts defined in composer.json file.'),
7785 new InputOption('no-progress', null, InputOption::VALUE_NONE, 'Do not output download progress.'),
7786 new InputOption('no-suggest', null, InputOption::VALUE_NONE, 'Do not show package suggestions.'),
7787 new InputOption('with-dependencies', null, InputOption::VALUE_NONE, 'Add also all dependencies of whitelisted packages to the whitelist.'),
7788 new InputOption('verbose', 'v|vv|vvv', InputOption::VALUE_NONE, 'Shows more details including new commits pulled in when updating packages.'),
7789 new InputOption('optimize-autoloader', 'o', InputOption::VALUE_NONE, 'Optimize autoloader during autoloader dump.'),
7790 new InputOption('classmap-authoritative', 'a', InputOption::VALUE_NONE, 'Autoload classes from the classmap only. Implicitly enables `--optimize-autoloader`.'),
7791 new InputOption('apcu-autoloader', null, InputOption::VALUE_NONE, 'Use APCu to cache found/not-found classes.'),
7792 new InputOption('ignore-platform-reqs', null, InputOption::VALUE_NONE, 'Ignore platform requirements (php & ext- packages).'),
7793 new InputOption('prefer-stable', null, InputOption::VALUE_NONE, 'Prefer stable versions of dependencies.'),
7794 new InputOption('prefer-lowest', null, InputOption::VALUE_NONE, 'Prefer lowest versions of dependencies.'),
7795 new InputOption('interactive', 'i', InputOption::VALUE_NONE, 'Interactive interface with autocompletion to select the packages to update.'),
7796 new InputOption('root-reqs', null, InputOption::VALUE_NONE, 'Restricts the update to your first degree dependencies.'),
7797 ))
7798 ->setHelp(<<<EOT
7799 The <info>update</info> command reads the composer.json file from the
7800 current directory, processes it, and updates, removes or installs all the
7801 dependencies.
7802
7803 <info>php composer.phar update</info>
7804
7805 To limit the update operation to a few packages, you can list the package(s)
7806 you want to update as such:
7807
7808 <info>php composer.phar update vendor/package1 foo/mypackage [...]</info>
7809
7810 You may also use an asterisk (*) pattern to limit the update operation to package(s)
7811 from a specific vendor:
7812
7813 <info>php composer.phar update vendor/package1 foo/* [...]</info>
7814
7815 To select packages names interactively with auto-completion use <info>-i</info>.
7816
7817 EOT
7818 )
7819 ;
7820 }
7821
7822 protected function execute(InputInterface $input, OutputInterface $output)
7823 {
7824 $io = $this->getIO();
7825 if ($input->getOption('no-custom-installers')) {
7826 $io->writeError('<warning>You are using the deprecated option "no-custom-installers". Use "no-plugins" instead.</warning>');
7827 $input->setOption('no-plugins', true);
7828 }
7829
7830 if ($input->getOption('dev')) {
7831 $io->writeError('<warning>You are using the deprecated option "dev". Dev packages are installed by default now.</warning>');
7832 }
7833
7834 $composer = $this->getComposer(true, $input->getOption('no-plugins'));
7835
7836 $packages = $input->getArgument('packages');
7837
7838 if ($input->getOption('interactive')) {
7839 $packages = $this->getPackagesInteractively($io, $input, $output, $composer, $packages);
7840 }
7841
7842 if ($input->getOption('root-reqs')) {
7843 $require = array_keys($composer->getPackage()->getRequires());
7844 if (!$input->getOption('no-dev')) {
7845 $requireDev = array_keys($composer->getPackage()->getDevRequires());
7846 $require = array_merge($require, $requireDev);
7847 }
7848
7849 if (!empty($packages)) {
7850 $packages = array_intersect($packages, $require);
7851 } else {
7852 $packages = $require;
7853 }
7854 }
7855
7856 $composer->getDownloadManager()->setOutputProgress(!$input->getOption('no-progress'));
7857
7858 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'update', $input, $output);
7859 $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
7860
7861 $install = Installer::create($io, $composer);
7862
7863 $config = $composer->getConfig();
7864 list($preferSource, $preferDist) = $this->getPreferredInstallOptions($config, $input);
7865
7866 $optimize = $input->getOption('optimize-autoloader') || $config->get('optimize-autoloader');
7867 $authoritative = $input->getOption('classmap-authoritative') || $config->get('classmap-authoritative');
7868 $apcu = $input->getOption('apcu-autoloader') || $config->get('apcu-autoloader');
7869
7870 $install
7871 ->setDryRun($input->getOption('dry-run'))
7872 ->setVerbose($input->getOption('verbose'))
7873 ->setPreferSource($preferSource)
7874 ->setPreferDist($preferDist)
7875 ->setDevMode(!$input->getOption('no-dev'))
7876 ->setDumpAutoloader(!$input->getOption('no-autoloader'))
7877 ->setRunScripts(!$input->getOption('no-scripts'))
7878 ->setSkipSuggest($input->getOption('no-suggest'))
7879 ->setOptimizeAutoloader($optimize)
7880 ->setClassMapAuthoritative($authoritative)
7881 ->setApcuAutoloader($apcu)
7882 ->setUpdate(true)
7883 ->setUpdateWhitelist($input->getOption('lock') ? array('lock') : $packages)
7884 ->setWhitelistDependencies($input->getOption('with-dependencies'))
7885 ->setIgnorePlatformRequirements($input->getOption('ignore-platform-reqs'))
7886 ->setPreferStable($input->getOption('prefer-stable'))
7887 ->setPreferLowest($input->getOption('prefer-lowest'))
7888 ;
7889
7890 if ($input->getOption('no-plugins')) {
7891 $install->disablePlugins();
7892 }
7893
7894 return $install->run();
7895 }
7896
7897 private function getPackagesInteractively(IOInterface $io, InputInterface $input, OutputInterface $output, Composer $composer, array $packages)
7898 {
7899 if (!$input->isInteractive()) {
7900 throw new \InvalidArgumentException('--interactive cannot be used in non-interactive terminals.');
7901 }
7902
7903 $requires = array_merge(
7904 $composer->getPackage()->getRequires(),
7905 $composer->getPackage()->getDevRequires()
7906 );
7907 $autocompleterValues = array();
7908 foreach ($requires as $require) {
7909 $autocompleterValues[strtolower($require->getTarget())] = $require->getTarget();
7910 }
7911
7912 $installedPackages = $composer->getRepositoryManager()->getLocalRepository()->getPackages();
7913 foreach ($installedPackages as $package) {
7914 $autocompleterValues[$package->getName()] = $package->getPrettyName();
7915 }
7916
7917 $helper = $this->getHelper('question');
7918 $question = new Question('<comment>Enter package name: </comment>', null);
7919
7920 $io->writeError('<info>Press enter without value to end submission</info>');
7921
7922 do {
7923 $autocompleterValues = array_diff($autocompleterValues, $packages);
7924 $question->setAutocompleterValues($autocompleterValues);
7925 $addedPackage = $helper->ask($input, $output, $question);
7926
7927 if (!is_string($addedPackage) || empty($addedPackage)) {
7928 break;
7929 }
7930
7931 $addedPackage = strtolower($addedPackage);
7932 if (!in_array($addedPackage, $packages)) {
7933 $packages[] = $addedPackage;
7934 }
7935 } while (true);
7936
7937 $packages = array_filter($packages);
7938 if (!$packages) {
7939 throw new \InvalidArgumentException('You must enter minimum one package.');
7940 }
7941
7942 $table = new Table($output);
7943 $table->setHeaders(array('Selected packages'));
7944 foreach ($packages as $package) {
7945 $table->addRow(array($package));
7946 }
7947 $table->render();
7948
7949 if ($io->askConfirmation(sprintf(
7950 'Would you like to continue and update the above package%s [<comment>yes</comment>]? ',
7951 1 === count($packages) ? '' : 's'
7952 ), true)) {
7953 return $packages;
7954 }
7955
7956 throw new \RuntimeException('Installation aborted.');
7957 }
7958 }
7959 <?php
7960
7961
7962
7963
7964
7965
7966
7967
7968
7969
7970
7971 namespace Composer\Command;
7972
7973 use Composer\Factory;
7974 use Composer\Package\Loader\ValidatingArrayLoader;
7975 use Composer\Plugin\CommandEvent;
7976 use Composer\Plugin\PluginEvents;
7977 use Composer\Util\ConfigValidator;
7978 use Symfony\Component\Console\Input\InputArgument;
7979 use Symfony\Component\Console\Input\InputInterface;
7980 use Symfony\Component\Console\Input\InputOption;
7981 use Symfony\Component\Console\Output\OutputInterface;
7982
7983
7984
7985
7986
7987
7988
7989 class ValidateCommand extends BaseCommand
7990 {
7991
7992
7993
7994 protected function configure()
7995 {
7996 $this
7997 ->setName('validate')
7998 ->setDescription('Validates a composer.json and composer.lock.')
7999 ->setDefinition(array(
8000 new InputOption('no-check-all', null, InputOption::VALUE_NONE, 'Do not make a complete validation'),
8001 new InputOption('no-check-lock', null, InputOption::VALUE_NONE, 'Do not check if lock file is up to date'),
8002 new InputOption('no-check-publish', null, InputOption::VALUE_NONE, 'Do not check for publish errors'),
8003 new InputOption('with-dependencies', 'A', InputOption::VALUE_NONE, 'Also validate the composer.json of all installed dependencies'),
8004 new InputOption('strict', null, InputOption::VALUE_NONE, 'Return a non-zero exit code for warnings as well as errors'),
8005 new InputArgument('file', InputArgument::OPTIONAL, 'path to composer.json file', './composer.json'),
8006 ))
8007 ->setHelp(<<<EOT
8008 The validate command validates a given composer.json and composer.lock
8009
8010 Exit codes in case of errors are:
8011 1 validation warning(s), only when --strict is given
8012 2 validation error(s)
8013 3 file unreadable or missing
8014
8015 EOT
8016 );
8017 }
8018
8019
8020
8021
8022
8023
8024
8025 protected function execute(InputInterface $input, OutputInterface $output)
8026 {
8027 $file = $input->getArgument('file');
8028 $io = $this->getIO();
8029
8030 if (!file_exists($file)) {
8031 $io->writeError('<error>' . $file . ' not found.</error>');
8032
8033 return 3;
8034 }
8035 if (!is_readable($file)) {
8036 $io->writeError('<error>' . $file . ' is not readable.</error>');
8037
8038 return 3;
8039 }
8040
8041 $validator = new ConfigValidator($io);
8042 $checkAll = $input->getOption('no-check-all') ? 0 : ValidatingArrayLoader::CHECK_ALL;
8043 $checkPublish = !$input->getOption('no-check-publish');
8044 $checkLock = !$input->getOption('no-check-lock');
8045 $isStrict = $input->getOption('strict');
8046 list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
8047
8048 $lockErrors = array();
8049 $composer = Factory::create($io, $file);
8050 $locker = $composer->getLocker();
8051 if ($locker->isLocked() && !$locker->isFresh()) {
8052 $lockErrors[] = 'The lock file is not up to date with the latest changes in composer.json, it is recommended that you run `composer update`.';
8053 }
8054
8055 $this->outputResult($io, $file, $errors, $warnings, $checkPublish, $publishErrors, $checkLock, $lockErrors, true);
8056
8057 $exitCode = $errors || ($publishErrors && $checkPublish) || ($lockErrors && $checkLock) ? 2 : ($isStrict && $warnings ? 1 : 0);
8058
8059 if ($input->getOption('with-dependencies')) {
8060 $localRepo = $composer->getRepositoryManager()->getLocalRepository();
8061 foreach ($localRepo->getPackages() as $package) {
8062 $path = $composer->getInstallationManager()->getInstallPath($package);
8063 $file = $path . '/composer.json';
8064 if (is_dir($path) && file_exists($file)) {
8065 list($errors, $publishErrors, $warnings) = $validator->validate($file, $checkAll);
8066 $this->outputResult($io, $package->getPrettyName(), $errors, $warnings, $checkPublish, $publishErrors);
8067
8068 $depCode = $errors || ($publishErrors && $checkPublish) ? 2 : ($isStrict && $warnings ? 1 : 0);
8069 $exitCode = max($depCode, $exitCode);
8070 }
8071 }
8072 }
8073
8074 $commandEvent = new CommandEvent(PluginEvents::COMMAND, 'validate', $input, $output);
8075 $eventCode = $composer->getEventDispatcher()->dispatch($commandEvent->getName(), $commandEvent);
8076 $exitCode = max($eventCode, $exitCode);
8077
8078 return $exitCode;
8079 }
8080
8081 private function outputResult($io, $name, &$errors, &$warnings, $checkPublish = false, $publishErrors = array(), $checkLock = false, $lockErrors = array(), $printSchemaUrl = false)
8082 {
8083 if (!$errors && !$publishErrors && !$warnings) {
8084 $io->write('<info>' . $name . ' is valid</info>');
8085 } elseif (!$errors && !$publishErrors) {
8086 $io->writeError('<info>' . $name . ' is valid, but with a few warnings</info>');
8087 if ($printSchemaUrl) {
8088 $io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
8089 }
8090 } elseif (!$errors) {
8091 $io->writeError('<info>' . $name . ' is valid for simple usage with composer but has</info>');
8092 $io->writeError('<info>strict errors that make it unable to be published as a package:</info>');
8093 if ($printSchemaUrl) {
8094 $io->writeError('<warning>See https://getcomposer.org/doc/04-schema.md for details on the schema</warning>');
8095 }
8096 } else {
8097 $io->writeError('<error>' . $name . ' is invalid, the following errors/warnings were found:</error>');
8098 }
8099
8100
8101  if ($checkPublish) {
8102 $errors = array_merge($errors, $publishErrors);
8103 } else {
8104 $warnings = array_merge($warnings, $publishErrors);
8105 }
8106
8107
8108  if ($checkLock) {
8109 $errors = array_merge($errors, $lockErrors);
8110 } else {
8111 $warnings = array_merge($warnings, $lockErrors);
8112 }
8113
8114 $messages = array(
8115 'error' => $errors,
8116 'warning' => $warnings,
8117 );
8118
8119 foreach ($messages as $style => $msgs) {
8120 foreach ($msgs as $msg) {
8121 $io->writeError('<' . $style . '>' . $msg . '</' . $style . '>');
8122 }
8123 }
8124 }
8125 }
8126 <?php
8127
8128
8129
8130
8131
8132
8133
8134
8135
8136
8137
8138 namespace Composer;
8139
8140 use Composer\Package\RootPackageInterface;
8141 use Composer\Package\Locker;
8142 use Composer\Repository\RepositoryManager;
8143 use Composer\Installer\InstallationManager;
8144 use Composer\Plugin\PluginManager;
8145 use Composer\Downloader\DownloadManager;
8146 use Composer\EventDispatcher\EventDispatcher;
8147 use Composer\Autoload\AutoloadGenerator;
8148 use Composer\Package\Archiver\ArchiveManager;
8149
8150
8151
8152
8153
8154
8155 class Composer
8156 {
8157 const VERSION = '1.5.2';
8158 const BRANCH_ALIAS_VERSION = '';
8159 const RELEASE_DATE = '2017-09-11 16:59:25';
8160
8161
8162
8163
8164 private $package;
8165
8166
8167
8168
8169 private $locker;
8170
8171
8172
8173
8174 private $repositoryManager;
8175
8176
8177
8178
8179 private $downloadManager;
8180
8181
8182
8183
8184 private $installationManager;
8185
8186
8187
8188
8189 private $pluginManager;
8190
8191
8192
8193
8194 private $config;
8195
8196
8197
8198
8199 private $eventDispatcher;
8200
8201
8202
8203
8204 private $autoloadGenerator;
8205
8206
8207
8208
8209 private $archiveManager;
8210
8211
8212
8213
8214
8215 public function setPackage(RootPackageInterface $package)
8216 {
8217 $this->package = $package;
8218 }
8219
8220
8221
8222
8223 public function getPackage()
8224 {
8225 return $this->package;
8226 }
8227
8228
8229
8230
8231 public function setConfig(Config $config)
8232 {
8233 $this->config = $config;
8234 }
8235
8236
8237
8238
8239 public function getConfig()
8240 {
8241 return $this->config;
8242 }
8243
8244
8245
8246
8247 public function setLocker(Locker $locker)
8248 {
8249 $this->locker = $locker;
8250 }
8251
8252
8253
8254
8255 public function getLocker()
8256 {
8257 return $this->locker;
8258 }
8259
8260
8261
8262
8263 public function setRepositoryManager(RepositoryManager $manager)
8264 {
8265 $this->repositoryManager = $manager;
8266 }
8267
8268
8269
8270
8271 public function getRepositoryManager()
8272 {
8273 return $this->repositoryManager;
8274 }
8275
8276
8277
8278
8279 public function setDownloadManager(DownloadManager $manager)
8280 {
8281 $this->downloadManager = $manager;
8282 }
8283
8284
8285
8286
8287 public function getDownloadManager()
8288 {
8289 return $this->downloadManager;
8290 }
8291
8292
8293
8294
8295 public function setArchiveManager(ArchiveManager $manager)
8296 {
8297 $this->archiveManager = $manager;
8298 }
8299
8300
8301
8302
8303 public function getArchiveManager()
8304 {
8305 return $this->archiveManager;
8306 }
8307
8308
8309
8310
8311 public function setInstallationManager(InstallationManager $manager)
8312 {
8313 $this->installationManager = $manager;
8314 }
8315
8316
8317
8318
8319 public function getInstallationManager()
8320 {
8321 return $this->installationManager;
8322 }
8323
8324
8325
8326
8327 public function setPluginManager(PluginManager $manager)
8328 {
8329 $this->pluginManager = $manager;
8330 }
8331
8332
8333
8334
8335 public function getPluginManager()
8336 {
8337 return $this->pluginManager;
8338 }
8339
8340
8341
8342
8343 public function setEventDispatcher(EventDispatcher $eventDispatcher)
8344 {
8345 $this->eventDispatcher = $eventDispatcher;
8346 }
8347
8348
8349
8350
8351 public function getEventDispatcher()
8352 {
8353 return $this->eventDispatcher;
8354 }
8355
8356
8357
8358
8359 public function setAutoloadGenerator(AutoloadGenerator $autoloadGenerator)
8360 {
8361 $this->autoloadGenerator = $autoloadGenerator;
8362 }
8363
8364
8365
8366
8367 public function getAutoloadGenerator()
8368 {
8369 return $this->autoloadGenerator;
8370 }
8371 }
8372 <?php
8373
8374
8375
8376
8377
8378
8379
8380
8381
8382
8383
8384 namespace Composer;
8385
8386 use Composer\Config\ConfigSourceInterface;
8387 use Composer\Downloader\TransportException;
8388 use Composer\IO\IOInterface;
8389 use Composer\Util\Platform;
8390
8391
8392
8393
8394 class Config
8395 {
8396 const RELATIVE_PATHS = 1;
8397
8398 public static $defaultConfig = array(
8399 'process-timeout' => 300,
8400 'use-include-path' => false,
8401 'preferred-install' => 'auto',
8402 'notify-on-install' => true,
8403 'github-protocols' => array('https', 'ssh', 'git'),
8404 'vendor-dir' => 'vendor',
8405 'bin-dir' => '{$vendor-dir}/bin',
8406 'cache-dir' => '{$home}/cache',
8407 'data-dir' => '{$home}',
8408 'cache-files-dir' => '{$cache-dir}/files',
8409 'cache-repo-dir' => '{$cache-dir}/repo',
8410 'cache-vcs-dir' => '{$cache-dir}/vcs',
8411 'cache-ttl' => 15552000, 
8412  'cache-files-ttl' => null, 
8413  'cache-files-maxsize' => '300MiB',
8414 'bin-compat' => 'auto',
8415 'discard-changes' => false,
8416 'autoloader-suffix' => null,
8417 'sort-packages' => false,
8418 'optimize-autoloader' => false,
8419 'classmap-authoritative' => false,
8420 'apcu-autoloader' => false,
8421 'prepend-autoloader' => true,
8422 'github-domains' => array('github.com'),
8423 'bitbucket-expose-hostname' => true,
8424 'disable-tls' => false,
8425 'secure-http' => true,
8426 'cafile' => null,
8427 'capath' => null,
8428 'github-expose-hostname' => true,
8429 'gitlab-domains' => array('gitlab.com'),
8430 'store-auths' => 'prompt',
8431 'platform' => array(),
8432 'archive-format' => 'tar',
8433 'archive-dir' => '.',
8434 'htaccess-protect' => true,
8435
8436  
8437  
8438  
8439  
8440  
8441  );
8442
8443 public static $defaultRepositories = array(
8444 'packagist.org' => array(
8445 'type' => 'composer',
8446 'url' => 'https?://packagist.org',
8447 'allow_ssl_downgrade' => true,
8448 ),
8449 );
8450
8451 private $config;
8452 private $baseDir;
8453 private $repositories;
8454
8455 private $configSource;
8456
8457 private $authConfigSource;
8458 private $useEnvironment;
8459 private $warnedHosts = array();
8460
8461
8462
8463
8464
8465 public function __construct($useEnvironment = true, $baseDir = null)
8466 {
8467
8468  $this->config = static::$defaultConfig;
8469 $this->repositories = static::$defaultRepositories;
8470 $this->useEnvironment = (bool) $useEnvironment;
8471 $this->baseDir = $baseDir;
8472 }
8473
8474 public function setConfigSource(ConfigSourceInterface $source)
8475 {
8476 $this->configSource = $source;
8477 }
8478
8479 public function getConfigSource()
8480 {
8481 return $this->configSource;
8482 }
8483
8484 public function setAuthConfigSource(ConfigSourceInterface $source)
8485 {
8486 $this->authConfigSource = $source;
8487 }
8488
8489 public function getAuthConfigSource()
8490 {
8491 return $this->authConfigSource;
8492 }
8493
8494
8495
8496
8497
8498
8499 public function merge($config)
8500 {
8501
8502  if (!empty($config['config']) && is_array($config['config'])) {
8503 foreach ($config['config'] as $key => $val) {
8504 if (in_array($key, array('bitbucket-oauth', 'github-oauth', 'gitlab-oauth', 'gitlab-token', 'http-basic')) && isset($this->config[$key])) {
8505 $this->config[$key] = array_merge($this->config[$key], $val);
8506 } elseif ('preferred-install' === $key && isset($this->config[$key])) {
8507 if (is_array($val) || is_array($this->config[$key])) {
8508 if (is_string($val)) {
8509 $val = array('*' => $val);
8510 }
8511 if (is_string($this->config[$key])) {
8512 $this->config[$key] = array('*' => $this->config[$key]);
8513 }
8514 $this->config[$key] = array_merge($this->config[$key], $val);
8515
8516  if (isset($this->config[$key]['*'])) {
8517 $wildcard = $this->config[$key]['*'];
8518 unset($this->config[$key]['*']);
8519 $this->config[$key]['*'] = $wildcard;
8520 }
8521 } else {
8522 $this->config[$key] = $val;
8523 }
8524 } else {
8525 $this->config[$key] = $val;
8526 }
8527 }
8528 }
8529
8530 if (!empty($config['repositories']) && is_array($config['repositories'])) {
8531 $this->repositories = array_reverse($this->repositories, true);
8532 $newRepos = array_reverse($config['repositories'], true);
8533 foreach ($newRepos as $name => $repository) {
8534
8535  if (false === $repository) {
8536 $this->disableRepoByName($name);
8537 continue;
8538 }
8539
8540
8541  if (is_array($repository) && 1 === count($repository) && false === current($repository)) {
8542 $this->disableRepoByName(key($repository));
8543 continue;
8544 }
8545
8546
8547  if (is_int($name)) {
8548 $this->repositories[] = $repository;
8549 } else {
8550 if ($name === 'packagist') { 
8551  $this->repositories[$name . '.org'] = $repository;
8552 } else {
8553 $this->repositories[$name] = $repository;
8554 }
8555 }
8556 }
8557 $this->repositories = array_reverse($this->repositories, true);
8558 }
8559 }
8560
8561
8562
8563
8564 public function getRepositories()
8565 {
8566 return $this->repositories;
8567 }
8568
8569
8570
8571
8572
8573
8574
8575
8576
8577 public function get($key, $flags = 0)
8578 {
8579 switch ($key) {
8580 case 'vendor-dir':
8581 case 'bin-dir':
8582 case 'process-timeout':
8583 case 'data-dir':
8584 case 'cache-dir':
8585 case 'cache-files-dir':
8586 case 'cache-repo-dir':
8587 case 'cache-vcs-dir':
8588 case 'cafile':
8589 case 'capath':
8590 case 'htaccess-protect':
8591
8592  $env = 'COMPOSER_' . strtoupper(strtr($key, '-', '_'));
8593
8594 $val = $this->getComposerEnv($env);
8595 $val = rtrim((string) $this->process(false !== $val ? $val : $this->config[$key], $flags), '/\\');
8596 $val = Platform::expandPath($val);
8597
8598 if (substr($key, -4) !== '-dir') {
8599 return $val;
8600 }
8601
8602 return (($flags & self::RELATIVE_PATHS) == self::RELATIVE_PATHS) ? $val : $this->realpath($val);
8603
8604 case 'cache-ttl':
8605 return (int) $this->config[$key];
8606
8607 case 'cache-files-maxsize':
8608 if (!preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $this->config[$key], $matches)) {
8609 throw new \RuntimeException(
8610 "Could not parse the value of 'cache-files-maxsize': {$this->config[$key]}"
8611 );
8612 }
8613 $size = $matches[1];
8614 if (isset($matches[2])) {
8615 switch (strtolower($matches[2])) {
8616 case 'g':
8617 $size *= 1024;
8618
8619  case 'm':
8620 $size *= 1024;
8621
8622  case 'k':
8623 $size *= 1024;
8624 break;
8625 }
8626 }
8627
8628 return $size;
8629
8630 case 'cache-files-ttl':
8631 if (isset($this->config[$key])) {
8632 return (int) $this->config[$key];
8633 }
8634
8635 return (int) $this->config['cache-ttl'];
8636
8637 case 'home':
8638 $val = preg_replace('#^(\$HOME|~)(/|$)#', rtrim(getenv('HOME') ?: getenv('USERPROFILE'), '/\\') . '/', $this->config[$key]);
8639
8640 return rtrim($this->process($val, $flags), '/\\');
8641
8642 case 'bin-compat':
8643 $value = $this->getComposerEnv('COMPOSER_BIN_COMPAT') ?: $this->config[$key];
8644
8645 if (!in_array($value, array('auto', 'full'))) {
8646 throw new \RuntimeException(
8647 "Invalid value for 'bin-compat': {$value}. Expected auto, full"
8648 );
8649 }
8650
8651 return $value;
8652
8653 case 'discard-changes':
8654 if ($env = $this->getComposerEnv('COMPOSER_DISCARD_CHANGES')) {
8655 if (!in_array($env, array('stash', 'true', 'false', '1', '0'), true)) {
8656 throw new \RuntimeException(
8657 "Invalid value for COMPOSER_DISCARD_CHANGES: {$env}. Expected 1, 0, true, false or stash"
8658 );
8659 }
8660 if ('stash' === $env) {
8661 return 'stash';
8662 }
8663
8664
8665  return $env !== 'false' && (bool) $env;
8666 }
8667
8668 if (!in_array($this->config[$key], array(true, false, 'stash'), true)) {
8669 throw new \RuntimeException(
8670 "Invalid value for 'discard-changes': {$this->config[$key]}. Expected true, false or stash"
8671 );
8672 }
8673
8674 return $this->config[$key];
8675
8676 case 'github-protocols':
8677 $protos = $this->config['github-protocols'];
8678 if ($this->config['secure-http'] && false !== ($index = array_search('git', $protos))) {
8679 unset($protos[$index]);
8680 }
8681 if (reset($protos) === 'http') {
8682 throw new \RuntimeException('The http protocol for github is not available anymore, update your config\'s github-protocols to use "https", "git" or "ssh"');
8683 }
8684
8685 return $protos;
8686
8687 case 'disable-tls':
8688 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
8689
8690 case 'secure-http':
8691 return $this->config[$key] !== 'false' && (bool) $this->config[$key];
8692
8693 default:
8694 if (!isset($this->config[$key])) {
8695 return null;
8696 }
8697
8698 return $this->process($this->config[$key], $flags);
8699 }
8700 }
8701
8702 public function all($flags = 0)
8703 {
8704 $all = array(
8705 'repositories' => $this->getRepositories(),
8706 );
8707 foreach (array_keys($this->config) as $key) {
8708 $all['config'][$key] = $this->get($key, $flags);
8709 }
8710
8711 return $all;
8712 }
8713
8714 public function raw()
8715 {
8716 return array(
8717 'repositories' => $this->getRepositories(),
8718 'config' => $this->config,
8719 );
8720 }
8721
8722
8723
8724
8725
8726
8727
8728 public function has($key)
8729 {
8730 return array_key_exists($key, $this->config);
8731 }
8732
8733
8734
8735
8736
8737
8738
8739
8740 private function process($value, $flags)
8741 {
8742 $config = $this;
8743
8744 if (!is_string($value)) {
8745 return $value;
8746 }
8747
8748 return preg_replace_callback('#\{\$(.+)\}#', function ($match) use ($config, $flags) {
8749 return $config->get($match[1], $flags);
8750 }, $value);
8751 }
8752
8753
8754
8755
8756
8757
8758
8759
8760
8761 private function realpath($path)
8762 {
8763 if (preg_match('{^(?:/|[a-z]:|[a-z0-9.]+://)}i', $path)) {
8764 return $path;
8765 }
8766
8767 return $this->baseDir . '/' . $path;
8768 }
8769
8770
8771
8772
8773
8774
8775
8776
8777
8778
8779 private function getComposerEnv($var)
8780 {
8781 if ($this->useEnvironment) {
8782 return getenv($var);
8783 }
8784
8785 return false;
8786 }
8787
8788 private function disableRepoByName($name)
8789 {
8790 if (isset($this->repositories[$name])) {
8791 unset($this->repositories[$name]);
8792 } elseif ($name === 'packagist') { 
8793  unset($this->repositories['packagist.org']);
8794 }
8795 }
8796
8797
8798
8799
8800
8801
8802
8803 public function prohibitUrlByConfig($url, IOInterface $io = null)
8804 {
8805
8806  if (false === filter_var($url, FILTER_VALIDATE_URL)) {
8807 return;
8808 }
8809
8810
8811  $scheme = parse_url($url, PHP_URL_SCHEME);
8812 if (in_array($scheme, array('http', 'git', 'ftp', 'svn'))) {
8813 if ($this->get('secure-http')) {
8814 throw new TransportException("Your configuration does not allow connections to $url. See https://getcomposer.org/doc/06-config.md#secure-http for details.");
8815 } elseif ($io) {
8816 $host = parse_url($url, PHP_URL_HOST);
8817 if (!isset($this->warnedHosts[$host])) {
8818 $io->writeError("<warning>Warning: Accessing $host over $scheme which is an insecure protocol.</warning>");
8819 }
8820 $this->warnedHosts[$host] = true;
8821 }
8822 }
8823 }
8824 }
8825 <?php
8826
8827
8828
8829
8830
8831
8832
8833
8834
8835
8836
8837 namespace Composer\Config;
8838
8839
8840
8841
8842
8843
8844
8845 interface ConfigSourceInterface
8846 {
8847
8848
8849
8850
8851
8852
8853 public function addRepository($name, $config);
8854
8855
8856
8857
8858
8859
8860 public function removeRepository($name);
8861
8862
8863
8864
8865
8866
8867
8868 public function addConfigSetting($name, $value);
8869
8870
8871
8872
8873
8874
8875 public function removeConfigSetting($name);
8876
8877
8878
8879
8880
8881
8882
8883 public function addProperty($name, $value);
8884
8885
8886
8887
8888
8889
8890 public function removeProperty($name);
8891
8892
8893
8894
8895
8896
8897
8898
8899 public function addLink($type, $name, $value);
8900
8901
8902
8903
8904
8905
8906
8907 public function removeLink($type, $name);
8908
8909
8910
8911
8912
8913
8914 public function getName();
8915 }
8916 <?php
8917
8918
8919
8920
8921
8922
8923
8924
8925
8926
8927
8928 namespace Composer\Config;
8929
8930 use Composer\Json\JsonFile;
8931 use Composer\Json\JsonManipulator;
8932 use Composer\Util\Silencer;
8933
8934
8935
8936
8937
8938
8939
8940 class JsonConfigSource implements ConfigSourceInterface
8941 {
8942
8943
8944
8945 private $file;
8946
8947
8948
8949
8950 private $authConfig;
8951
8952
8953
8954
8955
8956
8957
8958 public function __construct(JsonFile $file, $authConfig = false)
8959 {
8960 $this->file = $file;
8961 $this->authConfig = $authConfig;
8962 }
8963
8964
8965
8966
8967 public function getName()
8968 {
8969 return $this->file->getPath();
8970 }
8971
8972
8973
8974
8975 public function addRepository($name, $config)
8976 {
8977 $this->manipulateJson('addRepository', $name, $config, function (&$config, $repo, $repoConfig) {
8978
8979  
8980  if (isset($config['repositories'])) {
8981 foreach ($config['repositories'] as $index => $val) {
8982 if ($index === $repo) {
8983 continue;
8984 }
8985 if (is_numeric($index) && ($val === array('packagist' => false) || $val === array('packagist.org' => false))) {
8986 unset($config['repositories'][$index]);
8987 $config['repositories']['packagist.org'] = false;
8988 break;
8989 }
8990 }
8991 }
8992
8993 $config['repositories'][$repo] = $repoConfig;
8994 });
8995 }
8996
8997
8998
8999
9000 public function removeRepository($name)
9001 {
9002 $this->manipulateJson('removeRepository', $name, function (&$config, $repo) {
9003 unset($config['repositories'][$repo]);
9004 });
9005 }
9006
9007
9008
9009
9010 public function addConfigSetting($name, $value)
9011 {
9012 $authConfig = $this->authConfig;
9013 $this->manipulateJson('addConfigSetting', $name, $value, function (&$config, $key, $val) use ($authConfig) {
9014 if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|platform)\.}', $key)) {
9015 list($key, $host) = explode('.', $key, 2);
9016 if ($authConfig) {
9017 $config[$key][$host] = $val;
9018 } else {
9019 $config['config'][$key][$host] = $val;
9020 }
9021 } else {
9022 $config['config'][$key] = $val;
9023 }
9024 });
9025 }
9026
9027
9028
9029
9030 public function removeConfigSetting($name)
9031 {
9032 $authConfig = $this->authConfig;
9033 $this->manipulateJson('removeConfigSetting', $name, function (&$config, $key) use ($authConfig) {
9034 if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|platform)\.}', $key)) {
9035 list($key, $host) = explode('.', $key, 2);
9036 if ($authConfig) {
9037 unset($config[$key][$host]);
9038 } else {
9039 unset($config['config'][$key][$host]);
9040 }
9041 } else {
9042 unset($config['config'][$key]);
9043 }
9044 });
9045 }
9046
9047
9048
9049
9050 public function addProperty($name, $value)
9051 {
9052 $this->manipulateJson('addProperty', $name, $value, function (&$config, $key, $val) {
9053 if (substr($key, 0, 6) === 'extra.') {
9054 $bits = explode('.', $key);
9055 $last = array_pop($bits);
9056 $arr = &$config['extra'];
9057 foreach ($bits as $bit) {
9058 if (!isset($arr[$bit])) {
9059 $arr[$bit] = array();
9060 }
9061 $arr = &$arr[$bit];
9062 }
9063 $arr[$last] = $val;
9064 } else {
9065 $config[$key] = $val;
9066 }
9067 });
9068 }
9069
9070
9071
9072
9073 public function removeProperty($name)
9074 {
9075 $authConfig = $this->authConfig;
9076 $this->manipulateJson('removeProperty', $name, function (&$config, $key) {
9077 if (substr($key, 0, 6) === 'extra.') {
9078 $bits = explode('.', $key);
9079 $last = array_pop($bits);
9080 $arr = &$config['extra'];
9081 foreach ($bits as $bit) {
9082 if (!isset($arr[$bit])) {
9083 return;
9084 }
9085 $arr = &$arr[$bit];
9086 }
9087 unset($arr[$last]);
9088 } else {
9089 unset($config[$key]);
9090 }
9091 });
9092 }
9093
9094
9095
9096
9097 public function addLink($type, $name, $value)
9098 {
9099 $this->manipulateJson('addLink', $type, $name, $value, function (&$config, $type, $name, $value) {
9100 $config[$type][$name] = $value;
9101 });
9102 }
9103
9104
9105
9106
9107 public function removeLink($type, $name)
9108 {
9109 $this->manipulateJson('removeSubNode', $type, $name, function (&$config, $type, $name) {
9110 unset($config[$type][$name]);
9111 });
9112 }
9113
9114 protected function manipulateJson($method, $args, $fallback)
9115 {
9116 $args = func_get_args();
9117
9118  array_shift($args);
9119 $fallback = array_pop($args);
9120
9121 if ($this->file->exists()) {
9122 if (!is_writable($this->file->getPath())) {
9123 throw new \RuntimeException(sprintf('The file "%s" is not writable.', $this->file->getPath()));
9124 }
9125
9126 if (!is_readable($this->file->getPath())) {
9127 throw new \RuntimeException(sprintf('The file "%s" is not readable.', $this->file->getPath()));
9128 }
9129
9130 $contents = file_get_contents($this->file->getPath());
9131 } elseif ($this->authConfig) {
9132 $contents = "{\n}\n";
9133 } else {
9134 $contents = "{\n    \"config\": {\n    }\n}\n";
9135 }
9136
9137 $manipulator = new JsonManipulator($contents);
9138
9139 $newFile = !$this->file->exists();
9140
9141
9142  if ($this->authConfig && $method === 'addConfigSetting') {
9143 $method = 'addSubNode';
9144 list($mainNode, $name) = explode('.', $args[0], 2);
9145 $args = array($mainNode, $name, $args[1]);
9146 } elseif ($this->authConfig && $method === 'removeConfigSetting') {
9147 $method = 'removeSubNode';
9148 list($mainNode, $name) = explode('.', $args[0], 2);
9149 $args = array($mainNode, $name);
9150 }
9151
9152
9153  if (call_user_func_array(array($manipulator, $method), $args)) {
9154 file_put_contents($this->file->getPath(), $manipulator->getContents());
9155 } else {
9156
9157  $config = $this->file->read();
9158 $this->arrayUnshiftRef($args, $config);
9159 call_user_func_array($fallback, $args);
9160 $this->file->write($config);
9161 }
9162
9163 if ($newFile) {
9164 Silencer::call('chmod', $this->file->getPath(), 0600);
9165 }
9166 }
9167
9168
9169
9170
9171
9172
9173
9174
9175 private function arrayUnshiftRef(&$array, &$value)
9176 {
9177 $return = array_unshift($array, '');
9178 $array[0] = &$value;
9179
9180 return $return;
9181 }
9182 }
9183 <?php
9184
9185
9186
9187
9188
9189
9190
9191
9192
9193
9194
9195 namespace Composer\Console;
9196
9197 use Composer\Util\Platform;
9198 use Composer\Util\Silencer;
9199 use Symfony\Component\Console\Application as BaseApplication;
9200 use Symfony\Component\Console\Input\InputInterface;
9201 use Symfony\Component\Console\Input\InputOption;
9202 use Symfony\Component\Console\Output\OutputInterface;
9203 use Composer\Command;
9204 use Composer\Composer;
9205 use Composer\Factory;
9206 use Composer\IO\IOInterface;
9207 use Composer\IO\ConsoleIO;
9208 use Composer\Json\JsonValidationException;
9209 use Composer\Util\ErrorHandler;
9210 use Composer\EventDispatcher\ScriptExecutionException;
9211 use Composer\Exception\NoSslException;
9212
9213
9214
9215
9216
9217
9218
9219
9220 class Application extends BaseApplication
9221 {
9222
9223
9224
9225 protected $composer;
9226
9227
9228
9229
9230 protected $io;
9231
9232 private static $logo = '   ______
9233   / ____/___  ____ ___  ____  ____  ________  _____
9234  / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
9235 / /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
9236 \____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
9237                     /_/
9238 ';
9239
9240 private $hasPluginCommands = false;
9241 private $disablePluginsByDefault = false;
9242
9243 public function __construct()
9244 {
9245 static $shutdownRegistered = false;
9246
9247 if (function_exists('ini_set') && extension_loaded('xdebug')) {
9248 ini_set('xdebug.show_exception_trace', false);
9249 ini_set('xdebug.scream', false);
9250 }
9251
9252 if (function_exists('date_default_timezone_set') && function_exists('date_default_timezone_get')) {
9253 date_default_timezone_set(Silencer::call('date_default_timezone_get'));
9254 }
9255
9256 if (!$shutdownRegistered) {
9257 $shutdownRegistered = true;
9258
9259 register_shutdown_function(function () {
9260 $lastError = error_get_last();
9261
9262 if ($lastError && $lastError['message'] &&
9263 (strpos($lastError['message'], 'Allowed memory') !== false  ||
9264 strpos($lastError['message'], 'exceeded memory') !== false )) {
9265 echo "\n". 'Check https://getcomposer.org/doc/articles/troubleshooting.md#memory-limit-errors for more info on how to handle out of memory errors.';
9266 }
9267 });
9268 }
9269
9270 parent::__construct('Composer', Composer::VERSION);
9271 }
9272
9273
9274
9275
9276 public function run(InputInterface $input = null, OutputInterface $output = null)
9277 {
9278 if (null === $output) {
9279 $output = Factory::createOutput();
9280 }
9281
9282 return parent::run($input, $output);
9283 }
9284
9285
9286
9287
9288 public function doRun(InputInterface $input, OutputInterface $output)
9289 {
9290 $this->disablePluginsByDefault = $input->hasParameterOption('--no-plugins');
9291
9292 $io = $this->io = new ConsoleIO($input, $output, $this->getHelperSet());
9293 ErrorHandler::register($io);
9294
9295
9296  if ($newWorkDir = $this->getNewWorkingDir($input)) {
9297 $oldWorkingDir = getcwd();
9298 chdir($newWorkDir);
9299 $io->writeError('Changed CWD to ' . getcwd(), true, IOInterface::DEBUG);
9300 }
9301
9302
9303  $commandName = '';
9304 if ($name = $this->getCommandName($input)) {
9305 try {
9306 $commandName = $this->find($name)->getName();
9307 } catch (\InvalidArgumentException $e) {
9308 }
9309 }
9310
9311
9312  if ($io->isInteractive() && !$newWorkDir && !in_array($commandName, array('', 'list', 'init', 'about', 'help', 'diagnose', 'self-update', 'global', 'create-project'), true) && !file_exists(Factory::getComposerFile())) {
9313 $dir = dirname(getcwd());
9314 $home = realpath(getenv('HOME') ?: getenv('USERPROFILE') ?: '/');
9315
9316
9317  while (dirname($dir) !== $dir && $dir !== $home) {
9318 if (file_exists($dir.'/'.Factory::getComposerFile())) {
9319 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)) {
9320 $oldWorkingDir = getcwd();
9321 chdir($dir);
9322 }
9323 break;
9324 }
9325 $dir = dirname($dir);
9326 }
9327 }
9328
9329 if (!$this->disablePluginsByDefault && !$this->hasPluginCommands && 'global' !== $commandName) {
9330 try {
9331 foreach ($this->getPluginCommands() as $command) {
9332 if ($this->has($command->getName())) {
9333 $io->writeError('<warning>Plugin command '.$command->getName().' ('.get_class($command).') would override a Composer command and has been skipped</warning>');
9334 } else {
9335 $this->add($command);
9336 }
9337 }
9338 } catch (NoSslException $e) {
9339
9340  }
9341
9342 $this->hasPluginCommands = true;
9343 }
9344
9345
9346  $isProxyCommand = false;
9347 if ($name = $this->getCommandName($input)) {
9348 try {
9349 $command = $this->find($name);
9350 $commandName = $command->getName();
9351 $isProxyCommand = ($command instanceof Command\BaseCommand && $command->isProxyCommand());
9352 } catch (\InvalidArgumentException $e) {
9353 }
9354 }
9355
9356 if (!$isProxyCommand) {
9357 $io->writeError(sprintf(
9358 'Running %s (%s) with %s on %s',
9359 Composer::VERSION,
9360 Composer::RELEASE_DATE,
9361 defined('HHVM_VERSION') ? 'HHVM '.HHVM_VERSION : 'PHP '.PHP_VERSION,
9362 function_exists('php_uname') ? php_uname('s') . ' / ' . php_uname('r') : 'Unknown OS'
9363 ), true, IOInterface::DEBUG);
9364
9365 if (PHP_VERSION_ID < 50302) {
9366 $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>');
9367 }
9368
9369 if (extension_loaded('xdebug') && !getenv('COMPOSER_DISABLE_XDEBUG_WARN')) {
9370 $io->writeError('<warning>You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug</warning>');
9371 }
9372
9373 if (defined('COMPOSER_DEV_WARNING_TIME') && $commandName !== 'self-update' && $commandName !== 'selfupdate' && time() > COMPOSER_DEV_WARNING_TIME) {
9374 $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']));
9375 }
9376
9377 if (getenv('COMPOSER_NO_INTERACTION')) {
9378 $input->setInteractive(false);
9379 }
9380
9381 if (!Platform::isWindows() && function_exists('exec') && !getenv('COMPOSER_ALLOW_SUPERUSER')) {
9382 if (function_exists('posix_getuid') && posix_getuid() === 0) {
9383 if ($commandName !== 'self-update' && $commandName !== 'selfupdate') {
9384 $io->writeError('<warning>Do not run Composer as root/super user! See https://getcomposer.org/root for details</warning>');
9385 }
9386 if ($uid = (int) getenv('SUDO_UID')) {
9387
9388  
9389  Silencer::call('exec', "sudo -u \\#{$uid} sudo -K > /dev/null 2>&1");
9390 }
9391 }
9392
9393  Silencer::call('exec', 'sudo -K > /dev/null 2>&1');
9394 }
9395
9396
9397  Silencer::call(function () use ($io) {
9398 $tempfile = sys_get_temp_dir() . '/temp-' . md5(microtime());
9399 if (!(file_put_contents($tempfile, __FILE__) && (file_get_contents($tempfile) == __FILE__) && unlink($tempfile) && !file_exists($tempfile))) {
9400 $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()));
9401 }
9402 });
9403
9404
9405  $file = Factory::getComposerFile();
9406 if (is_file($file) && is_readable($file) && is_array($composer = json_decode(file_get_contents($file), true))) {
9407 if (isset($composer['scripts']) && is_array($composer['scripts'])) {
9408 foreach ($composer['scripts'] as $script => $dummy) {
9409 if (!defined('Composer\Script\ScriptEvents::'.str_replace('-', '_', strtoupper($script)))) {
9410 if ($this->has($script)) {
9411 $io->writeError('<warning>A script named '.$script.' would override a Composer command and has been skipped</warning>');
9412 } else {
9413 $this->add(new Command\ScriptAliasCommand($script));
9414 }
9415 }
9416 }
9417 }
9418 }
9419 }
9420
9421 try {
9422 if ($input->hasParameterOption('--profile')) {
9423 $startTime = microtime(true);
9424 $this->io->enableDebugging($startTime);
9425 }
9426
9427 $result = parent::doRun($input, $output);
9428
9429 if (isset($oldWorkingDir)) {
9430 chdir($oldWorkingDir);
9431 }
9432
9433 if (isset($startTime)) {
9434 $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');
9435 }
9436
9437 restore_error_handler();
9438
9439 return $result;
9440 } catch (ScriptExecutionException $e) {
9441 return $e->getCode();
9442 } catch (\Exception $e) {
9443 $this->hintCommonErrors($e);
9444 restore_error_handler();
9445 throw $e;
9446 }
9447 }
9448
9449
9450
9451
9452
9453
9454 private function getNewWorkingDir(InputInterface $input)
9455 {
9456 $workingDir = $input->getParameterOption(array('--working-dir', '-d'));
9457 if (false !== $workingDir && !is_dir($workingDir)) {
9458 throw new \RuntimeException('Invalid working directory specified, '.$workingDir.' does not exist.');
9459 }
9460
9461 return $workingDir;
9462 }
9463
9464
9465
9466
9467 private function hintCommonErrors($exception)
9468 {
9469 $io = $this->getIO();
9470
9471 Silencer::suppress();
9472 try {
9473 $composer = $this->getComposer(false, true);
9474 if ($composer) {
9475 $config = $composer->getConfig();
9476
9477 $minSpaceFree = 1024 * 1024;
9478 if ((($df = disk_free_space($dir = $config->get('home'))) !== false && $df < $minSpaceFree)
9479 || (($df = disk_free_space($dir = $config->get('vendor-dir'))) !== false && $df < $minSpaceFree)
9480 || (($df = disk_free_space($dir = sys_get_temp_dir())) !== false && $df < $minSpaceFree)
9481 ) {
9482 $io->writeError('<error>The disk hosting '.$dir.' is full, this may be the cause of the following exception</error>', true, IOInterface::QUIET);
9483 }
9484 }
9485 } catch (\Exception $e) {
9486 }
9487 Silencer::restore();
9488
9489 if (Platform::isWindows() && false !== strpos($exception->getMessage(), 'The system cannot find the path specified')) {
9490 $io->writeError('<error>The following exception may be caused by a stale entry in your cmd.exe AutoRun</error>', true, IOInterface::QUIET);
9491 $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);
9492 }
9493
9494 if (false !== strpos($exception->getMessage(), 'fork failed - Cannot allocate memory')) {
9495 $io->writeError('<error>The following exception is caused by a lack of memory or swap, or not having swap configured</error>', true, IOInterface::QUIET);
9496 $io->writeError('<error>Check https://getcomposer.org/doc/articles/troubleshooting.md#proc-open-fork-failed-errors for details</error>', true, IOInterface::QUIET);
9497 }
9498 }
9499
9500
9501
9502
9503
9504
9505
9506 public function getComposer($required = true, $disablePlugins = null)
9507 {
9508 if (null === $disablePlugins) {
9509 $disablePlugins = $this->disablePluginsByDefault;
9510 }
9511
9512 if (null === $this->composer) {
9513 try {
9514 $this->composer = Factory::create($this->io, null, $disablePlugins);
9515 } catch (\InvalidArgumentException $e) {
9516 if ($required) {
9517 $this->io->writeError($e->getMessage());
9518 exit(1);
9519 }
9520 } catch (JsonValidationException $e) {
9521 $errors = ' - ' . implode(PHP_EOL . ' - ', $e->getErrors());
9522 $message = $e->getMessage() . ':' . PHP_EOL . $errors;
9523 throw new JsonValidationException($message);
9524 }
9525 }
9526
9527 return $this->composer;
9528 }
9529
9530
9531
9532
9533 public function resetComposer()
9534 {
9535 $this->composer = null;
9536 }
9537
9538
9539
9540
9541 public function getIO()
9542 {
9543 return $this->io;
9544 }
9545
9546 public function getHelp()
9547 {
9548 return self::$logo . parent::getHelp();
9549 }
9550
9551
9552
9553
9554 protected function getDefaultCommands()
9555 {
9556 $commands = array_merge(parent::getDefaultCommands(), array(
9557 new Command\AboutCommand(),
9558 new Command\ConfigCommand(),
9559 new Command\DependsCommand(),
9560 new Command\ProhibitsCommand(),
9561 new Command\InitCommand(),
9562 new Command\InstallCommand(),
9563 new Command\CreateProjectCommand(),
9564 new Command\UpdateCommand(),
9565 new Command\SearchCommand(),
9566 new Command\ValidateCommand(),
9567 new Command\ShowCommand(),
9568 new Command\SuggestsCommand(),
9569 new Command\RequireCommand(),
9570 new Command\DumpAutoloadCommand(),
9571 new Command\StatusCommand(),
9572 new Command\ArchiveCommand(),
9573 new Command\DiagnoseCommand(),
9574 new Command\RunScriptCommand(),
9575 new Command\LicensesCommand(),
9576 new Command\GlobalCommand(),
9577 new Command\ClearCacheCommand(),
9578 new Command\RemoveCommand(),
9579 new Command\HomeCommand(),
9580 new Command\ExecCommand(),
9581 new Command\OutdatedCommand(),
9582 ));
9583
9584 if ('phar:' === substr(__FILE__, 0, 5)) {
9585 $commands[] = new Command\SelfUpdateCommand();
9586 }
9587
9588 return $commands;
9589 }
9590
9591
9592
9593
9594 public function getLongVersion()
9595 {
9596 if (Composer::BRANCH_ALIAS_VERSION) {
9597 return sprintf(
9598 '<info>%s</info> version <comment>%s (%s)</comment> %s',
9599 $this->getName(),
9600 Composer::BRANCH_ALIAS_VERSION,
9601 $this->getVersion(),
9602 Composer::RELEASE_DATE
9603 );
9604 }
9605
9606 return parent::getLongVersion() . ' ' . Composer::RELEASE_DATE;
9607 }
9608
9609
9610
9611
9612 protected function getDefaultInputDefinition()
9613 {
9614 $definition = parent::getDefaultInputDefinition();
9615 $definition->addOption(new InputOption('--profile', null, InputOption::VALUE_NONE, 'Display timing and memory usage information'));
9616 $definition->addOption(new InputOption('--no-plugins', null, InputOption::VALUE_NONE, 'Whether to disable plugins.'));
9617 $definition->addOption(new InputOption('--working-dir', '-d', InputOption::VALUE_REQUIRED, 'If specified, use the given directory as working directory.'));
9618
9619 return $definition;
9620 }
9621
9622 private function getPluginCommands()
9623 {
9624 $commands = array();
9625
9626 $composer = $this->getComposer(false, false);
9627 if (null === $composer) {
9628 $composer = Factory::createGlobal($this->io, false);
9629 }
9630
9631 if (null !== $composer) {
9632 $pm = $composer->getPluginManager();
9633 foreach ($pm->getPluginCapabilities('Composer\Plugin\Capability\CommandProvider', array('composer' => $composer, 'io' => $this->io)) as $capability) {
9634 $newCommands = $capability->getCommands();
9635 if (!is_array($newCommands)) {
9636 throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' failed to return an array from getCommands');
9637 }
9638 foreach ($newCommands as $command) {
9639 if (!$command instanceof Command\BaseCommand) {
9640 throw new \UnexpectedValueException('Plugin capability '.get_class($capability).' returned an invalid value, we expected an array of Composer\Command\BaseCommand objects');
9641 }
9642 }
9643 $commands = array_merge($commands, $newCommands);
9644 }
9645 }
9646
9647 return $commands;
9648 }
9649 }
9650 <?php
9651
9652
9653
9654
9655
9656
9657
9658
9659
9660
9661
9662 namespace Composer\Console;
9663
9664 use Symfony\Component\Console\Formatter\OutputFormatter;
9665
9666
9667
9668
9669 class HtmlOutputFormatter extends OutputFormatter
9670 {
9671 private static $availableForegroundColors = array(
9672 30 => 'black',
9673 31 => 'red',
9674 32 => 'green',
9675 33 => 'yellow',
9676 34 => 'blue',
9677 35 => 'magenta',
9678 36 => 'cyan',
9679 37 => 'white',
9680 );
9681 private static $availableBackgroundColors = array(
9682 40 => 'black',
9683 41 => 'red',
9684 42 => 'green',
9685 43 => 'yellow',
9686 44 => 'blue',
9687 45 => 'magenta',
9688 46 => 'cyan',
9689 47 => 'white',
9690 );
9691 private static $availableOptions = array(
9692 1 => 'bold',
9693 4 => 'underscore',
9694
9695  
9696  
9697  );
9698
9699
9700
9701
9702 public function __construct(array $styles = array())
9703 {
9704 parent::__construct(true, $styles);
9705 }
9706
9707 public function format($message)
9708 {
9709 $formatted = parent::format($message);
9710
9711 $clearEscapeCodes = '(?:39|49|0|22|24|25|27|28)';
9712
9713 return preg_replace_callback("{\033\[([0-9;]+)m(.*?)\033\[(?:".$clearEscapeCodes.";)*?".$clearEscapeCodes."m}s", array($this, 'formatHtml'), $formatted);
9714 }
9715
9716 private function formatHtml($matches)
9717 {
9718 $out = '<span style="';
9719 foreach (explode(';', $matches[1]) as $code) {
9720 if (isset(self::$availableForegroundColors[$code])) {
9721 $out .= 'color:'.self::$availableForegroundColors[$code].';';
9722 } elseif (isset(self::$availableBackgroundColors[$code])) {
9723 $out .= 'background-color:'.self::$availableBackgroundColors[$code].';';
9724 } elseif (isset(self::$availableOptions[$code])) {
9725 switch (self::$availableOptions[$code]) {
9726 case 'bold':
9727 $out .= 'font-weight:bold;';
9728 break;
9729
9730 case 'underscore':
9731 $out .= 'text-decoration:underline;';
9732 break;
9733 }
9734 }
9735 }
9736
9737 return $out.'">'.$matches[2].'</span>';
9738 }
9739 }
9740 <?php
9741
9742
9743
9744
9745
9746
9747
9748
9749
9750
9751
9752 namespace Composer\DependencyResolver;
9753
9754
9755
9756
9757
9758
9759 class Decisions implements \Iterator, \Countable
9760 {
9761 const DECISION_LITERAL = 0;
9762 const DECISION_REASON = 1;
9763
9764 protected $pool;
9765 protected $decisionMap;
9766 protected $decisionQueue = array();
9767
9768 public function __construct($pool)
9769 {
9770 $this->pool = $pool;
9771 $this->decisionMap = array();
9772 }
9773
9774 public function decide($literal, $level, $why)
9775 {
9776 $this->addDecision($literal, $level);
9777 $this->decisionQueue[] = array(
9778 self::DECISION_LITERAL => $literal,
9779 self::DECISION_REASON => $why,
9780 );
9781 }
9782
9783 public function satisfy($literal)
9784 {
9785 $packageId = abs($literal);
9786
9787 return (
9788 $literal > 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 ||
9789 $literal < 0 && isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0
9790 );
9791 }
9792
9793 public function conflict($literal)
9794 {
9795 $packageId = abs($literal);
9796
9797 return (
9798 (isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0 && $literal < 0) ||
9799 (isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] < 0 && $literal > 0)
9800 );
9801 }
9802
9803 public function decided($literalOrPackageId)
9804 {
9805 return !empty($this->decisionMap[abs($literalOrPackageId)]);
9806 }
9807
9808 public function undecided($literalOrPackageId)
9809 {
9810 return empty($this->decisionMap[abs($literalOrPackageId)]);
9811 }
9812
9813 public function decidedInstall($literalOrPackageId)
9814 {
9815 $packageId = abs($literalOrPackageId);
9816
9817 return isset($this->decisionMap[$packageId]) && $this->decisionMap[$packageId] > 0;
9818 }
9819
9820 public function decisionLevel($literalOrPackageId)
9821 {
9822 $packageId = abs($literalOrPackageId);
9823 if (isset($this->decisionMap[$packageId])) {
9824 return abs($this->decisionMap[$packageId]);
9825 }
9826
9827 return 0;
9828 }
9829
9830 public function decisionRule($literalOrPackageId)
9831 {
9832 $packageId = abs($literalOrPackageId);
9833
9834 foreach ($this->decisionQueue as $i => $decision) {
9835 if ($packageId === abs($decision[self::DECISION_LITERAL])) {
9836 return $decision[self::DECISION_REASON];
9837 }
9838 }
9839
9840 return null;
9841 }
9842
9843 public function atOffset($queueOffset)
9844 {
9845 return $this->decisionQueue[$queueOffset];
9846 }
9847
9848 public function validOffset($queueOffset)
9849 {
9850 return $queueOffset >= 0 && $queueOffset < count($this->decisionQueue);
9851 }
9852
9853 public function lastReason()
9854 {
9855 return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_REASON];
9856 }
9857
9858 public function lastLiteral()
9859 {
9860 return $this->decisionQueue[count($this->decisionQueue) - 1][self::DECISION_LITERAL];
9861 }
9862
9863 public function reset()
9864 {
9865 while ($decision = array_pop($this->decisionQueue)) {
9866 $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
9867 }
9868 }
9869
9870 public function resetToOffset($offset)
9871 {
9872 while (count($this->decisionQueue) > $offset + 1) {
9873 $decision = array_pop($this->decisionQueue);
9874 $this->decisionMap[abs($decision[self::DECISION_LITERAL])] = 0;
9875 }
9876 }
9877
9878 public function revertLast()
9879 {
9880 $this->decisionMap[abs($this->lastLiteral())] = 0;
9881 array_pop($this->decisionQueue);
9882 }
9883
9884 public function count()
9885 {
9886 return count($this->decisionQueue);
9887 }
9888
9889 public function rewind()
9890 {
9891 end($this->decisionQueue);
9892 }
9893
9894 public function current()
9895 {
9896 return current($this->decisionQueue);
9897 }
9898
9899 public function key()
9900 {
9901 return key($this->decisionQueue);
9902 }
9903
9904 public function next()
9905 {
9906 return prev($this->decisionQueue);
9907 }
9908
9909 public function valid()
9910 {
9911 return false !== current($this->decisionQueue);
9912 }
9913
9914 public function isEmpty()
9915 {
9916 return count($this->decisionQueue) === 0;
9917 }
9918
9919 protected function addDecision($literal, $level)
9920 {
9921 $packageId = abs($literal);
9922
9923 $previousDecision = isset($this->decisionMap[$packageId]) ? $this->decisionMap[$packageId] : null;
9924 if ($previousDecision != 0) {
9925 $literalString = $this->pool->literalToString($literal);
9926 $package = $this->pool->literalToPackage($literal);
9927 throw new SolverBugException(
9928 "Trying to decide $literalString on level $level, even though $package was previously decided as ".(int) $previousDecision."."
9929 );
9930 }
9931
9932 if ($literal > 0) {
9933 $this->decisionMap[$packageId] = $level;
9934 } else {
9935 $this->decisionMap[$packageId] = -$level;
9936 }
9937 }
9938 }
9939 <?php
9940
9941
9942
9943
9944
9945
9946
9947
9948
9949
9950
9951 namespace Composer\DependencyResolver;
9952
9953 use Composer\Package\PackageInterface;
9954 use Composer\Package\AliasPackage;
9955 use Composer\Package\BasePackage;
9956 use Composer\Semver\Constraint\Constraint;
9957
9958
9959
9960
9961
9962 class DefaultPolicy implements PolicyInterface
9963 {
9964 private $preferStable;
9965 private $preferLowest;
9966
9967 public function __construct($preferStable = false, $preferLowest = false)
9968 {
9969 $this->preferStable = $preferStable;
9970 $this->preferLowest = $preferLowest;
9971 }
9972
9973 public function versionCompare(PackageInterface $a, PackageInterface $b, $operator)
9974 {
9975 if ($this->preferStable && ($stabA = $a->getStability()) !== ($stabB = $b->getStability())) {
9976 return BasePackage::$stabilities[$stabA] < BasePackage::$stabilities[$stabB];
9977 }
9978
9979 $constraint = new Constraint($operator, $b->getVersion());
9980 $version = new Constraint('==', $a->getVersion());
9981
9982 return $constraint->matchSpecific($version, true);
9983 }
9984
9985 public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package, $mustMatchName = false)
9986 {
9987 $packages = array();
9988
9989 foreach ($pool->whatProvides($package->getName(), null, $mustMatchName) as $candidate) {
9990 if ($candidate !== $package) {
9991 $packages[] = $candidate;
9992 }
9993 }
9994
9995 return $packages;
9996 }
9997
9998 public function getPriority(Pool $pool, PackageInterface $package)
9999 {
10000 return $pool->getPriority($package->getRepository());
10001 }
10002
10003 public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null)
10004 {
10005 $packages = $this->groupLiteralsByNamePreferInstalled($pool, $installedMap, $literals);
10006
10007 foreach ($packages as &$literals) {
10008 $policy = $this;
10009 usort($literals, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
10010 return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage, true);
10011 });
10012 }
10013
10014 foreach ($packages as &$literals) {
10015 $literals = $this->pruneToHighestPriorityOrInstalled($pool, $installedMap, $literals);
10016
10017 $literals = $this->pruneToBestVersion($pool, $literals);
10018
10019 $literals = $this->pruneRemoteAliases($pool, $literals);
10020 }
10021
10022 $selected = call_user_func_array('array_merge', $packages);
10023
10024
10025  usort($selected, function ($a, $b) use ($policy, $pool, $installedMap, $requiredPackage) {
10026 return $policy->compareByPriorityPreferInstalled($pool, $installedMap, $pool->literalToPackage($a), $pool->literalToPackage($b), $requiredPackage);
10027 });
10028
10029 return $selected;
10030 }
10031
10032 protected function groupLiteralsByNamePreferInstalled(Pool $pool, array $installedMap, $literals)
10033 {
10034 $packages = array();
10035 foreach ($literals as $literal) {
10036 $packageName = $pool->literalToPackage($literal)->getName();
10037
10038 if (!isset($packages[$packageName])) {
10039 $packages[$packageName] = array();
10040 }
10041
10042 if (isset($installedMap[abs($literal)])) {
10043 array_unshift($packages[$packageName], $literal);
10044 } else {
10045 $packages[$packageName][] = $literal;
10046 }
10047 }
10048
10049 return $packages;
10050 }
10051
10052
10053
10054
10055 public function compareByPriorityPreferInstalled(Pool $pool, array $installedMap, PackageInterface $a, PackageInterface $b, $requiredPackage = null, $ignoreReplace = false)
10056 {
10057 if ($a->getRepository() === $b->getRepository()) {
10058
10059  if ($a->getName() === $b->getName()) {
10060 $aAliased = $a instanceof AliasPackage;
10061 $bAliased = $b instanceof AliasPackage;
10062 if ($aAliased && !$bAliased) {
10063 return -1; 
10064  }
10065 if (!$aAliased && $bAliased) {
10066 return 1; 
10067  }
10068 }
10069
10070 if (!$ignoreReplace) {
10071
10072  if ($this->replaces($a, $b)) {
10073 return 1; 
10074  }
10075 if ($this->replaces($b, $a)) {
10076 return -1; 
10077  }
10078
10079
10080  
10081  if ($requiredPackage && false !== ($pos = strpos($requiredPackage, '/'))) {
10082 $requiredVendor = substr($requiredPackage, 0, $pos);
10083
10084 $aIsSameVendor = substr($a->getName(), 0, $pos) === $requiredVendor;
10085 $bIsSameVendor = substr($b->getName(), 0, $pos) === $requiredVendor;
10086
10087 if ($bIsSameVendor !== $aIsSameVendor) {
10088 return $aIsSameVendor ? -1 : 1;
10089 }
10090 }
10091 }
10092
10093
10094  if ($a->id === $b->id) {
10095 return 0;
10096 }
10097
10098 return ($a->id < $b->id) ? -1 : 1;
10099 }
10100
10101 if (isset($installedMap[$a->id])) {
10102 return -1;
10103 }
10104
10105 if (isset($installedMap[$b->id])) {
10106 return 1;
10107 }
10108
10109 return ($this->getPriority($pool, $a) > $this->getPriority($pool, $b)) ? -1 : 1;
10110 }
10111
10112
10113
10114
10115
10116
10117
10118
10119
10120
10121
10122 protected function replaces(PackageInterface $source, PackageInterface $target)
10123 {
10124 foreach ($source->getReplaces() as $link) {
10125 if ($link->getTarget() === $target->getName()
10126
10127
10128  ) {
10129 return true;
10130 }
10131 }
10132
10133 return false;
10134 }
10135
10136 protected function pruneToBestVersion(Pool $pool, $literals)
10137 {
10138 $operator = $this->preferLowest ? '<' : '>';
10139 $bestLiterals = array($literals[0]);
10140 $bestPackage = $pool->literalToPackage($literals[0]);
10141 foreach ($literals as $i => $literal) {
10142 if (0 === $i) {
10143 continue;
10144 }
10145
10146 $package = $pool->literalToPackage($literal);
10147
10148 if ($this->versionCompare($package, $bestPackage, $operator)) {
10149 $bestPackage = $package;
10150 $bestLiterals = array($literal);
10151 } elseif ($this->versionCompare($package, $bestPackage, '==')) {
10152 $bestLiterals[] = $literal;
10153 }
10154 }
10155
10156 return $bestLiterals;
10157 }
10158
10159
10160
10161
10162 protected function pruneToHighestPriorityOrInstalled(Pool $pool, array $installedMap, array $literals)
10163 {
10164 $selected = array();
10165
10166 $priority = null;
10167
10168 foreach ($literals as $literal) {
10169 $package = $pool->literalToPackage($literal);
10170
10171 if (isset($installedMap[$package->id])) {
10172 $selected[] = $literal;
10173 continue;
10174 }
10175
10176 if (null === $priority) {
10177 $priority = $this->getPriority($pool, $package);
10178 }
10179
10180 if ($this->getPriority($pool, $package) != $priority) {
10181 break;
10182 }
10183
10184 $selected[] = $literal;
10185 }
10186
10187 return $selected;
10188 }
10189
10190
10191
10192
10193
10194
10195 protected function pruneRemoteAliases(Pool $pool, array $literals)
10196 {
10197 $hasLocalAlias = false;
10198
10199 foreach ($literals as $literal) {
10200 $package = $pool->literalToPackage($literal);
10201
10202 if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
10203 $hasLocalAlias = true;
10204 break;
10205 }
10206 }
10207
10208 if (!$hasLocalAlias) {
10209 return $literals;
10210 }
10211
10212 $selected = array();
10213 foreach ($literals as $literal) {
10214 $package = $pool->literalToPackage($literal);
10215
10216 if ($package instanceof AliasPackage && $package->isRootPackageAlias()) {
10217 $selected[] = $literal;
10218 }
10219 }
10220
10221 return $selected;
10222 }
10223 }
10224 <?php
10225
10226
10227
10228
10229
10230
10231
10232
10233
10234
10235
10236 namespace Composer\DependencyResolver;
10237
10238 use Composer\Package\PackageInterface;
10239 use Composer\Package\Link;
10240
10241
10242
10243
10244 class GenericRule extends Rule
10245 {
10246 protected $literals;
10247
10248
10249
10250
10251
10252
10253
10254 public function __construct(array $literals, $reason, $reasonData, $job = null)
10255 {
10256 parent::__construct($reason, $reasonData, $job);
10257
10258
10259  sort($literals);
10260
10261 $this->literals = $literals;
10262 }
10263
10264 public function getLiterals()
10265 {
10266 return $this->literals;
10267 }
10268
10269 public function getHash()
10270 {
10271 $data = unpack('ihash', md5(implode(',', $this->literals), true));
10272
10273 return $data['hash'];
10274 }
10275
10276
10277
10278
10279
10280
10281
10282
10283
10284 public function equals(Rule $rule)
10285 {
10286 return $this->literals === $rule->getLiterals();
10287 }
10288
10289 public function isAssertion()
10290 {
10291 return 1 === count($this->literals);
10292 }
10293
10294
10295
10296
10297
10298
10299 public function __toString()
10300 {
10301 $result = ($this->isDisabled()) ? 'disabled(' : '(';
10302
10303 foreach ($this->literals as $i => $literal) {
10304 if ($i != 0) {
10305 $result .= '|';
10306 }
10307 $result .= $literal;
10308 }
10309
10310 $result .= ')';
10311
10312 return $result;
10313 }
10314 }
10315 <?php
10316
10317
10318
10319
10320
10321
10322
10323
10324
10325
10326
10327 namespace Composer\DependencyResolver\Operation;
10328
10329 use Composer\Package\PackageInterface;
10330
10331
10332
10333
10334
10335
10336 class InstallOperation extends SolverOperation
10337 {
10338 protected $package;
10339
10340
10341
10342
10343
10344
10345
10346 public function __construct(PackageInterface $package, $reason = null)
10347 {
10348 parent::__construct($reason);
10349
10350 $this->package = $package;
10351 }
10352
10353
10354
10355
10356
10357
10358 public function getPackage()
10359 {
10360 return $this->package;
10361 }
10362
10363
10364
10365
10366
10367
10368 public function getJobType()
10369 {
10370 return 'install';
10371 }
10372
10373
10374
10375
10376 public function __toString()
10377 {
10378 return 'Installing '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
10379 }
10380 }
10381 <?php
10382
10383
10384
10385
10386
10387
10388
10389
10390
10391
10392
10393 namespace Composer\DependencyResolver\Operation;
10394
10395 use Composer\Package\AliasPackage;
10396 use Composer\Package\PackageInterface;
10397
10398
10399
10400
10401
10402
10403 class MarkAliasInstalledOperation extends SolverOperation
10404 {
10405 protected $package;
10406
10407
10408
10409
10410
10411
10412
10413 public function __construct(AliasPackage $package, $reason = null)
10414 {
10415 parent::__construct($reason);
10416
10417 $this->package = $package;
10418 }
10419
10420
10421
10422
10423
10424
10425 public function getPackage()
10426 {
10427 return $this->package;
10428 }
10429
10430
10431
10432
10433
10434
10435 public function getJobType()
10436 {
10437 return 'markAliasInstalled';
10438 }
10439
10440
10441
10442
10443 public function __toString()
10444 {
10445 return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as installed, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
10446 }
10447 }
10448 <?php
10449
10450
10451
10452
10453
10454
10455
10456
10457
10458
10459
10460 namespace Composer\DependencyResolver\Operation;
10461
10462 use Composer\Package\AliasPackage;
10463 use Composer\Package\PackageInterface;
10464
10465
10466
10467
10468
10469
10470 class MarkAliasUninstalledOperation extends SolverOperation
10471 {
10472 protected $package;
10473
10474
10475
10476
10477
10478
10479
10480 public function __construct(AliasPackage $package, $reason = null)
10481 {
10482 parent::__construct($reason);
10483
10484 $this->package = $package;
10485 }
10486
10487
10488
10489
10490
10491
10492 public function getPackage()
10493 {
10494 return $this->package;
10495 }
10496
10497
10498
10499
10500
10501
10502 public function getJobType()
10503 {
10504 return 'markAliasUninstalled';
10505 }
10506
10507
10508
10509
10510 public function __toString()
10511 {
10512 return 'Marking '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).') as uninstalled, alias of '.$this->package->getAliasOf()->getPrettyName().' ('.$this->formatVersion($this->package->getAliasOf()).')';
10513 }
10514 }
10515 <?php
10516
10517
10518
10519
10520
10521
10522
10523
10524
10525
10526
10527 namespace Composer\DependencyResolver\Operation;
10528
10529
10530
10531
10532
10533
10534 interface OperationInterface
10535 {
10536
10537
10538
10539
10540
10541 public function getJobType();
10542
10543
10544
10545
10546
10547
10548 public function getReason();
10549
10550
10551
10552
10553
10554
10555 public function __toString();
10556 }
10557 <?php
10558
10559
10560
10561
10562
10563
10564
10565
10566
10567
10568
10569 namespace Composer\DependencyResolver\Operation;
10570
10571 use Composer\Package\PackageInterface;
10572
10573
10574
10575
10576
10577
10578 abstract class SolverOperation implements OperationInterface
10579 {
10580 protected $reason;
10581
10582
10583
10584
10585
10586
10587 public function __construct($reason = null)
10588 {
10589 $this->reason = $reason;
10590 }
10591
10592
10593
10594
10595
10596
10597 public function getReason()
10598 {
10599 return $this->reason;
10600 }
10601
10602 protected function formatVersion(PackageInterface $package)
10603 {
10604 return $package->getFullPrettyVersion();
10605 }
10606 }
10607 <?php
10608
10609
10610
10611
10612
10613
10614
10615
10616
10617
10618
10619 namespace Composer\DependencyResolver\Operation;
10620
10621 use Composer\Package\PackageInterface;
10622
10623
10624
10625
10626
10627
10628 class UninstallOperation extends SolverOperation
10629 {
10630 protected $package;
10631
10632
10633
10634
10635
10636
10637
10638 public function __construct(PackageInterface $package, $reason = null)
10639 {
10640 parent::__construct($reason);
10641
10642 $this->package = $package;
10643 }
10644
10645
10646
10647
10648
10649
10650 public function getPackage()
10651 {
10652 return $this->package;
10653 }
10654
10655
10656
10657
10658
10659
10660 public function getJobType()
10661 {
10662 return 'uninstall';
10663 }
10664
10665
10666
10667
10668 public function __toString()
10669 {
10670 return 'Uninstalling '.$this->package->getPrettyName().' ('.$this->formatVersion($this->package).')';
10671 }
10672 }
10673 <?php
10674
10675
10676
10677
10678
10679
10680
10681
10682
10683
10684
10685 namespace Composer\DependencyResolver\Operation;
10686
10687 use Composer\Package\PackageInterface;
10688
10689
10690
10691
10692
10693
10694 class UpdateOperation extends SolverOperation
10695 {
10696 protected $initialPackage;
10697 protected $targetPackage;
10698
10699
10700
10701
10702
10703
10704
10705
10706 public function __construct(PackageInterface $initial, PackageInterface $target, $reason = null)
10707 {
10708 parent::__construct($reason);
10709
10710 $this->initialPackage = $initial;
10711 $this->targetPackage = $target;
10712 }
10713
10714
10715
10716
10717
10718
10719 public function getInitialPackage()
10720 {
10721 return $this->initialPackage;
10722 }
10723
10724
10725
10726
10727
10728
10729 public function getTargetPackage()
10730 {
10731 return $this->targetPackage;
10732 }
10733
10734
10735
10736
10737
10738
10739 public function getJobType()
10740 {
10741 return 'update';
10742 }
10743
10744
10745
10746
10747 public function __toString()
10748 {
10749 return 'Updating '.$this->initialPackage->getPrettyName().' ('.$this->formatVersion($this->initialPackage).') to '.
10750 $this->targetPackage->getPrettyName(). ' ('.$this->formatVersion($this->targetPackage).')';
10751 }
10752 }
10753 <?php
10754
10755
10756
10757
10758
10759
10760
10761
10762
10763
10764
10765 namespace Composer\DependencyResolver;
10766
10767 use Composer\Package\PackageInterface;
10768
10769
10770
10771
10772 interface PolicyInterface
10773 {
10774 public function versionCompare(PackageInterface $a, PackageInterface $b, $operator);
10775
10776 public function findUpdatePackages(Pool $pool, array $installedMap, PackageInterface $package);
10777
10778 public function selectPreferredPackages(Pool $pool, array $installedMap, array $literals, $requiredPackage = null);
10779 }
10780 <?php
10781
10782
10783
10784
10785
10786
10787
10788
10789
10790
10791
10792 namespace Composer\DependencyResolver;
10793
10794 use Composer\Package\BasePackage;
10795 use Composer\Package\AliasPackage;
10796 use Composer\Package\Version\VersionParser;
10797 use Composer\Semver\Constraint\ConstraintInterface;
10798 use Composer\Semver\Constraint\Constraint;
10799 use Composer\Semver\Constraint\EmptyConstraint;
10800 use Composer\Repository\RepositoryInterface;
10801 use Composer\Repository\CompositeRepository;
10802 use Composer\Repository\ComposerRepository;
10803 use Composer\Repository\InstalledRepositoryInterface;
10804 use Composer\Repository\PlatformRepository;
10805 use Composer\Package\PackageInterface;
10806
10807
10808
10809
10810
10811
10812
10813 class Pool implements \Countable
10814 {
10815 const MATCH_NAME = -1;
10816 const MATCH_NONE = 0;
10817 const MATCH = 1;
10818 const MATCH_PROVIDE = 2;
10819 const MATCH_REPLACE = 3;
10820 const MATCH_FILTERED = 4;
10821
10822 protected $repositories = array();
10823 protected $providerRepos = array();
10824 protected $packages = array();
10825 protected $packageByName = array();
10826 protected $packageByExactName = array();
10827 protected $acceptableStabilities;
10828 protected $stabilityFlags;
10829 protected $versionParser;
10830 protected $providerCache = array();
10831 protected $filterRequires;
10832 protected $whitelist = null;
10833 protected $id = 1;
10834
10835 public function __construct($minimumStability = 'stable', array $stabilityFlags = array(), array $filterRequires = array())
10836 {
10837 $this->versionParser = new VersionParser;
10838 $this->acceptableStabilities = array();
10839 foreach (BasePackage::$stabilities as $stability => $value) {
10840 if ($value <= BasePackage::$stabilities[$minimumStability]) {
10841 $this->acceptableStabilities[$stability] = $value;
10842 }
10843 }
10844 $this->stabilityFlags = $stabilityFlags;
10845 $this->filterRequires = $filterRequires;
10846 foreach ($filterRequires as $name => $constraint) {
10847 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name)) {
10848 unset($this->filterRequires[$name]);
10849 }
10850 }
10851 }
10852
10853 public function setWhitelist($whitelist)
10854 {
10855 $this->whitelist = $whitelist;
10856 $this->providerCache = array();
10857 }
10858
10859
10860
10861
10862
10863
10864
10865 public function addRepository(RepositoryInterface $repo, $rootAliases = array())
10866 {
10867 if ($repo instanceof CompositeRepository) {
10868 $repos = $repo->getRepositories();
10869 } else {
10870 $repos = array($repo);
10871 }
10872
10873 foreach ($repos as $repo) {
10874 $this->repositories[] = $repo;
10875
10876 $exempt = $repo instanceof PlatformRepository || $repo instanceof InstalledRepositoryInterface;
10877
10878 if ($repo instanceof ComposerRepository && $repo->hasProviders()) {
10879 $this->providerRepos[] = $repo;
10880 $repo->setRootAliases($rootAliases);
10881 $repo->resetPackageIds();
10882 } else {
10883 foreach ($repo->getPackages() as $package) {
10884 $names = $package->getNames();
10885 $stability = $package->getStability();
10886 if ($exempt || $this->isPackageAcceptable($names, $stability)) {
10887 $package->setId($this->id++);
10888 $this->packages[] = $package;
10889 $this->packageByExactName[$package->getName()][$package->id] = $package;
10890
10891 foreach ($names as $provided) {
10892 $this->packageByName[$provided][] = $package;
10893 }
10894
10895
10896  $name = $package->getName();
10897 if (isset($rootAliases[$name][$package->getVersion()])) {
10898 $alias = $rootAliases[$name][$package->getVersion()];
10899 if ($package instanceof AliasPackage) {
10900 $package = $package->getAliasOf();
10901 }
10902 $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
10903 $aliasPackage->setRootPackageAlias(true);
10904 $aliasPackage->setId($this->id++);
10905
10906 $package->getRepository()->addPackage($aliasPackage);
10907 $this->packages[] = $aliasPackage;
10908 $this->packageByExactName[$aliasPackage->getName()][$aliasPackage->id] = $aliasPackage;
10909
10910 foreach ($aliasPackage->getNames() as $name) {
10911 $this->packageByName[$name][] = $aliasPackage;
10912 }
10913 }
10914 }
10915 }
10916 }
10917 }
10918 }
10919
10920 public function getPriority(RepositoryInterface $repo)
10921 {
10922 $priority = array_search($repo, $this->repositories, true);
10923
10924 if (false === $priority) {
10925 throw new \RuntimeException("Could not determine repository priority. The repository was not registered in the pool.");
10926 }
10927
10928 return -$priority;
10929 }
10930
10931
10932
10933
10934
10935
10936
10937 public function packageById($id)
10938 {
10939 return $this->packages[$id - 1];
10940 }
10941
10942
10943
10944
10945 public function count()
10946 {
10947 return count($this->packages);
10948 }
10949
10950
10951
10952
10953
10954
10955
10956
10957
10958
10959
10960
10961 public function whatProvides($name, ConstraintInterface $constraint = null, $mustMatchName = false, $bypassFilters = false)
10962 {
10963 if ($bypassFilters) {
10964 return $this->computeWhatProvides($name, $constraint, $mustMatchName, true);
10965 }
10966
10967 $key = ((int) $mustMatchName).$constraint;
10968 if (isset($this->providerCache[$name][$key])) {
10969 return $this->providerCache[$name][$key];
10970 }
10971
10972 return $this->providerCache[$name][$key] = $this->computeWhatProvides($name, $constraint, $mustMatchName, $bypassFilters);
10973 }
10974
10975
10976
10977
10978 private function computeWhatProvides($name, $constraint, $mustMatchName = false, $bypassFilters = false)
10979 {
10980 $candidates = array();
10981
10982 foreach ($this->providerRepos as $repo) {
10983 foreach ($repo->whatProvides($this, $name, $bypassFilters) as $candidate) {
10984 $candidates[] = $candidate;
10985 if ($candidate->id < 1) {
10986 $candidate->setId($this->id++);
10987 $this->packages[$this->id - 2] = $candidate;
10988 }
10989 }
10990 }
10991
10992 if ($mustMatchName) {
10993 $candidates = array_filter($candidates, function ($candidate) use ($name) {
10994 return $candidate->getName() == $name;
10995 });
10996 if (isset($this->packageByExactName[$name])) {
10997 $candidates = array_merge($candidates, $this->packageByExactName[$name]);
10998 }
10999 } elseif (isset($this->packageByName[$name])) {
11000 $candidates = array_merge($candidates, $this->packageByName[$name]);
11001 }
11002
11003 $matches = $provideMatches = array();
11004 $nameMatch = false;
11005
11006 foreach ($candidates as $candidate) {
11007 $aliasOfCandidate = null;
11008
11009
11010  
11011  if ($candidate instanceof AliasPackage) {
11012 $aliasOfCandidate = $candidate->getAliasOf();
11013 }
11014
11015 if ($this->whitelist !== null && !$bypassFilters && (
11016 (!($candidate instanceof AliasPackage) && !isset($this->whitelist[$candidate->id])) ||
11017 ($candidate instanceof AliasPackage && !isset($this->whitelist[$aliasOfCandidate->id]))
11018 )) {
11019 continue;
11020 }
11021 switch ($this->match($candidate, $name, $constraint, $bypassFilters)) {
11022 case self::MATCH_NONE:
11023 break;
11024
11025 case self::MATCH_NAME:
11026 $nameMatch = true;
11027 break;
11028
11029 case self::MATCH:
11030 $nameMatch = true;
11031 $matches[] = $candidate;
11032 break;
11033
11034 case self::MATCH_PROVIDE:
11035 $provideMatches[] = $candidate;
11036 break;
11037
11038 case self::MATCH_REPLACE:
11039 $matches[] = $candidate;
11040 break;
11041
11042 case self::MATCH_FILTERED:
11043 break;
11044
11045 default:
11046 throw new \UnexpectedValueException('Unexpected match type');
11047 }
11048 }
11049
11050
11051  if ($nameMatch) {
11052 return $matches;
11053 }
11054
11055 return array_merge($matches, $provideMatches);
11056 }
11057
11058 public function literalToPackage($literal)
11059 {
11060 $packageId = abs($literal);
11061
11062 return $this->packageById($packageId);
11063 }
11064
11065 public function literalToPrettyString($literal, $installedMap)
11066 {
11067 $package = $this->literalToPackage($literal);
11068
11069 if (isset($installedMap[$package->id])) {
11070 $prefix = ($literal > 0 ? 'keep' : 'remove');
11071 } else {
11072 $prefix = ($literal > 0 ? 'install' : 'don\'t install');
11073 }
11074
11075 return $prefix.' '.$package->getPrettyString();
11076 }
11077
11078 public function isPackageAcceptable($name, $stability)
11079 {
11080 foreach ((array) $name as $n) {
11081
11082  if (!isset($this->stabilityFlags[$n]) && isset($this->acceptableStabilities[$stability])) {
11083 return true;
11084 }
11085
11086
11087  if (isset($this->stabilityFlags[$n]) && BasePackage::$stabilities[$stability] <= $this->stabilityFlags[$n]) {
11088 return true;
11089 }
11090 }
11091
11092 return false;
11093 }
11094
11095
11096
11097
11098
11099
11100
11101
11102
11103
11104 private function match($candidate, $name, ConstraintInterface $constraint = null, $bypassFilters)
11105 {
11106 $candidateName = $candidate->getName();
11107 $candidateVersion = $candidate->getVersion();
11108 $isDev = $candidate->getStability() === 'dev';
11109 $isAlias = $candidate instanceof AliasPackage;
11110
11111 if (!$bypassFilters && !$isDev && !$isAlias && isset($this->filterRequires[$name])) {
11112 $requireFilter = $this->filterRequires[$name];
11113 } else {
11114 $requireFilter = new EmptyConstraint;
11115 }
11116
11117 if ($candidateName === $name) {
11118 $pkgConstraint = new Constraint('==', $candidateVersion);
11119
11120 if ($constraint === null || $constraint->matches($pkgConstraint)) {
11121 return $requireFilter->matches($pkgConstraint) ? self::MATCH : self::MATCH_FILTERED;
11122 }
11123
11124 return self::MATCH_NAME;
11125 }
11126
11127 $provides = $candidate->getProvides();
11128 $replaces = $candidate->getReplaces();
11129
11130
11131  if (isset($replaces[0]) || isset($provides[0])) {
11132 foreach ($provides as $link) {
11133 if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
11134 return $requireFilter->matches($link->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
11135 }
11136 }
11137
11138 foreach ($replaces as $link) {
11139 if ($link->getTarget() === $name && ($constraint === null || $constraint->matches($link->getConstraint()))) {
11140 return $requireFilter->matches($link->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
11141 }
11142 }
11143
11144 return self::MATCH_NONE;
11145 }
11146
11147 if (isset($provides[$name]) && ($constraint === null || $constraint->matches($provides[$name]->getConstraint()))) {
11148 return $requireFilter->matches($provides[$name]->getConstraint()) ? self::MATCH_PROVIDE : self::MATCH_FILTERED;
11149 }
11150
11151 if (isset($replaces[$name]) && ($constraint === null || $constraint->matches($replaces[$name]->getConstraint()))) {
11152 return $requireFilter->matches($replaces[$name]->getConstraint()) ? self::MATCH_REPLACE : self::MATCH_FILTERED;
11153 }
11154
11155 return self::MATCH_NONE;
11156 }
11157 }
11158 <?php
11159
11160
11161
11162
11163
11164
11165
11166
11167
11168
11169
11170 namespace Composer\DependencyResolver;
11171
11172
11173
11174
11175
11176
11177 class Problem
11178 {
11179
11180
11181
11182
11183 protected $reasonSeen;
11184
11185
11186
11187
11188
11189 protected $reasons = array();
11190
11191 protected $section = 0;
11192
11193 protected $pool;
11194
11195 public function __construct(Pool $pool)
11196 {
11197 $this->pool = $pool;
11198 }
11199
11200
11201
11202
11203
11204
11205 public function addRule(Rule $rule)
11206 {
11207 $this->addReason(spl_object_hash($rule), array(
11208 'rule' => $rule,
11209 'job' => $rule->getJob(),
11210 ));
11211 }
11212
11213
11214
11215
11216
11217
11218 public function getReasons()
11219 {
11220 return $this->reasons;
11221 }
11222
11223
11224
11225
11226
11227
11228
11229 public function getPrettyString(array $installedMap = array())
11230 {
11231 $reasons = call_user_func_array('array_merge', array_reverse($this->reasons));
11232
11233 if (count($reasons) === 1) {
11234 reset($reasons);
11235 $reason = current($reasons);
11236
11237 $rule = $reason['rule'];
11238 $job = $reason['job'];
11239
11240 if (isset($job['constraint'])) {
11241 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
11242 } else {
11243 $packages = array();
11244 }
11245
11246 if ($job && $job['cmd'] === 'install' && empty($packages)) {
11247
11248
11249  if ($job['packageName'] === 'php' || $job['packageName'] === 'php-64bit' || $job['packageName'] === 'hhvm') {
11250 $available = $this->pool->whatProvides($job['packageName']);
11251 $version = count($available) ? $available[0]->getPrettyVersion() : phpversion();
11252
11253 $msg = "\n    - This package requires ".$job['packageName'].$this->constraintToText($job['constraint']).' but ';
11254
11255 if (defined('HHVM_VERSION')) {
11256 return $msg . 'your HHVM version does not satisfy that requirement.';
11257 }
11258
11259 if ($job['packageName'] === 'hhvm') {
11260 return $msg . 'you are running this with PHP and not HHVM.';
11261 }
11262
11263 return $msg . 'your PHP version ('. $version .') does not satisfy that requirement.';
11264 }
11265
11266
11267  if (0 === stripos($job['packageName'], 'ext-')) {
11268 $ext = substr($job['packageName'], 4);
11269 $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
11270
11271 return "\n    - The requested PHP extension ".$job['packageName'].$this->constraintToText($job['constraint']).' '.$error.'. Install or enable PHP\'s '.$ext.' extension.';
11272 }
11273
11274
11275  if (0 === stripos($job['packageName'], 'lib-')) {
11276 if (strtolower($job['packageName']) === 'lib-icu') {
11277 $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.';
11278
11279 return "\n    - The requested linked library ".$job['packageName'].$this->constraintToText($job['constraint']).' '.$error;
11280 }
11281
11282 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.';
11283 }
11284
11285 if (!preg_match('{^[A-Za-z0-9_./-]+$}', $job['packageName'])) {
11286 $illegalChars = preg_replace('{[A-Za-z0-9_./-]+}', '', $job['packageName']);
11287
11288 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.';
11289 }
11290
11291 if ($providers = $this->pool->whatProvides($job['packageName'], $job['constraint'], true, true)) {
11292 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.';
11293 }
11294
11295 if ($providers = $this->pool->whatProvides($job['packageName'], null, true, true)) {
11296 return "\n    - The requested package ".$job['packageName'].$this->constraintToText($job['constraint']).' exists as '.$this->getPackageList($providers).' but these are rejected by your constraint.';
11297 }
11298
11299 return "\n    - The requested package ".$job['packageName'].' could not be found in any version, there may be a typo in the package name.';
11300 }
11301 }
11302
11303 $messages = array();
11304
11305 foreach ($reasons as $reason) {
11306 $rule = $reason['rule'];
11307 $job = $reason['job'];
11308
11309 if ($job) {
11310 $messages[] = $this->jobToText($job);
11311 } elseif ($rule) {
11312 if ($rule instanceof Rule) {
11313 $messages[] = $rule->getPrettyString($this->pool, $installedMap);
11314 }
11315 }
11316 }
11317
11318 return "\n    - ".implode("\n    - ", $messages);
11319 }
11320
11321
11322
11323
11324
11325
11326
11327 protected function addReason($id, $reason)
11328 {
11329 if (!isset($this->reasonSeen[$id])) {
11330 $this->reasonSeen[$id] = true;
11331 $this->reasons[$this->section][] = $reason;
11332 }
11333 }
11334
11335 public function nextSection()
11336 {
11337 $this->section++;
11338 }
11339
11340
11341
11342
11343
11344
11345
11346 protected function jobToText($job)
11347 {
11348 switch ($job['cmd']) {
11349 case 'install':
11350 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
11351 if (!$packages) {
11352 return 'No package found to satisfy install request for '.$job['packageName'].$this->constraintToText($job['constraint']);
11353 }
11354
11355 return 'Installation request for '.$job['packageName'].$this->constraintToText($job['constraint']).' -> satisfiable by '.$this->getPackageList($packages).'.';
11356 case 'update':
11357 return 'Update request for '.$job['packageName'].$this->constraintToText($job['constraint']).'.';
11358 case 'remove':
11359 return 'Removal request for '.$job['packageName'].$this->constraintToText($job['constraint']).'';
11360 }
11361
11362 if (isset($job['constraint'])) {
11363 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
11364 } else {
11365 $packages = array();
11366 }
11367
11368 return 'Job(cmd='.$job['cmd'].', target='.$job['packageName'].', packages=['.$this->getPackageList($packages).'])';
11369 }
11370
11371 protected function getPackageList($packages)
11372 {
11373 $prepared = array();
11374 foreach ($packages as $package) {
11375 $prepared[$package->getName()]['name'] = $package->getPrettyName();
11376 $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
11377 }
11378 foreach ($prepared as $name => $package) {
11379 $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
11380 }
11381
11382 return implode(', ', $prepared);
11383 }
11384
11385
11386
11387
11388
11389
11390
11391 protected function constraintToText($constraint)
11392 {
11393 return ($constraint) ? ' '.$constraint->getPrettyString() : '';
11394 }
11395 }
11396 <?php
11397
11398
11399
11400
11401
11402
11403
11404
11405
11406
11407
11408 namespace Composer\DependencyResolver;
11409
11410 use Composer\Semver\Constraint\ConstraintInterface;
11411
11412
11413
11414
11415 class Request
11416 {
11417 protected $jobs;
11418
11419 public function __construct()
11420 {
11421 $this->jobs = array();
11422 }
11423
11424 public function install($packageName, ConstraintInterface $constraint = null)
11425 {
11426 $this->addJob($packageName, 'install', $constraint);
11427 }
11428
11429 public function update($packageName, ConstraintInterface $constraint = null)
11430 {
11431 $this->addJob($packageName, 'update', $constraint);
11432 }
11433
11434 public function remove($packageName, ConstraintInterface $constraint = null)
11435 {
11436 $this->addJob($packageName, 'remove', $constraint);
11437 }
11438
11439
11440
11441
11442
11443
11444
11445
11446
11447 public function fix($packageName, ConstraintInterface $constraint = null)
11448 {
11449 $this->addJob($packageName, 'install', $constraint, true);
11450 }
11451
11452 protected function addJob($packageName, $cmd, ConstraintInterface $constraint = null, $fixed = false)
11453 {
11454 $packageName = strtolower($packageName);
11455
11456 $this->jobs[] = array(
11457 'cmd' => $cmd,
11458 'packageName' => $packageName,
11459 'constraint' => $constraint,
11460 'fixed' => $fixed,
11461 );
11462 }
11463
11464 public function updateAll()
11465 {
11466 $this->jobs[] = array('cmd' => 'update-all');
11467 }
11468
11469 public function getJobs()
11470 {
11471 return $this->jobs;
11472 }
11473 }
11474 <?php
11475
11476
11477
11478
11479
11480
11481
11482
11483
11484
11485
11486 namespace Composer\DependencyResolver;
11487
11488 use Composer\Package\CompletePackage;
11489 use Composer\Package\Link;
11490 use Composer\Package\PackageInterface;
11491
11492
11493
11494
11495
11496 abstract class Rule
11497 {
11498
11499  const RULE_INTERNAL_ALLOW_UPDATE = 1;
11500 const RULE_JOB_INSTALL = 2;
11501 const RULE_JOB_REMOVE = 3;
11502 const RULE_PACKAGE_CONFLICT = 6;
11503 const RULE_PACKAGE_REQUIRES = 7;
11504 const RULE_PACKAGE_OBSOLETES = 8;
11505 const RULE_INSTALLED_PACKAGE_OBSOLETES = 9;
11506 const RULE_PACKAGE_SAME_NAME = 10;
11507 const RULE_PACKAGE_IMPLICIT_OBSOLETES = 11;
11508 const RULE_LEARNED = 12;
11509 const RULE_PACKAGE_ALIAS = 13;
11510
11511
11512  const BITFIELD_TYPE = 0;
11513 const BITFIELD_REASON = 8;
11514 const BITFIELD_DISABLED = 16;
11515
11516 protected $bitfield;
11517 protected $reasonData;
11518
11519
11520
11521
11522
11523
11524 public function __construct($reason, $reasonData, $job = null)
11525 {
11526 $this->reasonData = $reasonData;
11527
11528 if ($job) {
11529 $this->job = $job;
11530 }
11531
11532 $this->bitfield = (0 << self::BITFIELD_DISABLED) |
11533 ($reason << self::BITFIELD_REASON) |
11534 (255 << self::BITFIELD_TYPE);
11535 }
11536
11537 abstract public function getLiterals();
11538
11539 abstract public function getHash();
11540
11541 public function getJob()
11542 {
11543 return isset($this->job) ? $this->job : null;
11544 }
11545
11546 abstract public function equals(Rule $rule);
11547
11548 public function getReason()
11549 {
11550 return ($this->bitfield & (255 << self::BITFIELD_REASON)) >> self::BITFIELD_REASON;
11551 }
11552
11553 public function getReasonData()
11554 {
11555 return $this->reasonData;
11556 }
11557
11558 public function getRequiredPackage()
11559 {
11560 if ($this->getReason() === self::RULE_JOB_INSTALL) {
11561 return $this->reasonData;
11562 }
11563
11564 if ($this->getReason() === self::RULE_PACKAGE_REQUIRES) {
11565 return $this->reasonData->getTarget();
11566 }
11567 }
11568
11569 public function setType($type)
11570 {
11571 $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_TYPE)) | ((255 & $type) << self::BITFIELD_TYPE);
11572 }
11573
11574 public function getType()
11575 {
11576 return ($this->bitfield & (255 << self::BITFIELD_TYPE)) >> self::BITFIELD_TYPE;
11577 }
11578
11579 public function disable()
11580 {
11581 $this->bitfield = ($this->bitfield & ~(255 << self::BITFIELD_DISABLED)) | (1 << self::BITFIELD_DISABLED);
11582 }
11583
11584 public function enable()
11585 {
11586 $this->bitfield = $this->bitfield & ~(255 << self::BITFIELD_DISABLED);
11587 }
11588
11589 public function isDisabled()
11590 {
11591 return (bool) (($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
11592 }
11593
11594 public function isEnabled()
11595 {
11596 return !(($this->bitfield & (255 << self::BITFIELD_DISABLED)) >> self::BITFIELD_DISABLED);
11597 }
11598
11599 abstract public function isAssertion();
11600
11601 public function getPrettyString(Pool $pool, array $installedMap = array())
11602 {
11603 $literals = $this->getLiterals();
11604
11605 $ruleText = '';
11606 foreach ($literals as $i => $literal) {
11607 if ($i != 0) {
11608 $ruleText .= '|';
11609 }
11610 $ruleText .= $pool->literalToPrettyString($literal, $installedMap);
11611 }
11612
11613 switch ($this->getReason()) {
11614 case self::RULE_INTERNAL_ALLOW_UPDATE:
11615 return $ruleText;
11616
11617 case self::RULE_JOB_INSTALL:
11618 return "Install command rule ($ruleText)";
11619
11620 case self::RULE_JOB_REMOVE:
11621 return "Remove command rule ($ruleText)";
11622
11623 case self::RULE_PACKAGE_CONFLICT:
11624 $package1 = $pool->literalToPackage($literals[0]);
11625 $package2 = $pool->literalToPackage($literals[1]);
11626
11627 return $package1->getPrettyString().' conflicts with '.$this->formatPackagesUnique($pool, array($package2)).'.';
11628
11629 case self::RULE_PACKAGE_REQUIRES:
11630 $sourceLiteral = array_shift($literals);
11631 $sourcePackage = $pool->literalToPackage($sourceLiteral);
11632
11633 $requires = array();
11634 foreach ($literals as $literal) {
11635 $requires[] = $pool->literalToPackage($literal);
11636 }
11637
11638 $text = $this->reasonData->getPrettyString($sourcePackage);
11639 if ($requires) {
11640 $text .= ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $requires) . '.';
11641 } else {
11642 $targetName = $this->reasonData->getTarget();
11643
11644 if ($targetName === 'php' || $targetName === 'php-64bit' || $targetName === 'hhvm') {
11645
11646  if (defined('HHVM_VERSION')) {
11647 return $text . ' -> your HHVM version does not satisfy that requirement.';
11648 }
11649
11650 if ($targetName === 'hhvm') {
11651 return $text . ' -> you are running this with PHP and not HHVM.';
11652 }
11653
11654 $packages = $pool->whatProvides($targetName);
11655 $package = count($packages) ? current($packages) : phpversion();
11656
11657 if (!($package instanceof CompletePackage)) {
11658 return $text . ' -> your PHP version ('.phpversion().') does not satisfy that requirement.';
11659 }
11660
11661 $extra = $package->getExtra();
11662
11663 if (!empty($extra['config.platform'])) {
11664 $text .= ' -> your PHP version ('.phpversion().') overridden by "config.platform.php" version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
11665 } else {
11666 $text .= ' -> your PHP version ('.$package->getPrettyVersion().') does not satisfy that requirement.';
11667 }
11668
11669 return $text;
11670 }
11671
11672 if (0 === strpos($targetName, 'ext-')) {
11673
11674  $ext = substr($targetName, 4);
11675 $error = extension_loaded($ext) ? 'has the wrong version ('.(phpversion($ext) ?: '0').') installed' : 'is missing from your system';
11676
11677 return $text . ' -> the requested PHP extension '.$ext.' '.$error.'.';
11678 }
11679
11680 if (0 === strpos($targetName, 'lib-')) {
11681
11682  $lib = substr($targetName, 4);
11683
11684 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.';
11685 }
11686
11687 if ($providers = $pool->whatProvides($targetName, $this->reasonData->getConstraint(), true, true)) {
11688 return $text . ' -> satisfiable by ' . $this->formatPackagesUnique($pool, $providers) .' but these conflict with your requirements or minimum-stability.';
11689 }
11690
11691 return $text . ' -> no matching package found.';
11692 }
11693
11694 return $text;
11695
11696 case self::RULE_PACKAGE_OBSOLETES:
11697 return $ruleText;
11698 case self::RULE_INSTALLED_PACKAGE_OBSOLETES:
11699 return $ruleText;
11700 case self::RULE_PACKAGE_SAME_NAME:
11701 return 'Can only install one of: ' . $this->formatPackagesUnique($pool, $literals) . '.';
11702 case self::RULE_PACKAGE_IMPLICIT_OBSOLETES:
11703 return $ruleText;
11704 case self::RULE_LEARNED:
11705 return 'Conclusion: '.$ruleText;
11706 case self::RULE_PACKAGE_ALIAS:
11707 return $ruleText;
11708 default:
11709 return '('.$ruleText.')';
11710 }
11711 }
11712
11713
11714
11715
11716
11717
11718
11719 protected function formatPackagesUnique($pool, array $packages)
11720 {
11721 $prepared = array();
11722 foreach ($packages as $package) {
11723 if (!is_object($package)) {
11724 $package = $pool->literalToPackage($package);
11725 }
11726 $prepared[$package->getName()]['name'] = $package->getPrettyName();
11727 $prepared[$package->getName()]['versions'][$package->getVersion()] = $package->getPrettyVersion();
11728 }
11729 foreach ($prepared as $name => $package) {
11730 $prepared[$name] = $package['name'].'['.implode(', ', $package['versions']).']';
11731 }
11732
11733 return implode(', ', $prepared);
11734 }
11735 }
11736 <?php
11737
11738
11739
11740
11741
11742
11743
11744
11745
11746
11747
11748 namespace Composer\DependencyResolver;
11749
11750 use Composer\Package\PackageInterface;
11751 use Composer\Package\Link;
11752
11753
11754
11755
11756 class Rule2Literals extends Rule
11757 {
11758 protected $literal1;
11759 protected $literal2;
11760
11761
11762
11763
11764
11765
11766
11767
11768 public function __construct($literal1, $literal2, $reason, $reasonData, $job = null)
11769 {
11770 parent::__construct($reason, $reasonData, $job);
11771
11772 if ($literal1 < $literal2) {
11773 $this->literal1 = $literal1;
11774 $this->literal2 = $literal2;
11775 } else {
11776 $this->literal1 = $literal2;
11777 $this->literal2 = $literal1;
11778 }
11779 }
11780
11781 public function getLiterals()
11782 {
11783 return array($this->literal1, $this->literal2);
11784 }
11785
11786 public function getHash()
11787 {
11788 $data = unpack('ihash', md5($this->literal1.','.$this->literal2, true));
11789
11790 return $data['hash'];
11791 }
11792
11793
11794
11795
11796
11797
11798
11799
11800
11801 public function equals(Rule $rule)
11802 {
11803 $literals = $rule->getLiterals();
11804 if (2 != count($literals)) {
11805 return false;
11806 }
11807
11808 if ($this->literal1 !== $literals[0]) {
11809 return false;
11810 }
11811
11812 if ($this->literal2 !== $literals[1]) {
11813 return false;
11814 }
11815
11816 return true;
11817 }
11818
11819 public function isAssertion()
11820 {
11821 return false;
11822 }
11823
11824
11825
11826
11827
11828
11829 public function __toString()
11830 {
11831 $result = ($this->isDisabled()) ? 'disabled(' : '(';
11832
11833 $result .= $this->literal1 . '|' . $this->literal2 . ')';
11834
11835 return $result;
11836 }
11837 }
11838 <?php
11839
11840
11841
11842
11843
11844
11845
11846
11847
11848
11849
11850 namespace Composer\DependencyResolver;
11851
11852
11853
11854
11855 class RuleSet implements \IteratorAggregate, \Countable
11856 {
11857
11858  const TYPE_PACKAGE = 0;
11859 const TYPE_JOB = 1;
11860 const TYPE_LEARNED = 4;
11861
11862
11863
11864
11865
11866
11867 public $ruleById;
11868
11869 protected static $types = array(
11870 255 => 'UNKNOWN',
11871 self::TYPE_PACKAGE => 'PACKAGE',
11872 self::TYPE_JOB => 'JOB',
11873 self::TYPE_LEARNED => 'LEARNED',
11874 );
11875
11876 protected $rules;
11877 protected $nextRuleId;
11878
11879 protected $rulesByHash;
11880
11881 public function __construct()
11882 {
11883 $this->nextRuleId = 0;
11884
11885 foreach ($this->getTypes() as $type) {
11886 $this->rules[$type] = array();
11887 }
11888
11889 $this->rulesByHash = array();
11890 }
11891
11892 public function add(Rule $rule, $type)
11893 {
11894 if (!isset(self::$types[$type])) {
11895 throw new \OutOfBoundsException('Unknown rule type: ' . $type);
11896 }
11897
11898 $hash = $rule->getHash();
11899
11900
11901  if (isset($this->rulesByHash[$hash])) {
11902 $potentialDuplicates = $this->rulesByHash[$hash];
11903 if (is_array($potentialDuplicates)) {
11904 foreach ($potentialDuplicates as $potentialDuplicate) {
11905 if ($rule->equals($potentialDuplicate)) {
11906 return;
11907 }
11908 }
11909 } else {
11910 if ($rule->equals($potentialDuplicates)) {
11911 return;
11912 }
11913 }
11914 }
11915
11916 if (!isset($this->rules[$type])) {
11917 $this->rules[$type] = array();
11918 }
11919
11920 $this->rules[$type][] = $rule;
11921 $this->ruleById[$this->nextRuleId] = $rule;
11922 $rule->setType($type);
11923
11924 $this->nextRuleId++;
11925
11926 if (!isset($this->rulesByHash[$hash])) {
11927 $this->rulesByHash[$hash] = $rule;
11928 } elseif (is_array($this->rulesByHash[$hash])) {
11929 $this->rulesByHash[$hash][] = $rule;
11930 } else {
11931 $originalRule = $this->rulesByHash[$hash];
11932 $this->rulesByHash[$hash] = array($originalRule, $rule);
11933 }
11934 }
11935
11936 public function count()
11937 {
11938 return $this->nextRuleId;
11939 }
11940
11941 public function ruleById($id)
11942 {
11943 return $this->ruleById[$id];
11944 }
11945
11946 public function getRules()
11947 {
11948 return $this->rules;
11949 }
11950
11951 public function getIterator()
11952 {
11953 return new RuleSetIterator($this->getRules());
11954 }
11955
11956 public function getIteratorFor($types)
11957 {
11958 if (!is_array($types)) {
11959 $types = array($types);
11960 }
11961
11962 $allRules = $this->getRules();
11963 $rules = array();
11964
11965 foreach ($types as $type) {
11966 $rules[$type] = $allRules[$type];
11967 }
11968
11969 return new RuleSetIterator($rules);
11970 }
11971
11972 public function getIteratorWithout($types)
11973 {
11974 if (!is_array($types)) {
11975 $types = array($types);
11976 }
11977
11978 $rules = $this->getRules();
11979
11980 foreach ($types as $type) {
11981 unset($rules[$type]);
11982 }
11983
11984 return new RuleSetIterator($rules);
11985 }
11986
11987 public function getTypes()
11988 {
11989 $types = self::$types;
11990 unset($types[255]);
11991
11992 return array_keys($types);
11993 }
11994
11995 public function getPrettyString(Pool $pool = null)
11996 {
11997 $string = "\n";
11998 foreach ($this->rules as $type => $rules) {
11999 $string .= str_pad(self::$types[$type], 8, ' ') . ": ";
12000 foreach ($rules as $rule) {
12001 $string .= ($pool ? $rule->getPrettyString($pool) : $rule)."\n";
12002 }
12003 $string .= "\n\n";
12004 }
12005
12006 return $string;
12007 }
12008
12009 public function __toString()
12010 {
12011 return $this->getPrettyString(null);
12012 }
12013 }
12014 <?php
12015
12016
12017
12018
12019
12020
12021
12022
12023
12024
12025
12026 namespace Composer\DependencyResolver;
12027
12028 use Composer\Package\PackageInterface;
12029 use Composer\Package\AliasPackage;
12030 use Composer\Repository\PlatformRepository;
12031
12032
12033
12034
12035 class RuleSetGenerator
12036 {
12037 protected $policy;
12038 protected $pool;
12039 protected $rules;
12040 protected $jobs;
12041 protected $installedMap;
12042 protected $whitelistedMap;
12043 protected $addedMap;
12044
12045 public function __construct(PolicyInterface $policy, Pool $pool)
12046 {
12047 $this->policy = $policy;
12048 $this->pool = $pool;
12049 }
12050
12051
12052
12053
12054
12055
12056
12057
12058
12059
12060
12061
12062
12063
12064
12065 protected function createRequireRule(PackageInterface $package, array $providers, $reason, $reasonData = null)
12066 {
12067 $literals = array(-$package->id);
12068
12069 foreach ($providers as $provider) {
12070
12071  if ($provider === $package) {
12072 return null;
12073 }
12074 $literals[] = $provider->id;
12075 }
12076
12077 return new GenericRule($literals, $reason, $reasonData);
12078 }
12079
12080
12081
12082
12083
12084
12085
12086
12087
12088
12089
12090
12091
12092 protected function createInstallOneOfRule(array $packages, $reason, $job)
12093 {
12094 $literals = array();
12095 foreach ($packages as $package) {
12096 $literals[] = $package->id;
12097 }
12098
12099 return new GenericRule($literals, $reason, $job['packageName'], $job);
12100 }
12101
12102
12103
12104
12105
12106
12107
12108
12109
12110
12111
12112
12113 protected function createRemoveRule(PackageInterface $package, $reason, $job)
12114 {
12115 return new GenericRule(array(-$package->id), $reason, $job['packageName'], $job);
12116 }
12117
12118
12119
12120
12121
12122
12123
12124
12125
12126
12127
12128
12129
12130
12131
12132 protected function createRule2Literals(PackageInterface $issuer, PackageInterface $provider, $reason, $reasonData = null)
12133 {
12134
12135  if ($issuer === $provider) {
12136 return null;
12137 }
12138
12139 return new Rule2Literals(-$issuer->id, -$provider->id, $reason, $reasonData);
12140 }
12141
12142
12143
12144
12145
12146
12147
12148
12149
12150
12151 private function addRule($type, Rule $newRule = null)
12152 {
12153 if (!$newRule) {
12154 return;
12155 }
12156
12157 $this->rules->add($newRule, $type);
12158 }
12159
12160 protected function whitelistFromPackage(PackageInterface $package)
12161 {
12162 $workQueue = new \SplQueue;
12163 $workQueue->enqueue($package);
12164
12165 while (!$workQueue->isEmpty()) {
12166 $package = $workQueue->dequeue();
12167 if (isset($this->whitelistedMap[$package->id])) {
12168 continue;
12169 }
12170
12171 $this->whitelistedMap[$package->id] = true;
12172
12173 foreach ($package->getRequires() as $link) {
12174 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint(), true);
12175
12176 foreach ($possibleRequires as $require) {
12177 $workQueue->enqueue($require);
12178 }
12179 }
12180
12181 $obsoleteProviders = $this->pool->whatProvides($package->getName(), null, true);
12182
12183 foreach ($obsoleteProviders as $provider) {
12184 if ($provider === $package) {
12185 continue;
12186 }
12187
12188 if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
12189 $workQueue->enqueue($provider);
12190 }
12191 }
12192 }
12193 }
12194
12195 protected function addRulesForPackage(PackageInterface $package, $ignorePlatformReqs)
12196 {
12197 $workQueue = new \SplQueue;
12198 $workQueue->enqueue($package);
12199
12200 while (!$workQueue->isEmpty()) {
12201 $package = $workQueue->dequeue();
12202 if (isset($this->addedMap[$package->id])) {
12203 continue;
12204 }
12205
12206 $this->addedMap[$package->id] = true;
12207
12208 foreach ($package->getRequires() as $link) {
12209 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
12210 continue;
12211 }
12212
12213 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
12214
12215 $this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createRequireRule($package, $possibleRequires, Rule::RULE_PACKAGE_REQUIRES, $link));
12216
12217 foreach ($possibleRequires as $require) {
12218 $workQueue->enqueue($require);
12219 }
12220 }
12221
12222 foreach ($package->getConflicts() as $link) {
12223 $possibleConflicts = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
12224
12225 foreach ($possibleConflicts as $conflict) {
12226 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $conflict, Rule::RULE_PACKAGE_CONFLICT, $link));
12227 }
12228 }
12229
12230
12231  $isInstalled = (isset($this->installedMap[$package->id]));
12232
12233 foreach ($package->getReplaces() as $link) {
12234 $obsoleteProviders = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
12235
12236 foreach ($obsoleteProviders as $provider) {
12237 if ($provider === $package) {
12238 continue;
12239 }
12240
12241 if (!$this->obsoleteImpossibleForAlias($package, $provider)) {
12242 $reason = ($isInstalled) ? Rule::RULE_INSTALLED_PACKAGE_OBSOLETES : Rule::RULE_PACKAGE_OBSOLETES;
12243 $this->addRule(RuleSet::TYPE_PACKAGE, $this->createRule2Literals($package, $provider, $reason, $link));
12244 }
12245 }
12246 }
12247
12248 $obsoleteProviders = $this->pool->whatProvides($package->getName(), null);
12249
12250 foreach ($obsoleteProviders as $provider) {
12251 if ($provider === $package) {
12252 continue;
12253 }
12254
12255 if (($package instanceof AliasPackage) && $package->getAliasOf() === $provider) {
12256 $this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createRequireRule($package, array($provider), Rule::RULE_PACKAGE_ALIAS, $package));
12257 } elseif (!$this->obsoleteImpossibleForAlias($package, $provider)) {
12258 $reason = ($package->getName() == $provider->getName()) ? Rule::RULE_PACKAGE_SAME_NAME : Rule::RULE_PACKAGE_IMPLICIT_OBSOLETES;
12259 $this->addRule(RuleSet::TYPE_PACKAGE, $rule = $this->createRule2Literals($package, $provider, $reason, $package));
12260 }
12261 }
12262 }
12263 }
12264
12265 protected function obsoleteImpossibleForAlias($package, $provider)
12266 {
12267 $packageIsAlias = $package instanceof AliasPackage;
12268 $providerIsAlias = $provider instanceof AliasPackage;
12269
12270 $impossible = (
12271 ($packageIsAlias && $package->getAliasOf() === $provider) ||
12272 ($providerIsAlias && $provider->getAliasOf() === $package) ||
12273 ($packageIsAlias && $providerIsAlias && $provider->getAliasOf() === $package->getAliasOf())
12274 );
12275
12276 return $impossible;
12277 }
12278
12279 protected function whitelistFromJobs()
12280 {
12281 foreach ($this->jobs as $job) {
12282 switch ($job['cmd']) {
12283 case 'install':
12284 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint'], true);
12285 foreach ($packages as $package) {
12286 $this->whitelistFromPackage($package);
12287 }
12288 break;
12289 }
12290 }
12291 }
12292
12293 protected function addRulesForJobs($ignorePlatformReqs)
12294 {
12295 foreach ($this->jobs as $job) {
12296 switch ($job['cmd']) {
12297 case 'install':
12298 if (!$job['fixed'] && $ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
12299 continue;
12300 }
12301
12302 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
12303 if ($packages) {
12304 foreach ($packages as $package) {
12305 if (!isset($this->installedMap[$package->id])) {
12306 $this->addRulesForPackage($package, $ignorePlatformReqs);
12307 }
12308 }
12309
12310 $rule = $this->createInstallOneOfRule($packages, Rule::RULE_JOB_INSTALL, $job);
12311 $this->addRule(RuleSet::TYPE_JOB, $rule);
12312 }
12313 break;
12314 case 'remove':
12315
12316  
12317  $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
12318 foreach ($packages as $package) {
12319 $rule = $this->createRemoveRule($package, Rule::RULE_JOB_REMOVE, $job);
12320 $this->addRule(RuleSet::TYPE_JOB, $rule);
12321 }
12322 break;
12323 }
12324 }
12325 }
12326
12327 public function getRulesFor($jobs, $installedMap, $ignorePlatformReqs = false)
12328 {
12329 $this->jobs = $jobs;
12330 $this->rules = new RuleSet;
12331 $this->installedMap = $installedMap;
12332
12333 $this->whitelistedMap = array();
12334 foreach ($this->installedMap as $package) {
12335 $this->whitelistFromPackage($package);
12336 }
12337 $this->whitelistFromJobs();
12338
12339 $this->pool->setWhitelist($this->whitelistedMap);
12340
12341 $this->addedMap = array();
12342 foreach ($this->installedMap as $package) {
12343 $this->addRulesForPackage($package, $ignorePlatformReqs);
12344 }
12345
12346 $this->addRulesForJobs($ignorePlatformReqs);
12347
12348 return $this->rules;
12349 }
12350 }
12351 <?php
12352
12353
12354
12355
12356
12357
12358
12359
12360
12361
12362
12363 namespace Composer\DependencyResolver;
12364
12365
12366
12367
12368 class RuleSetIterator implements \Iterator
12369 {
12370 protected $rules;
12371 protected $types;
12372
12373 protected $currentOffset;
12374 protected $currentType;
12375 protected $currentTypeOffset;
12376
12377 public function __construct(array $rules)
12378 {
12379 $this->rules = $rules;
12380 $this->types = array_keys($rules);
12381 sort($this->types);
12382
12383 $this->rewind();
12384 }
12385
12386 public function current()
12387 {
12388 return $this->rules[$this->currentType][$this->currentOffset];
12389 }
12390
12391 public function key()
12392 {
12393 return $this->currentType;
12394 }
12395
12396 public function next()
12397 {
12398 $this->currentOffset++;
12399
12400 if (!isset($this->rules[$this->currentType])) {
12401 return;
12402 }
12403
12404 if ($this->currentOffset >= sizeof($this->rules[$this->currentType])) {
12405 $this->currentOffset = 0;
12406
12407 do {
12408 $this->currentTypeOffset++;
12409
12410 if (!isset($this->types[$this->currentTypeOffset])) {
12411 $this->currentType = -1;
12412 break;
12413 }
12414
12415 $this->currentType = $this->types[$this->currentTypeOffset];
12416 } while (isset($this->types[$this->currentTypeOffset]) && !sizeof($this->rules[$this->currentType]));
12417 }
12418 }
12419
12420 public function rewind()
12421 {
12422 $this->currentOffset = 0;
12423
12424 $this->currentTypeOffset = -1;
12425 $this->currentType = -1;
12426
12427 do {
12428 $this->currentTypeOffset++;
12429
12430 if (!isset($this->types[$this->currentTypeOffset])) {
12431 $this->currentType = -1;
12432 break;
12433 }
12434
12435 $this->currentType = $this->types[$this->currentTypeOffset];
12436 } while (isset($this->types[$this->currentTypeOffset]) && !sizeof($this->rules[$this->currentType]));
12437 }
12438
12439 public function valid()
12440 {
12441 return isset($this->rules[$this->currentType])
12442 && isset($this->rules[$this->currentType][$this->currentOffset]);
12443 }
12444 }
12445 <?php
12446
12447
12448
12449
12450
12451
12452
12453
12454
12455
12456
12457 namespace Composer\DependencyResolver;
12458
12459
12460
12461
12462
12463
12464
12465
12466
12467 class RuleWatchChain extends \SplDoublyLinkedList
12468 {
12469 protected $offset = 0;
12470
12471
12472
12473
12474
12475
12476 public function seek($offset)
12477 {
12478 $this->rewind();
12479 for ($i = 0; $i < $offset; $i++, $this->next());
12480 }
12481
12482
12483
12484
12485
12486
12487
12488
12489
12490 public function remove()
12491 {
12492 $offset = $this->key();
12493 $this->offsetUnset($offset);
12494 $this->seek($offset);
12495 }
12496 }
12497 <?php
12498
12499
12500
12501
12502
12503
12504
12505
12506
12507
12508
12509 namespace Composer\DependencyResolver;
12510
12511
12512
12513
12514
12515
12516
12517
12518
12519
12520
12521 class RuleWatchGraph
12522 {
12523 protected $watchChains = array();
12524
12525
12526
12527
12528
12529
12530
12531
12532
12533
12534
12535
12536
12537 public function insert(RuleWatchNode $node)
12538 {
12539 if ($node->getRule()->isAssertion()) {
12540 return;
12541 }
12542
12543 foreach (array($node->watch1, $node->watch2) as $literal) {
12544 if (!isset($this->watchChains[$literal])) {
12545 $this->watchChains[$literal] = new RuleWatchChain;
12546 }
12547
12548 $this->watchChains[$literal]->unshift($node);
12549 }
12550 }
12551
12552
12553
12554
12555
12556
12557
12558
12559
12560
12561
12562
12563
12564
12565
12566
12567
12568
12569
12570
12571
12572
12573
12574
12575 public function propagateLiteral($decidedLiteral, $level, $decisions)
12576 {
12577
12578  
12579  
12580  $literal = -$decidedLiteral;
12581
12582 if (!isset($this->watchChains[$literal])) {
12583 return null;
12584 }
12585
12586 $chain = $this->watchChains[$literal];
12587
12588 $chain->rewind();
12589 while ($chain->valid()) {
12590 $node = $chain->current();
12591 $otherWatch = $node->getOtherWatch($literal);
12592
12593 if (!$node->getRule()->isDisabled() && !$decisions->satisfy($otherWatch)) {
12594 $ruleLiterals = $node->getRule()->getLiterals();
12595
12596 $alternativeLiterals = array_filter($ruleLiterals, function ($ruleLiteral) use ($literal, $otherWatch, $decisions) {
12597 return $literal !== $ruleLiteral &&
12598 $otherWatch !== $ruleLiteral &&
12599 !$decisions->conflict($ruleLiteral);
12600 });
12601
12602 if ($alternativeLiterals) {
12603 reset($alternativeLiterals);
12604 $this->moveWatch($literal, current($alternativeLiterals), $node);
12605 continue;
12606 }
12607
12608 if ($decisions->conflict($otherWatch)) {
12609 return $node->getRule();
12610 }
12611
12612 $decisions->decide($otherWatch, $level, $node->getRule());
12613 }
12614
12615 $chain->next();
12616 }
12617
12618 return null;
12619 }
12620
12621
12622
12623
12624
12625
12626
12627
12628
12629
12630 protected function moveWatch($fromLiteral, $toLiteral, $node)
12631 {
12632 if (!isset($this->watchChains[$toLiteral])) {
12633 $this->watchChains[$toLiteral] = new RuleWatchChain;
12634 }
12635
12636 $node->moveWatch($fromLiteral, $toLiteral);
12637 $this->watchChains[$fromLiteral]->remove();
12638 $this->watchChains[$toLiteral]->unshift($node);
12639 }
12640 }
12641 <?php
12642
12643
12644
12645
12646
12647
12648
12649
12650
12651
12652
12653 namespace Composer\DependencyResolver;
12654
12655
12656
12657
12658
12659
12660
12661
12662 class RuleWatchNode
12663 {
12664 public $watch1;
12665 public $watch2;
12666
12667 protected $rule;
12668
12669
12670
12671
12672
12673
12674 public function __construct($rule)
12675 {
12676 $this->rule = $rule;
12677
12678 $literals = $rule->getLiterals();
12679
12680 $this->watch1 = count($literals) > 0 ? $literals[0] : 0;
12681 $this->watch2 = count($literals) > 1 ? $literals[1] : 0;
12682 }
12683
12684
12685
12686
12687
12688
12689
12690
12691
12692 public function watch2OnHighest(Decisions $decisions)
12693 {
12694 $literals = $this->rule->getLiterals();
12695
12696
12697  if (count($literals) < 3) {
12698 return;
12699 }
12700
12701 $watchLevel = 0;
12702
12703 foreach ($literals as $literal) {
12704 $level = $decisions->decisionLevel($literal);
12705
12706 if ($level > $watchLevel) {
12707 $this->watch2 = $literal;
12708 $watchLevel = $level;
12709 }
12710 }
12711 }
12712
12713
12714
12715
12716
12717
12718 public function getRule()
12719 {
12720 return $this->rule;
12721 }
12722
12723
12724
12725
12726
12727
12728
12729 public function getOtherWatch($literal)
12730 {
12731 if ($this->watch1 == $literal) {
12732 return $this->watch2;
12733 } else {
12734 return $this->watch1;
12735 }
12736 }
12737
12738
12739
12740
12741
12742
12743
12744 public function moveWatch($from, $to)
12745 {
12746 if ($this->watch1 == $from) {
12747 $this->watch1 = $to;
12748 } else {
12749 $this->watch2 = $to;
12750 }
12751 }
12752 }
12753 <?php
12754
12755
12756
12757
12758
12759
12760
12761
12762
12763
12764
12765 namespace Composer\DependencyResolver;
12766
12767 use Composer\IO\IOInterface;
12768 use Composer\Repository\RepositoryInterface;
12769 use Composer\Repository\PlatformRepository;
12770
12771
12772
12773
12774 class Solver
12775 {
12776 const BRANCH_LITERALS = 0;
12777 const BRANCH_LEVEL = 1;
12778
12779
12780 protected $policy;
12781
12782 protected $pool;
12783
12784 protected $installed;
12785
12786 protected $rules;
12787
12788 protected $ruleSetGenerator;
12789
12790 protected $jobs;
12791
12792
12793 protected $updateMap = array();
12794
12795 protected $watchGraph;
12796
12797 protected $decisions;
12798
12799 protected $installedMap;
12800
12801
12802 protected $propagateIndex;
12803
12804 protected $branches = array();
12805
12806 protected $problems = array();
12807
12808 protected $learnedPool = array();
12809
12810 protected $learnedWhy = array();
12811
12812
12813 protected $io;
12814
12815
12816
12817
12818
12819
12820
12821 public function __construct(PolicyInterface $policy, Pool $pool, RepositoryInterface $installed, IOInterface $io)
12822 {
12823 $this->io = $io;
12824 $this->policy = $policy;
12825 $this->pool = $pool;
12826 $this->installed = $installed;
12827 $this->ruleSetGenerator = new RuleSetGenerator($policy, $pool);
12828 }
12829
12830
12831
12832
12833 public function getRuleSetSize()
12834 {
12835 return count($this->rules);
12836 }
12837
12838
12839
12840 private function makeAssertionRuleDecisions()
12841 {
12842 $decisionStart = count($this->decisions) - 1;
12843
12844 $rulesCount = count($this->rules);
12845 for ($ruleIndex = 0; $ruleIndex < $rulesCount; $ruleIndex++) {
12846 $rule = $this->rules->ruleById[$ruleIndex];
12847
12848 if (!$rule->isAssertion() || $rule->isDisabled()) {
12849 continue;
12850 }
12851
12852 $literals = $rule->getLiterals();
12853 $literal = $literals[0];
12854
12855 if (!$this->decisions->decided(abs($literal))) {
12856 $this->decisions->decide($literal, 1, $rule);
12857 continue;
12858 }
12859
12860 if ($this->decisions->satisfy($literal)) {
12861 continue;
12862 }
12863
12864
12865  if (RuleSet::TYPE_LEARNED === $rule->getType()) {
12866 $rule->disable();
12867 continue;
12868 }
12869
12870 $conflict = $this->decisions->decisionRule($literal);
12871
12872 if ($conflict && RuleSet::TYPE_PACKAGE === $conflict->getType()) {
12873 $problem = new Problem($this->pool);
12874
12875 $problem->addRule($rule);
12876 $problem->addRule($conflict);
12877 $this->disableProblem($rule);
12878 $this->problems[] = $problem;
12879 continue;
12880 }
12881
12882
12883  $problem = new Problem($this->pool);
12884 $problem->addRule($rule);
12885 $problem->addRule($conflict);
12886
12887
12888  
12889  foreach ($this->rules->getIteratorFor(RuleSet::TYPE_JOB) as $assertRule) {
12890 if ($assertRule->isDisabled() || !$assertRule->isAssertion()) {
12891 continue;
12892 }
12893
12894 $assertRuleLiterals = $assertRule->getLiterals();
12895 $assertRuleLiteral = $assertRuleLiterals[0];
12896
12897 if (abs($literal) !== abs($assertRuleLiteral)) {
12898 continue;
12899 }
12900
12901 $problem->addRule($assertRule);
12902 $this->disableProblem($assertRule);
12903 }
12904 $this->problems[] = $problem;
12905
12906 $this->decisions->resetToOffset($decisionStart);
12907 $ruleIndex = -1;
12908 }
12909 }
12910
12911 protected function setupInstalledMap()
12912 {
12913 $this->installedMap = array();
12914 foreach ($this->installed->getPackages() as $package) {
12915 $this->installedMap[$package->id] = $package;
12916 }
12917 }
12918
12919
12920
12921
12922 protected function checkForRootRequireProblems($ignorePlatformReqs)
12923 {
12924 foreach ($this->jobs as $job) {
12925 switch ($job['cmd']) {
12926 case 'update':
12927 $packages = $this->pool->whatProvides($job['packageName'], $job['constraint']);
12928 foreach ($packages as $package) {
12929 if (isset($this->installedMap[$package->id])) {
12930 $this->updateMap[$package->id] = true;
12931 }
12932 }
12933 break;
12934
12935 case 'update-all':
12936 foreach ($this->installedMap as $package) {
12937 $this->updateMap[$package->id] = true;
12938 }
12939 break;
12940
12941 case 'install':
12942 if ($ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $job['packageName'])) {
12943 break;
12944 }
12945
12946 if (!$this->pool->whatProvides($job['packageName'], $job['constraint'])) {
12947 $problem = new Problem($this->pool);
12948 $problem->addRule(new GenericRule(array(), null, null, $job));
12949 $this->problems[] = $problem;
12950 }
12951 break;
12952 }
12953 }
12954 }
12955
12956
12957
12958
12959
12960
12961 public function solve(Request $request, $ignorePlatformReqs = false)
12962 {
12963 $this->jobs = $request->getJobs();
12964
12965 $this->setupInstalledMap();
12966 $this->rules = $this->ruleSetGenerator->getRulesFor($this->jobs, $this->installedMap, $ignorePlatformReqs);
12967 $this->checkForRootRequireProblems($ignorePlatformReqs);
12968 $this->decisions = new Decisions($this->pool);
12969 $this->watchGraph = new RuleWatchGraph;
12970
12971 foreach ($this->rules as $rule) {
12972 $this->watchGraph->insert(new RuleWatchNode($rule));
12973 }
12974
12975
12976 $this->makeAssertionRuleDecisions();
12977
12978 $this->io->writeError('Resolving dependencies through SAT', true, IOInterface::DEBUG);
12979 $before = microtime(true);
12980 $this->runSat(true);
12981 $this->io->writeError(sprintf('Dependency resolution completed in %.3f seconds', microtime(true) - $before), true, IOInterface::VERBOSE);
12982
12983
12984  foreach ($this->installedMap as $packageId => $void) {
12985 if ($this->decisions->undecided($packageId)) {
12986 $this->decisions->decide(-$packageId, 1, null);
12987 }
12988 }
12989
12990 if ($this->problems) {
12991 throw new SolverProblemsException($this->problems, $this->installedMap);
12992 }
12993
12994 $transaction = new Transaction($this->policy, $this->pool, $this->installedMap, $this->decisions);
12995
12996 return $transaction->getOperations();
12997 }
12998
12999
13000
13001
13002
13003
13004
13005
13006
13007
13008 protected function propagate($level)
13009 {
13010 while ($this->decisions->validOffset($this->propagateIndex)) {
13011 $decision = $this->decisions->atOffset($this->propagateIndex);
13012
13013 $conflict = $this->watchGraph->propagateLiteral(
13014 $decision[Decisions::DECISION_LITERAL],
13015 $level,
13016 $this->decisions
13017 );
13018
13019 $this->propagateIndex++;
13020
13021 if ($conflict) {
13022 return $conflict;
13023 }
13024 }
13025
13026 return null;
13027 }
13028
13029
13030
13031
13032
13033
13034 private function revert($level)
13035 {
13036 while (!$this->decisions->isEmpty()) {
13037 $literal = $this->decisions->lastLiteral();
13038
13039 if ($this->decisions->undecided($literal)) {
13040 break;
13041 }
13042
13043 $decisionLevel = $this->decisions->decisionLevel($literal);
13044
13045 if ($decisionLevel <= $level) {
13046 break;
13047 }
13048
13049 $this->decisions->revertLast();
13050 $this->propagateIndex = count($this->decisions);
13051 }
13052
13053 while (!empty($this->branches) && $this->branches[count($this->branches) - 1][self::BRANCH_LEVEL] >= $level) {
13054 array_pop($this->branches);
13055 }
13056 }
13057
13058
13059
13060
13061
13062
13063
13064
13065
13066
13067
13068
13069
13070
13071
13072
13073
13074
13075
13076
13077 private function setPropagateLearn($level, $literal, $disableRules, Rule $rule)
13078 {
13079 $level++;
13080
13081 $this->decisions->decide($literal, $level, $rule);
13082
13083 while (true) {
13084 $rule = $this->propagate($level);
13085
13086 if (!$rule) {
13087 break;
13088 }
13089
13090 if ($level == 1) {
13091 return $this->analyzeUnsolvable($rule, $disableRules);
13092 }
13093
13094
13095  list($learnLiteral, $newLevel, $newRule, $why) = $this->analyze($level, $rule);
13096
13097 if ($newLevel <= 0 || $newLevel >= $level) {
13098 throw new SolverBugException(
13099 "Trying to revert to invalid level ".(int) $newLevel." from level ".(int) $level."."
13100 );
13101 } elseif (!$newRule) {
13102 throw new SolverBugException(
13103 "No rule was learned from analyzing $rule at level $level."
13104 );
13105 }
13106
13107 $level = $newLevel;
13108
13109 $this->revert($level);
13110
13111 $this->rules->add($newRule, RuleSet::TYPE_LEARNED);
13112
13113 $this->learnedWhy[spl_object_hash($newRule)] = $why;
13114
13115 $ruleNode = new RuleWatchNode($newRule);
13116 $ruleNode->watch2OnHighest($this->decisions);
13117 $this->watchGraph->insert($ruleNode);
13118
13119 $this->decisions->decide($learnLiteral, $level, $newRule);
13120 }
13121
13122 return $level;
13123 }
13124
13125
13126
13127
13128
13129
13130
13131
13132 private function selectAndInstall($level, array $decisionQueue, $disableRules, Rule $rule)
13133 {
13134
13135  $literals = $this->policy->selectPreferredPackages($this->pool, $this->installedMap, $decisionQueue, $rule->getRequiredPackage());
13136
13137 $selectedLiteral = array_shift($literals);
13138
13139
13140  if (count($literals)) {
13141 $this->branches[] = array($literals, $level);
13142 }
13143
13144 return $this->setPropagateLearn($level, $selectedLiteral, $disableRules, $rule);
13145 }
13146
13147
13148
13149
13150
13151
13152 protected function analyze($level, Rule $rule)
13153 {
13154 $analyzedRule = $rule;
13155 $ruleLevel = 1;
13156 $num = 0;
13157 $l1num = 0;
13158 $seen = array();
13159 $learnedLiterals = array(null);
13160
13161 $decisionId = count($this->decisions);
13162
13163 $this->learnedPool[] = array();
13164
13165 while (true) {
13166 $this->learnedPool[count($this->learnedPool) - 1][] = $rule;
13167
13168 foreach ($rule->getLiterals() as $literal) {
13169
13170  if ($this->decisions->satisfy($literal)) {
13171 continue;
13172 }
13173
13174 if (isset($seen[abs($literal)])) {
13175 continue;
13176 }
13177 $seen[abs($literal)] = true;
13178
13179 $l = $this->decisions->decisionLevel($literal);
13180
13181 if (1 === $l) {
13182 $l1num++;
13183 } elseif ($level === $l) {
13184 $num++;
13185 } else {
13186
13187  $learnedLiterals[] = $literal;
13188
13189 if ($l > $ruleLevel) {
13190 $ruleLevel = $l;
13191 }
13192 }
13193 }
13194
13195 $l1retry = true;
13196 while ($l1retry) {
13197 $l1retry = false;
13198
13199 if (!$num && !--$l1num) {
13200
13201  break 2;
13202 }
13203
13204 while (true) {
13205 if ($decisionId <= 0) {
13206 throw new SolverBugException(
13207 "Reached invalid decision id $decisionId while looking through $rule for a literal present in the analyzed rule $analyzedRule."
13208 );
13209 }
13210
13211 $decisionId--;
13212
13213 $decision = $this->decisions->atOffset($decisionId);
13214 $literal = $decision[Decisions::DECISION_LITERAL];
13215
13216 if (isset($seen[abs($literal)])) {
13217 break;
13218 }
13219 }
13220
13221 unset($seen[abs($literal)]);
13222
13223 if ($num && 0 === --$num) {
13224 $learnedLiterals[0] = -abs($literal);
13225
13226 if (!$l1num) {
13227 break 2;
13228 }
13229
13230 foreach ($learnedLiterals as $i => $learnedLiteral) {
13231 if ($i !== 0) {
13232 unset($seen[abs($learnedLiteral)]);
13233 }
13234 }
13235
13236  $l1num++;
13237 $l1retry = true;
13238 }
13239 }
13240
13241 $decision = $this->decisions->atOffset($decisionId);
13242 $rule = $decision[Decisions::DECISION_REASON];
13243 }
13244
13245 $why = count($this->learnedPool) - 1;
13246
13247 if (!$learnedLiterals[0]) {
13248 throw new SolverBugException(
13249 "Did not find a learnable literal in analyzed rule $analyzedRule."
13250 );
13251 }
13252
13253 $newRule = new GenericRule($learnedLiterals, Rule::RULE_LEARNED, $why);
13254
13255 return array($learnedLiterals[0], $ruleLevel, $newRule, $why);
13256 }
13257
13258
13259
13260
13261
13262 private function analyzeUnsolvableRule(Problem $problem, Rule $conflictRule)
13263 {
13264 $why = spl_object_hash($conflictRule);
13265
13266 if ($conflictRule->getType() == RuleSet::TYPE_LEARNED) {
13267 $learnedWhy = $this->learnedWhy[$why];
13268 $problemRules = $this->learnedPool[$learnedWhy];
13269
13270 foreach ($problemRules as $problemRule) {
13271 $this->analyzeUnsolvableRule($problem, $problemRule);
13272 }
13273
13274 return;
13275 }
13276
13277 if ($conflictRule->getType() == RuleSet::TYPE_PACKAGE) {
13278
13279  return;
13280 }
13281
13282 $problem->nextSection();
13283 $problem->addRule($conflictRule);
13284 }
13285
13286
13287
13288
13289
13290
13291 private function analyzeUnsolvable(Rule $conflictRule, $disableRules)
13292 {
13293 $problem = new Problem($this->pool);
13294 $problem->addRule($conflictRule);
13295
13296 $this->analyzeUnsolvableRule($problem, $conflictRule);
13297
13298 $this->problems[] = $problem;
13299
13300 $seen = array();
13301 $literals = $conflictRule->getLiterals();
13302
13303 foreach ($literals as $literal) {
13304
13305  if ($this->decisions->satisfy($literal)) {
13306 continue;
13307 }
13308 $seen[abs($literal)] = true;
13309 }
13310
13311 foreach ($this->decisions as $decision) {
13312 $literal = $decision[Decisions::DECISION_LITERAL];
13313
13314
13315  if (!isset($seen[abs($literal)])) {
13316 continue;
13317 }
13318
13319 $why = $decision[Decisions::DECISION_REASON];
13320
13321 $problem->addRule($why);
13322 $this->analyzeUnsolvableRule($problem, $why);
13323
13324 $literals = $why->getLiterals();
13325
13326 foreach ($literals as $literal) {
13327
13328  if ($this->decisions->satisfy($literal)) {
13329 continue;
13330 }
13331 $seen[abs($literal)] = true;
13332 }
13333 }
13334
13335 if ($disableRules) {
13336 foreach ($this->problems[count($this->problems) - 1] as $reason) {
13337 $this->disableProblem($reason['rule']);
13338 }
13339
13340 $this->resetSolver();
13341
13342 return 1;
13343 }
13344
13345 return 0;
13346 }
13347
13348
13349
13350
13351 private function disableProblem(Rule $why)
13352 {
13353 $job = $why->getJob();
13354
13355 if (!$job) {
13356 $why->disable();
13357
13358 return;
13359 }
13360
13361
13362  foreach ($this->rules as $rule) {
13363
13364 if ($job === $rule->getJob()) {
13365 $rule->disable();
13366 }
13367 }
13368 }
13369
13370 private function resetSolver()
13371 {
13372 $this->decisions->reset();
13373
13374 $this->propagateIndex = 0;
13375 $this->branches = array();
13376
13377 $this->enableDisableLearnedRules();
13378 $this->makeAssertionRuleDecisions();
13379 }
13380
13381
13382
13383
13384
13385
13386
13387
13388 private function enableDisableLearnedRules()
13389 {
13390 foreach ($this->rules->getIteratorFor(RuleSet::TYPE_LEARNED) as $rule) {
13391 $why = $this->learnedWhy[spl_object_hash($rule)];
13392 $problemRules = $this->learnedPool[$why];
13393
13394 $foundDisabled = false;
13395 foreach ($problemRules as $problemRule) {
13396 if ($problemRule->isDisabled()) {
13397 $foundDisabled = true;
13398 break;
13399 }
13400 }
13401
13402 if ($foundDisabled && $rule->isEnabled()) {
13403 $rule->disable();
13404 } elseif (!$foundDisabled && $rule->isDisabled()) {
13405 $rule->enable();
13406 }
13407 }
13408 }
13409
13410
13411
13412
13413 private function runSat($disableRules = true)
13414 {
13415 $this->propagateIndex = 0;
13416
13417
13418
13419
13420
13421
13422
13423
13424
13425
13426
13427 $decisionQueue = array();
13428 $decisionSupplementQueue = array();
13429
13430
13431
13432 $disableRules = array();
13433
13434 $level = 1;
13435 $systemLevel = $level + 1;
13436 $installedPos = 0;
13437
13438 while (true) {
13439 if (1 === $level) {
13440 $conflictRule = $this->propagate($level);
13441 if (null !== $conflictRule) {
13442 if ($this->analyzeUnsolvable($conflictRule, $disableRules)) {
13443 continue;
13444 }
13445
13446 return;
13447 }
13448 }
13449
13450
13451  if ($level < $systemLevel) {
13452 $iterator = $this->rules->getIteratorFor(RuleSet::TYPE_JOB);
13453 foreach ($iterator as $rule) {
13454 if ($rule->isEnabled()) {
13455 $decisionQueue = array();
13456 $noneSatisfied = true;
13457
13458 foreach ($rule->getLiterals() as $literal) {
13459 if ($this->decisions->satisfy($literal)) {
13460 $noneSatisfied = false;
13461 break;
13462 }
13463 if ($literal > 0 && $this->decisions->undecided($literal)) {
13464 $decisionQueue[] = $literal;
13465 }
13466 }
13467
13468 if ($noneSatisfied && count($decisionQueue)) {
13469
13470  
13471  if (count($this->installed) != count($this->updateMap)) {
13472 $prunedQueue = array();
13473 foreach ($decisionQueue as $literal) {
13474 if (isset($this->installedMap[abs($literal)])) {
13475 $prunedQueue[] = $literal;
13476 if (isset($this->updateMap[abs($literal)])) {
13477 $prunedQueue = $decisionQueue;
13478 break;
13479 }
13480 }
13481 }
13482 $decisionQueue = $prunedQueue;
13483 }
13484 }
13485
13486 if ($noneSatisfied && count($decisionQueue)) {
13487 $oLevel = $level;
13488 $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
13489
13490 if (0 === $level) {
13491 return;
13492 }
13493 if ($level <= $oLevel) {
13494 break;
13495 }
13496 }
13497 }
13498 }
13499
13500 $systemLevel = $level + 1;
13501
13502
13503  $iterator->next();
13504 if ($iterator->valid()) {
13505 continue;
13506 }
13507 }
13508
13509 if ($level < $systemLevel) {
13510 $systemLevel = $level;
13511 }
13512
13513 $rulesCount = count($this->rules);
13514
13515 for ($i = 0, $n = 0; $n < $rulesCount; $i++, $n++) {
13516 if ($i == $rulesCount) {
13517 $i = 0;
13518 }
13519
13520 $rule = $this->rules->ruleById[$i];
13521 $literals = $rule->getLiterals();
13522
13523 if ($rule->isDisabled()) {
13524 continue;
13525 }
13526
13527 $decisionQueue = array();
13528
13529
13530  
13531  
13532  
13533  
13534  
13535  foreach ($literals as $literal) {
13536 if ($literal <= 0) {
13537 if (!$this->decisions->decidedInstall(abs($literal))) {
13538 continue 2; 
13539  }
13540 } else {
13541 if ($this->decisions->decidedInstall(abs($literal))) {
13542 continue 2; 
13543  }
13544 if ($this->decisions->undecided(abs($literal))) {
13545 $decisionQueue[] = $literal;
13546 }
13547 }
13548 }
13549
13550
13551  if (count($decisionQueue) < 2) {
13552 continue;
13553 }
13554
13555 $level = $this->selectAndInstall($level, $decisionQueue, $disableRules, $rule);
13556
13557 if (0 === $level) {
13558 return;
13559 }
13560
13561
13562  $rulesCount = count($this->rules);
13563 $n = -1;
13564 }
13565
13566 if ($level < $systemLevel) {
13567 continue;
13568 }
13569
13570
13571  if (count($this->branches)) {
13572 $lastLiteral = null;
13573 $lastLevel = null;
13574 $lastBranchIndex = 0;
13575 $lastBranchOffset = 0;
13576
13577 for ($i = count($this->branches) - 1; $i >= 0; $i--) {
13578 list($literals, $l) = $this->branches[$i];
13579
13580 foreach ($literals as $offset => $literal) {
13581 if ($literal && $literal > 0 && $this->decisions->decisionLevel($literal) > $l + 1) {
13582 $lastLiteral = $literal;
13583 $lastBranchIndex = $i;
13584 $lastBranchOffset = $offset;
13585 $lastLevel = $l;
13586 }
13587 }
13588 }
13589
13590 if ($lastLiteral) {
13591 unset($this->branches[$lastBranchIndex][self::BRANCH_LITERALS][$lastBranchOffset]);
13592
13593 $level = $lastLevel;
13594 $this->revert($level);
13595
13596 $why = $this->decisions->lastReason();
13597
13598 $level = $this->setPropagateLearn($level, $lastLiteral, $disableRules, $why);
13599
13600 if ($level == 0) {
13601 return;
13602 }
13603
13604 continue;
13605 }
13606 }
13607
13608 break;
13609 }
13610 }
13611 }
13612 <?php
13613
13614
13615
13616
13617
13618
13619
13620
13621
13622
13623
13624 namespace Composer\DependencyResolver;
13625
13626
13627
13628
13629 class SolverBugException extends \RuntimeException
13630 {
13631 public function __construct($message)
13632 {
13633 parent::__construct(
13634 $message."\nThis exception was most likely caused by a bug in Composer.\n".
13635 "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");
13636 }
13637 }
13638 <?php
13639
13640
13641
13642
13643
13644
13645
13646
13647
13648
13649
13650 namespace Composer\DependencyResolver;
13651
13652 use Composer\Util\IniHelper;
13653
13654
13655
13656
13657 class SolverProblemsException extends \RuntimeException
13658 {
13659 protected $problems;
13660 protected $installedMap;
13661
13662 public function __construct(array $problems, array $installedMap)
13663 {
13664 $this->problems = $problems;
13665 $this->installedMap = $installedMap;
13666
13667 parent::__construct($this->createMessage(), 2);
13668 }
13669
13670 protected function createMessage()
13671 {
13672 $text = "\n";
13673 $hasExtensionProblems = false;
13674 foreach ($this->problems as $i => $problem) {
13675 $text .= "  Problem ".($i + 1).$problem->getPrettyString($this->installedMap)."\n";
13676
13677 if (!$hasExtensionProblems && $this->hasExtensionProblems($problem->getReasons())) {
13678 $hasExtensionProblems = true;
13679 }
13680 }
13681
13682 if (strpos($text, 'could not be found') || strpos($text, 'no matching package found')) {
13683 $text .= "\nPotential causes:\n - A typo in the package name\n - The package is not available in a stable-enough version according to your minimum-stability setting\n   see <https://getcomposer.org/doc/04-schema.md#minimum-stability> for more details.\n\nRead <https://getcomposer.org/doc/articles/troubleshooting.md> for further common problems.";
13684 }
13685
13686 if ($hasExtensionProblems) {
13687 $text .= $this->createExtensionHint();
13688 }
13689
13690 return $text;
13691 }
13692
13693 public function getProblems()
13694 {
13695 return $this->problems;
13696 }
13697
13698 private function createExtensionHint()
13699 {
13700 $paths = IniHelper::getAll();
13701
13702 if (count($paths) === 1 && empty($paths[0])) {
13703 return '';
13704 }
13705
13706 $text = "\n  To enable extensions, verify that they are enabled in your .ini files:\n    - ";
13707 $text .= implode("\n    - ", $paths);
13708 $text .= "\n  You can also run `php --ini` inside terminal to see which files are used by PHP in CLI mode.";
13709
13710 return $text;
13711 }
13712
13713 private function hasExtensionProblems(array $reasonSets)
13714 {
13715 foreach ($reasonSets as $reasonSet) {
13716 foreach ($reasonSet as $reason) {
13717 if (isset($reason["rule"]) && 0 === strpos($reason["rule"]->getRequiredPackage(), 'ext-')) {
13718 return true;
13719 }
13720 }
13721 }
13722
13723 return false;
13724 }
13725 }
13726 <?php
13727
13728
13729
13730
13731
13732
13733
13734
13735
13736
13737
13738 namespace Composer\DependencyResolver;
13739
13740 use Composer\Package\AliasPackage;
13741
13742
13743
13744
13745 class Transaction
13746 {
13747 protected $policy;
13748 protected $pool;
13749 protected $installedMap;
13750 protected $decisions;
13751 protected $transaction;
13752
13753 public function __construct($policy, $pool, $installedMap, $decisions)
13754 {
13755 $this->policy = $policy;
13756 $this->pool = $pool;
13757 $this->installedMap = $installedMap;
13758 $this->decisions = $decisions;
13759 $this->transaction = array();
13760 }
13761
13762 public function getOperations()
13763 {
13764 $installMeansUpdateMap = $this->findUpdates();
13765
13766 $updateMap = array();
13767 $installMap = array();
13768 $uninstallMap = array();
13769
13770 foreach ($this->decisions as $i => $decision) {
13771 $literal = $decision[Decisions::DECISION_LITERAL];
13772 $reason = $decision[Decisions::DECISION_REASON];
13773
13774 $package = $this->pool->literalToPackage($literal);
13775
13776
13777  if (($literal > 0) == (isset($this->installedMap[$package->id]))) {
13778 continue;
13779 }
13780
13781 if ($literal > 0) {
13782 if (isset($installMeansUpdateMap[abs($literal)]) && !$package instanceof AliasPackage) {
13783 $source = $installMeansUpdateMap[abs($literal)];
13784
13785 $updateMap[$package->id] = array(
13786 'package' => $package,
13787 'source' => $source,
13788 'reason' => $reason,
13789 );
13790
13791
13792  unset($installMeansUpdateMap[abs($literal)]);
13793 $ignoreRemove[$source->id] = true;
13794 } else {
13795 $installMap[$package->id] = array(
13796 'package' => $package,
13797 'reason' => $reason,
13798 );
13799 }
13800 }
13801 }
13802
13803 foreach ($this->decisions as $i => $decision) {
13804 $literal = $decision[Decisions::DECISION_LITERAL];
13805 $reason = $decision[Decisions::DECISION_REASON];
13806 $package = $this->pool->literalToPackage($literal);
13807
13808 if ($literal <= 0 &&
13809 isset($this->installedMap[$package->id]) &&
13810 !isset($ignoreRemove[$package->id])) {
13811 $uninstallMap[$package->id] = array(
13812 'package' => $package,
13813 'reason' => $reason,
13814 );
13815 }
13816 }
13817
13818 $this->transactionFromMaps($installMap, $updateMap, $uninstallMap);
13819
13820 return $this->transaction;
13821 }
13822
13823 protected function transactionFromMaps($installMap, $updateMap, $uninstallMap)
13824 {
13825 $queue = array_map(
13826 function ($operation) {
13827 return $operation['package'];
13828 },
13829 $this->findRootPackages($installMap, $updateMap)
13830 );
13831
13832 $visited = array();
13833
13834 while (!empty($queue)) {
13835 $package = array_pop($queue);
13836 $packageId = $package->id;
13837
13838 if (!isset($visited[$packageId])) {
13839 array_push($queue, $package);
13840
13841 if ($package instanceof AliasPackage) {
13842 array_push($queue, $package->getAliasOf());
13843 } else {
13844 foreach ($package->getRequires() as $link) {
13845 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
13846
13847 foreach ($possibleRequires as $require) {
13848 array_push($queue, $require);
13849 }
13850 }
13851 }
13852
13853 $visited[$package->id] = true;
13854 } else {
13855 if (isset($installMap[$packageId])) {
13856 $this->install(
13857 $installMap[$packageId]['package'],
13858 $installMap[$packageId]['reason']
13859 );
13860 unset($installMap[$packageId]);
13861 }
13862 if (isset($updateMap[$packageId])) {
13863 $this->update(
13864 $updateMap[$packageId]['source'],
13865 $updateMap[$packageId]['package'],
13866 $updateMap[$packageId]['reason']
13867 );
13868 unset($updateMap[$packageId]);
13869 }
13870 }
13871 }
13872
13873 foreach ($uninstallMap as $uninstall) {
13874 $this->uninstall($uninstall['package'], $uninstall['reason']);
13875 }
13876 }
13877
13878 protected function findRootPackages($installMap, $updateMap)
13879 {
13880 $packages = $installMap + $updateMap;
13881 $roots = $packages;
13882
13883 foreach ($packages as $packageId => $operation) {
13884 $package = $operation['package'];
13885
13886 if (!isset($roots[$packageId])) {
13887 continue;
13888 }
13889
13890 foreach ($package->getRequires() as $link) {
13891 $possibleRequires = $this->pool->whatProvides($link->getTarget(), $link->getConstraint());
13892
13893 foreach ($possibleRequires as $require) {
13894 if ($require !== $package) {
13895 unset($roots[$require->id]);
13896 }
13897 }
13898 }
13899 }
13900
13901 return $roots;
13902 }
13903
13904 protected function findUpdates()
13905 {
13906 $installMeansUpdateMap = array();
13907
13908 foreach ($this->decisions as $i => $decision) {
13909 $literal = $decision[Decisions::DECISION_LITERAL];
13910 $package = $this->pool->literalToPackage($literal);
13911
13912 if ($package instanceof AliasPackage) {
13913 continue;
13914 }
13915
13916
13917  if ($literal <= 0 && isset($this->installedMap[$package->id])) {
13918 $updates = $this->policy->findUpdatePackages($this->pool, $this->installedMap, $package);
13919
13920 $literals = array($package->id);
13921
13922 foreach ($updates as $update) {
13923 $literals[] = $update->id;
13924 }
13925
13926 foreach ($literals as $updateLiteral) {
13927 if ($updateLiteral !== $literal) {
13928 $installMeansUpdateMap[abs($updateLiteral)] = $package;
13929 }
13930 }
13931 }
13932 }
13933
13934 return $installMeansUpdateMap;
13935 }
13936
13937 protected function install($package, $reason)
13938 {
13939 if ($package instanceof AliasPackage) {
13940 return $this->markAliasInstalled($package, $reason);
13941 }
13942
13943 $this->transaction[] = new Operation\InstallOperation($package, $reason);
13944 }
13945
13946 protected function update($from, $to, $reason)
13947 {
13948 $this->transaction[] = new Operation\UpdateOperation($from, $to, $reason);
13949 }
13950
13951 protected function uninstall($package, $reason)
13952 {
13953 if ($package instanceof AliasPackage) {
13954 return $this->markAliasUninstalled($package, $reason);
13955 }
13956
13957 $this->transaction[] = new Operation\UninstallOperation($package, $reason);
13958 }
13959
13960 protected function markAliasInstalled($package, $reason)
13961 {
13962 $this->transaction[] = new Operation\MarkAliasInstalledOperation($package, $reason);
13963 }
13964
13965 protected function markAliasUninstalled($package, $reason)
13966 {
13967 $this->transaction[] = new Operation\MarkAliasUninstalledOperation($package, $reason);
13968 }
13969 }
13970 <?php
13971
13972
13973
13974
13975
13976
13977
13978
13979
13980
13981
13982 namespace Composer\Downloader;
13983
13984 use Composer\Package\PackageInterface;
13985 use Symfony\Component\Finder\Finder;
13986 use Composer\IO\IOInterface;
13987
13988
13989
13990
13991
13992
13993
13994
13995 abstract class ArchiveDownloader extends FileDownloader
13996 {
13997
13998
13999
14000 public function download(PackageInterface $package, $path, $output = true)
14001 {
14002 $temporaryDir = $this->config->get('vendor-dir').'/composer/'.substr(md5(uniqid('', true)), 0, 8);
14003 $retries = 3;
14004 while ($retries--) {
14005 $fileName = parent::download($package, $path, $output);
14006
14007 $this->io->writeError(' Extracting archive', false, IOInterface::VERBOSE);
14008
14009 try {
14010 $this->filesystem->ensureDirectoryExists($temporaryDir);
14011 try {
14012 $this->extract($fileName, $temporaryDir);
14013 } catch (\Exception $e) {
14014
14015  parent::clearLastCacheWrite($package);
14016 throw $e;
14017 }
14018
14019 $this->filesystem->unlink($fileName);
14020
14021 $contentDir = $this->getFolderContent($temporaryDir);
14022
14023
14024  if (1 === count($contentDir) && is_dir(reset($contentDir))) {
14025 $contentDir = $this->getFolderContent((string) reset($contentDir));
14026 }
14027
14028
14029  foreach ($contentDir as $file) {
14030 $file = (string) $file;
14031 $this->filesystem->rename($file, $path . '/' . basename($file));
14032 }
14033
14034 $this->filesystem->removeDirectory($temporaryDir);
14035 if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir').'/composer/')) {
14036 $this->filesystem->removeDirectory($this->config->get('vendor-dir').'/composer/');
14037 }
14038 if ($this->filesystem->isDirEmpty($this->config->get('vendor-dir'))) {
14039 $this->filesystem->removeDirectory($this->config->get('vendor-dir'));
14040 }
14041 } catch (\Exception $e) {
14042
14043  $this->filesystem->removeDirectory($path);
14044 $this->filesystem->removeDirectory($temporaryDir);
14045
14046
14047  if ($retries && $e instanceof \UnexpectedValueException && class_exists('ZipArchive') && $e->getCode() === \ZipArchive::ER_NOZIP) {
14048 $this->io->writeError('');
14049 if ($this->io->isDebug()) {
14050 $this->io->writeError('    Invalid zip file ('.$e->getMessage().'), retrying...');
14051 } else {
14052 $this->io->writeError('    Invalid zip file, retrying...');
14053 }
14054 usleep(500000);
14055 continue;
14056 }
14057
14058 throw $e;
14059 }
14060
14061 break;
14062 }
14063 }
14064
14065
14066
14067
14068 protected function getFileName(PackageInterface $package, $path)
14069 {
14070 return rtrim($path.'/'.md5($path.spl_object_hash($package)).'.'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_EXTENSION), '.');
14071 }
14072
14073
14074
14075
14076 protected function processUrl(PackageInterface $package, $url)
14077 {
14078 if ($package->getDistReference() && strpos($url, 'github.com')) {
14079 if (preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/(zip|tar)ball/(.+)$}i', $url, $match)) {
14080
14081  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $package->getDistReference();
14082 } elseif ($package->getDistReference() && preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/archive/.+\.(zip|tar)(?:\.gz)?$}i', $url, $match)) {
14083
14084  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $package->getDistReference();
14085 } elseif ($package->getDistReference() && preg_match('{^https?://api\.github\.com/repos/([^/]+)/([^/]+)/(zip|tar)ball(?:/.+)?$}i', $url, $match)) {
14086
14087  $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $package->getDistReference();
14088 }
14089 } elseif ($package->getDistReference() && strpos($url, 'bitbucket.org')) {
14090 if (preg_match('{^https?://(?:www\.)?bitbucket\.org/([^/]+)/([^/]+)/get/(.+)\.(zip|tar\.gz|tar\.bz2)$}i', $url, $match)) {
14091
14092  $url = 'https://bitbucket.org/' . $match[1] . '/'. $match[2] . '/get/' . $package->getDistReference() . '.' . $match[4];
14093 }
14094 }
14095
14096 return parent::processUrl($package, $url);
14097 }
14098
14099
14100
14101
14102
14103
14104
14105
14106
14107 abstract protected function extract($file, $path);
14108
14109
14110
14111
14112
14113
14114
14115 private function getFolderContent($dir)
14116 {
14117 $finder = Finder::create()
14118 ->ignoreVCS(false)
14119 ->ignoreDotFiles(false)
14120 ->depth(0)
14121 ->in($dir);
14122
14123 return iterator_to_array($finder);
14124 }
14125 }
14126 <?php
14127
14128
14129
14130
14131
14132
14133
14134
14135
14136
14137
14138 namespace Composer\Downloader;
14139
14140 use Composer\Package\PackageInterface;
14141
14142
14143
14144
14145
14146
14147 interface ChangeReportInterface
14148 {
14149
14150
14151
14152
14153
14154
14155
14156 public function getLocalChanges(PackageInterface $package, $path);
14157 }
14158 <?php
14159
14160
14161
14162
14163
14164
14165
14166
14167
14168
14169
14170 namespace Composer\Downloader;
14171
14172 use Composer\Package\PackageInterface;
14173 use Composer\IO\IOInterface;
14174 use Composer\Util\Filesystem;
14175
14176
14177
14178
14179
14180
14181 class DownloadManager
14182 {
14183 private $io;
14184 private $preferDist = false;
14185 private $preferSource = false;
14186 private $packagePreferences = array();
14187 private $filesystem;
14188 private $downloaders = array();
14189
14190
14191
14192
14193
14194
14195
14196
14197 public function __construct(IOInterface $io, $preferSource = false, Filesystem $filesystem = null)
14198 {
14199 $this->io = $io;
14200 $this->preferSource = $preferSource;
14201 $this->filesystem = $filesystem ?: new Filesystem();
14202 }
14203
14204
14205
14206
14207
14208
14209
14210 public function setPreferSource($preferSource)
14211 {
14212 $this->preferSource = $preferSource;
14213
14214 return $this;
14215 }
14216
14217
14218
14219
14220
14221
14222
14223 public function setPreferDist($preferDist)
14224 {
14225 $this->preferDist = $preferDist;
14226
14227 return $this;
14228 }
14229
14230
14231
14232
14233
14234
14235
14236 public function setPreferences(array $preferences)
14237 {
14238 $this->packagePreferences = $preferences;
14239
14240 return $this;
14241 }
14242
14243
14244
14245
14246
14247
14248
14249
14250 public function setOutputProgress($outputProgress)
14251 {
14252 foreach ($this->downloaders as $downloader) {
14253 $downloader->setOutputProgress($outputProgress);
14254 }
14255
14256 return $this;
14257 }
14258
14259
14260
14261
14262
14263
14264
14265
14266 public function setDownloader($type, DownloaderInterface $downloader)
14267 {
14268 $type = strtolower($type);
14269 $this->downloaders[$type] = $downloader;
14270
14271 return $this;
14272 }
14273
14274
14275
14276
14277
14278
14279
14280
14281 public function getDownloader($type)
14282 {
14283 $type = strtolower($type);
14284 if (!isset($this->downloaders[$type])) {
14285 throw new \InvalidArgumentException(sprintf('Unknown downloader type: %s. Available types: %s.', $type, implode(', ', array_keys($this->downloaders))));
14286 }
14287
14288 return $this->downloaders[$type];
14289 }
14290
14291
14292
14293
14294
14295
14296
14297
14298
14299
14300 public function getDownloaderForInstalledPackage(PackageInterface $package)
14301 {
14302 $installationSource = $package->getInstallationSource();
14303
14304 if ('metapackage' === $package->getType()) {
14305 return;
14306 }
14307
14308 if ('dist' === $installationSource) {
14309 $downloader = $this->getDownloader($package->getDistType());
14310 } elseif ('source' === $installationSource) {
14311 $downloader = $this->getDownloader($package->getSourceType());
14312 } else {
14313 throw new \InvalidArgumentException(
14314 'Package '.$package.' seems not been installed properly'
14315 );
14316 }
14317
14318 if ($installationSource !== $downloader->getInstallationSource()) {
14319 throw new \LogicException(sprintf(
14320 'Downloader "%s" is a %s type downloader and can not be used to download %s',
14321 get_class($downloader), $downloader->getInstallationSource(), $installationSource
14322 ));
14323 }
14324
14325 return $downloader;
14326 }
14327
14328
14329
14330
14331
14332
14333
14334
14335
14336
14337
14338 public function download(PackageInterface $package, $targetDir, $preferSource = null)
14339 {
14340 $preferSource = null !== $preferSource ? $preferSource : $this->preferSource;
14341 $sourceType = $package->getSourceType();
14342 $distType = $package->getDistType();
14343
14344 $sources = array();
14345 if ($sourceType) {
14346 $sources[] = 'source';
14347 }
14348 if ($distType) {
14349 $sources[] = 'dist';
14350 }
14351
14352 if (empty($sources)) {
14353 throw new \InvalidArgumentException('Package '.$package.' must have a source or dist specified');
14354 }
14355
14356 if (!$preferSource && ($this->preferDist || 'dist' === $this->resolvePackageInstallPreference($package))) {
14357 $sources = array_reverse($sources);
14358 }
14359
14360 $this->filesystem->ensureDirectoryExists($targetDir);
14361
14362 foreach ($sources as $i => $source) {
14363 if (isset($e)) {
14364 $this->io->writeError('    <warning>Now trying to download from ' . $source . '</warning>');
14365 }
14366 $package->setInstallationSource($source);
14367 try {
14368 $downloader = $this->getDownloaderForInstalledPackage($package);
14369 if ($downloader) {
14370 $downloader->download($package, $targetDir);
14371 }
14372 break;
14373 } catch (\RuntimeException $e) {
14374 if ($i === count($sources) - 1) {
14375 throw $e;
14376 }
14377
14378 $this->io->writeError(
14379 '    <warning>Failed to download '.
14380 $package->getPrettyName().
14381 ' from ' . $source . ': '.
14382 $e->getMessage().'</warning>'
14383 );
14384 }
14385 }
14386 }
14387
14388
14389
14390
14391
14392
14393
14394
14395
14396
14397 public function update(PackageInterface $initial, PackageInterface $target, $targetDir)
14398 {
14399 $downloader = $this->getDownloaderForInstalledPackage($initial);
14400 if (!$downloader) {
14401 return;
14402 }
14403
14404 $installationSource = $initial->getInstallationSource();
14405
14406 if ('dist' === $installationSource) {
14407 $initialType = $initial->getDistType();
14408 $targetType = $target->getDistType();
14409 } else {
14410 $initialType = $initial->getSourceType();
14411 $targetType = $target->getSourceType();
14412 }
14413
14414
14415  if ($target->isDev() && 'dist' === $installationSource) {
14416 $downloader->remove($initial, $targetDir);
14417 $this->download($target, $targetDir);
14418
14419 return;
14420 }
14421
14422 if ($initialType === $targetType) {
14423 $target->setInstallationSource($installationSource);
14424 try {
14425 $downloader->update($initial, $target, $targetDir);
14426
14427 return;
14428 } catch (\RuntimeException $e) {
14429 if (!$this->io->isInteractive()) {
14430 throw $e;
14431 }
14432 $this->io->writeError('<error>    Update failed ('.$e->getMessage().')</error>');
14433 if (!$this->io->askConfirmation('    Would you like to try reinstalling the package instead [<comment>yes</comment>]? ', true)) {
14434 throw $e;
14435 }
14436 }
14437 }
14438
14439 $downloader->remove($initial, $targetDir);
14440 $this->download($target, $targetDir, 'source' === $installationSource);
14441 }
14442
14443
14444
14445
14446
14447
14448
14449 public function remove(PackageInterface $package, $targetDir)
14450 {
14451 $downloader = $this->getDownloaderForInstalledPackage($package);
14452 if ($downloader) {
14453 $downloader->remove($package, $targetDir);
14454 }
14455 }
14456
14457
14458
14459
14460
14461
14462
14463
14464 protected function resolvePackageInstallPreference(PackageInterface $package)
14465 {
14466 foreach ($this->packagePreferences as $pattern => $preference) {
14467 $pattern = '{^'.str_replace('\\*', '.*', preg_quote($pattern)).'$}i';
14468 if (preg_match($pattern, $package->getName())) {
14469 if ('dist' === $preference || (!$package->isDev() && 'auto' === $preference)) {
14470 return 'dist';
14471 }
14472
14473 return 'source';
14474 }
14475 }
14476
14477 return $package->isDev() ? 'source' : 'dist';
14478 }
14479 }
14480 <?php
14481
14482
14483
14484
14485
14486
14487
14488
14489
14490
14491
14492 namespace Composer\Downloader;
14493
14494 use Composer\Package\PackageInterface;
14495
14496
14497
14498
14499
14500
14501
14502 interface DownloaderInterface
14503 {
14504
14505
14506
14507
14508
14509 public function getInstallationSource();
14510
14511
14512
14513
14514
14515
14516
14517 public function download(PackageInterface $package, $path);
14518
14519
14520
14521
14522
14523
14524
14525
14526 public function update(PackageInterface $initial, PackageInterface $target, $path);
14527
14528
14529
14530
14531
14532
14533
14534 public function remove(PackageInterface $package, $path);
14535
14536
14537
14538
14539
14540
14541
14542 public function setOutputProgress($outputProgress);
14543 }
14544 <?php
14545
14546
14547
14548
14549
14550
14551
14552
14553
14554
14555
14556 namespace Composer\Downloader;
14557
14558 use Composer\Package\PackageInterface;
14559
14560
14561
14562
14563
14564
14565 interface DvcsDownloaderInterface
14566 {
14567
14568
14569
14570
14571
14572
14573
14574 public function getUnpushedChanges(PackageInterface $package, $path);
14575 }
14576 <?php
14577
14578
14579
14580
14581
14582
14583
14584
14585
14586
14587
14588 namespace Composer\Downloader;
14589
14590 use Composer\Config;
14591 use Composer\Cache;
14592 use Composer\Factory;
14593 use Composer\IO\IOInterface;
14594 use Composer\Package\PackageInterface;
14595 use Composer\Plugin\PluginEvents;
14596 use Composer\Plugin\PreFileDownloadEvent;
14597 use Composer\EventDispatcher\EventDispatcher;
14598 use Composer\Util\Filesystem;
14599 use Composer\Util\RemoteFilesystem;
14600
14601
14602
14603
14604
14605
14606
14607
14608
14609 class FileDownloader implements DownloaderInterface
14610 {
14611 protected $io;
14612 protected $config;
14613 protected $rfs;
14614 protected $filesystem;
14615 protected $cache;
14616 protected $outputProgress = true;
14617 private $lastCacheWrites = array();
14618 private $eventDispatcher;
14619
14620
14621
14622
14623
14624
14625
14626
14627
14628
14629
14630 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, RemoteFilesystem $rfs = null, Filesystem $filesystem = null)
14631 {
14632 $this->io = $io;
14633 $this->config = $config;
14634 $this->eventDispatcher = $eventDispatcher;
14635 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $config);
14636 $this->filesystem = $filesystem ?: new Filesystem();
14637 $this->cache = $cache;
14638
14639 if ($this->cache && $this->cache->gcIsNecessary()) {
14640 $this->cache->gc($config->get('cache-files-ttl'), $config->get('cache-files-maxsize'));
14641 }
14642 }
14643
14644
14645
14646
14647 public function getInstallationSource()
14648 {
14649 return 'dist';
14650 }
14651
14652
14653
14654
14655 public function download(PackageInterface $package, $path, $output = true)
14656 {
14657 if (!$package->getDistUrl()) {
14658 throw new \InvalidArgumentException('The given package is missing url information');
14659 }
14660
14661 if ($output) {
14662 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>): ", false);
14663 }
14664
14665 $urls = $package->getDistUrls();
14666 while ($url = array_shift($urls)) {
14667 try {
14668 $fileName = $this->doDownload($package, $path, $url);
14669 break;
14670 } catch (\Exception $e) {
14671 if ($this->io->isDebug()) {
14672 $this->io->writeError('');
14673 $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getCode().': '.$e->getMessage());
14674 } elseif (count($urls)) {
14675 $this->io->writeError('');
14676 $this->io->writeError(' Failed, trying the next URL ('.$e->getCode().': '.$e->getMessage().')', false);
14677 }
14678
14679 if (!count($urls)) {
14680 throw $e;
14681 }
14682 }
14683 }
14684
14685 if ($output) {
14686 $this->io->writeError('');
14687 }
14688
14689 return $fileName;
14690 }
14691
14692 protected function doDownload(PackageInterface $package, $path, $url)
14693 {
14694 $this->filesystem->emptyDirectory($path);
14695
14696 $fileName = $this->getFileName($package, $path);
14697
14698 $processedUrl = $this->processUrl($package, $url);
14699 $hostname = parse_url($processedUrl, PHP_URL_HOST);
14700
14701 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $processedUrl);
14702 if ($this->eventDispatcher) {
14703 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
14704 }
14705 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
14706
14707 try {
14708 $checksum = $package->getDistSha1Checksum();
14709 $cacheKey = $this->getCacheKey($package, $processedUrl);
14710
14711
14712  if (!$this->cache || ($checksum && $checksum !== $this->cache->sha1($cacheKey)) || !$this->cache->copyTo($cacheKey, $fileName)) {
14713 if (!$this->outputProgress) {
14714 $this->io->writeError('Downloading', false);
14715 }
14716
14717
14718  $retries = 3;
14719 while ($retries--) {
14720 try {
14721 $rfs->copy($hostname, $processedUrl, $fileName, $this->outputProgress, $package->getTransportOptions());
14722 break;
14723 } catch (TransportException $e) {
14724
14725  if ((0 !== $e->getCode() && !in_array($e->getCode(), array(500, 502, 503, 504))) || !$retries) {
14726 throw $e;
14727 }
14728 $this->io->writeError('');
14729 $this->io->writeError('    Download failed, retrying...', true, IOInterface::VERBOSE);
14730 usleep(500000);
14731 }
14732 }
14733
14734 if (!$this->outputProgress) {
14735 $this->io->writeError(' (<comment>100%</comment>)', false);
14736 }
14737
14738 if ($this->cache) {
14739 $this->lastCacheWrites[$package->getName()] = $cacheKey;
14740 $this->cache->copyFrom($cacheKey, $fileName);
14741 }
14742 } else {
14743 $this->io->writeError('Loading from cache', false);
14744 }
14745
14746 if (!file_exists($fileName)) {
14747 throw new \UnexpectedValueException($url.' could not be saved to '.$fileName.', make sure the'
14748 .' directory is writable and you have internet connectivity');
14749 }
14750
14751 if ($checksum && hash_file('sha1', $fileName) !== $checksum) {
14752 throw new \UnexpectedValueException('The checksum verification of the file failed (downloaded from '.$url.')');
14753 }
14754 } catch (\Exception $e) {
14755
14756  $this->filesystem->removeDirectory($path);
14757 $this->clearLastCacheWrite($package);
14758 throw $e;
14759 }
14760
14761 return $fileName;
14762 }
14763
14764
14765
14766
14767 public function setOutputProgress($outputProgress)
14768 {
14769 $this->outputProgress = $outputProgress;
14770
14771 return $this;
14772 }
14773
14774 protected function clearLastCacheWrite(PackageInterface $package)
14775 {
14776 if ($this->cache && isset($this->lastCacheWrites[$package->getName()])) {
14777 $this->cache->remove($this->lastCacheWrites[$package->getName()]);
14778 unset($this->lastCacheWrites[$package->getName()]);
14779 }
14780 }
14781
14782
14783
14784
14785 public function update(PackageInterface $initial, PackageInterface $target, $path)
14786 {
14787 $name = $target->getName();
14788 $from = $initial->getPrettyVersion();
14789 $to = $target->getPrettyVersion();
14790
14791 $this->io->writeError("  - Updating <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>): ", false);
14792
14793 $this->remove($initial, $path, false);
14794 $this->download($target, $path, false);
14795
14796 $this->io->writeError('');
14797 }
14798
14799
14800
14801
14802 public function remove(PackageInterface $package, $path, $output = true)
14803 {
14804 if ($output) {
14805 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
14806 }
14807 if (!$this->filesystem->removeDirectory($path)) {
14808 throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
14809 }
14810 }
14811
14812
14813
14814
14815
14816
14817
14818
14819 protected function getFileName(PackageInterface $package, $path)
14820 {
14821 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
14822 }
14823
14824
14825
14826
14827
14828
14829
14830
14831
14832 protected function processUrl(PackageInterface $package, $url)
14833 {
14834 if (!extension_loaded('openssl') && 0 === strpos($url, 'https:')) {
14835 throw new \RuntimeException('You must enable the openssl extension to download files via https');
14836 }
14837
14838 return $url;
14839 }
14840
14841 private function getCacheKey(PackageInterface $package, $processedUrl)
14842 {
14843
14844  
14845  
14846  
14847  $cacheKey = sha1($processedUrl);
14848
14849 return $package->getName().'/'.$cacheKey.'.'.$package->getDistType();
14850 }
14851 }
14852 <?php
14853
14854
14855
14856
14857
14858
14859
14860
14861
14862
14863
14864 namespace Composer\Downloader;
14865
14866
14867
14868
14869
14870
14871 class FilesystemException extends \Exception
14872 {
14873 public function __construct($message = '', $code = 0, \Exception $previous = null)
14874 {
14875 parent::__construct("Filesystem exception: \n".$message, $code, $previous);
14876 }
14877 }
14878 <?php
14879
14880
14881
14882
14883
14884
14885
14886
14887
14888
14889
14890 namespace Composer\Downloader;
14891
14892 use Composer\Package\PackageInterface;
14893 use Composer\Util\ProcessExecutor;
14894
14895
14896
14897
14898 class FossilDownloader extends VcsDownloader
14899 {
14900
14901
14902
14903 public function doDownload(PackageInterface $package, $path, $url)
14904 {
14905
14906  $this->config->prohibitUrlByConfig($url, $this->io);
14907
14908 $url = ProcessExecutor::escape($url);
14909 $ref = ProcessExecutor::escape($package->getSourceReference());
14910 $repoFile = $path . '.fossil';
14911 $this->io->writeError("Cloning ".$package->getSourceReference());
14912 $command = sprintf('fossil clone %s %s', $url, ProcessExecutor::escape($repoFile));
14913 if (0 !== $this->process->execute($command, $ignoredOutput)) {
14914 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
14915 }
14916 $command = sprintf('fossil open %s', ProcessExecutor::escape($repoFile));
14917 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
14918 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
14919 }
14920 $command = sprintf('fossil update %s', $ref);
14921 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
14922 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
14923 }
14924 }
14925
14926
14927
14928
14929 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
14930 {
14931
14932  $this->config->prohibitUrlByConfig($url, $this->io);
14933
14934 $url = ProcessExecutor::escape($url);
14935 $ref = ProcessExecutor::escape($target->getSourceReference());
14936 $this->io->writeError(" Updating to ".$target->getSourceReference());
14937
14938 if (!$this->hasMetadataRepository($path)) {
14939 throw new \RuntimeException('The .fslckout file is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
14940 }
14941
14942 $command = sprintf('fossil pull && fossil up %s', $ref);
14943 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
14944 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
14945 }
14946 }
14947
14948
14949
14950
14951 public function getLocalChanges(PackageInterface $package, $path)
14952 {
14953 if (!$this->hasMetadataRepository($path)) {
14954 return null;
14955 }
14956
14957 $this->process->execute('fossil changes', $output, realpath($path));
14958
14959 return trim($output) ?: null;
14960 }
14961
14962
14963
14964
14965 protected function getCommitLogs($fromReference, $toReference, $path)
14966 {
14967 $command = sprintf('fossil timeline -t ci -W 0 -n 0 before %s', $toReference);
14968
14969 if (0 !== $this->process->execute($command, $output, realpath($path))) {
14970 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
14971 }
14972
14973 $log = '';
14974 $match = '/\d\d:\d\d:\d\d\s+\[' . $toReference . '\]/';
14975
14976 foreach ($this->process->splitLines($output) as $line) {
14977 if (preg_match($match, $line)) {
14978 break;
14979 }
14980 $log .= $line;
14981 }
14982
14983 return $log;
14984 }
14985
14986
14987
14988
14989 protected function hasMetadataRepository($path)
14990 {
14991 return is_file($path . '/.fslckout') || is_file($path . '/_FOSSIL_');
14992 }
14993 }
14994 <?php
14995
14996
14997
14998
14999
15000
15001
15002
15003
15004
15005
15006 namespace Composer\Downloader;
15007
15008 use Composer\Package\PackageInterface;
15009 use Composer\Util\Git as GitUtil;
15010 use Composer\Util\Platform;
15011 use Composer\Util\ProcessExecutor;
15012 use Composer\IO\IOInterface;
15013 use Composer\Util\Filesystem;
15014 use Composer\Config;
15015
15016
15017
15018
15019 class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface
15020 {
15021 private $hasStashedChanges = false;
15022 private $hasDiscardedChanges = false;
15023 private $gitUtil;
15024
15025 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
15026 {
15027 parent::__construct($io, $config, $process, $fs);
15028 $this->gitUtil = new GitUtil($this->io, $this->config, $this->process, $this->filesystem);
15029 }
15030
15031
15032
15033
15034 public function doDownload(PackageInterface $package, $path, $url)
15035 {
15036 GitUtil::cleanEnv();
15037 $path = $this->normalizePath($path);
15038 $cachePath = $this->config->get('cache-vcs-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $url).'/';
15039 $cacheOptions = '';
15040 $ref = $package->getSourceReference();
15041 $flag = Platform::isWindows() ? '/D ' : '';
15042
15043
15044  $gitVersion = $this->gitUtil->getVersion();
15045 $msg = "Cloning ".$this->getShortHash($ref);
15046 if ($gitVersion && version_compare($gitVersion, '2.3.0-rc0', '>=')) {
15047 $this->io->writeError('', true, IOInterface::DEBUG);
15048 $this->io->writeError(sprintf('    Cloning to cache at %s', ProcessExecutor::escape($cachePath)), true, IOInterface::DEBUG);
15049 try {
15050 $this->gitUtil->syncMirror($url, $cachePath);
15051 if (is_dir($cachePath)) {
15052 $cacheOptions = sprintf('--dissociate --reference %s ', ProcessExecutor::escape($cachePath));
15053 $msg = "Cloning ".$this->getShortHash($ref).' from cache';
15054 }
15055 } catch (\RuntimeException $e) {
15056 }
15057 }
15058 $command = 'git clone --no-checkout %s %s '.$cacheOptions.'&& cd '.$flag.'%2$s && git remote add composer %1$s && git fetch composer';
15059 $this->io->writeError($msg);
15060
15061 $commandCallable = function ($url) use ($ref, $path, $command) {
15062 return sprintf($command, ProcessExecutor::escape($url), ProcessExecutor::escape($path), ProcessExecutor::escape($ref));
15063 };
15064
15065 $this->gitUtil->runCommand($commandCallable, $url, $path, true);
15066 if ($url !== $package->getSourceUrl()) {
15067 $this->updateOriginUrl($path, $package->getSourceUrl());
15068 } else {
15069 $this->setPushUrl($path, $url);
15070 }
15071
15072 if ($newRef = $this->updateToCommit($path, $ref, $package->getPrettyVersion(), $package->getReleaseDate())) {
15073 if ($package->getDistReference() === $package->getSourceReference()) {
15074 $package->setDistReference($newRef);
15075 }
15076 $package->setSourceReference($newRef);
15077 }
15078 }
15079
15080
15081
15082
15083 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
15084 {
15085 GitUtil::cleanEnv();
15086 if (!$this->hasMetadataRepository($path)) {
15087 throw new \RuntimeException('The .git directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
15088 }
15089
15090 $updateOriginUrl = false;
15091 if (
15092 0 === $this->process->execute('git remote -v', $output, $path)
15093 && preg_match('{^origin\s+(?P<url>\S+)}m', $output, $originMatch)
15094 && preg_match('{^composer\s+(?P<url>\S+)}m', $output, $composerMatch)
15095 ) {
15096 if ($originMatch['url'] === $composerMatch['url'] && $composerMatch['url'] !== $target->getSourceUrl()) {
15097 $updateOriginUrl = true;
15098 }
15099 }
15100
15101 $ref = $target->getSourceReference();
15102 $this->io->writeError(" Checking out ".$this->getShortHash($ref));
15103 $command = 'git remote set-url composer %s && git rev-parse --quiet --verify %s^{commit} || (git fetch composer && git fetch --tags composer)';
15104
15105 $commandCallable = function ($url) use ($command, $ref) {
15106 return sprintf($command, ProcessExecutor::escape($url), ProcessExecutor::escape($ref));
15107 };
15108
15109 $this->gitUtil->runCommand($commandCallable, $url, $path);
15110 if ($newRef = $this->updateToCommit($path, $ref, $target->getPrettyVersion(), $target->getReleaseDate())) {
15111 if ($target->getDistReference() === $target->getSourceReference()) {
15112 $target->setDistReference($newRef);
15113 }
15114 $target->setSourceReference($newRef);
15115 }
15116
15117 if ($updateOriginUrl) {
15118 $this->updateOriginUrl($path, $target->getSourceUrl());
15119 }
15120 }
15121
15122
15123
15124
15125 public function getLocalChanges(PackageInterface $package, $path)
15126 {
15127 GitUtil::cleanEnv();
15128 if (!$this->hasMetadataRepository($path)) {
15129 return;
15130 }
15131
15132 $command = 'git status --porcelain --untracked-files=no';
15133 if (0 !== $this->process->execute($command, $output, $path)) {
15134 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15135 }
15136
15137 return trim($output) ?: null;
15138 }
15139
15140 public function getUnpushedChanges(PackageInterface $package, $path)
15141 {
15142 GitUtil::cleanEnv();
15143 $path = $this->normalizePath($path);
15144 if (!$this->hasMetadataRepository($path)) {
15145 return;
15146 }
15147
15148 $command = 'git show-ref --head -d';
15149 if (0 !== $this->process->execute($command, $output, $path)) {
15150 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15151 }
15152
15153 $refs = trim($output);
15154 if (!preg_match('{^([a-f0-9]+) HEAD$}mi', $refs, $match)) {
15155
15156  return;
15157 }
15158
15159 $headRef = $match[1];
15160 if (!preg_match_all('{^'.$headRef.' refs/heads/(.+)$}mi', $refs, $matches)) {
15161
15162  return;
15163 }
15164
15165
15166  $branch = $matches[1][0];
15167 $unpushedChanges = null;
15168
15169
15170  for ($i = 0; $i <= 1; $i++) {
15171
15172  foreach ($matches[1] as $candidate) {
15173 if (preg_match('{^[a-f0-9]+ refs/remotes/((?:composer|origin)/'.preg_quote($candidate).')$}mi', $refs, $match)) {
15174 $branch = $candidate;
15175 $remoteBranch = $match[1];
15176 break;
15177 }
15178 }
15179
15180
15181  
15182  
15183  if (!isset($remoteBranch)) {
15184 $unpushedChanges = 'Branch ' . $branch . ' could not be found on the origin remote and appears to be unpushed';
15185 } else {
15186 $command = sprintf('git diff --name-status %s...%s --', $remoteBranch, $branch);
15187 if (0 !== $this->process->execute($command, $output, $path)) {
15188 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15189 }
15190
15191 $unpushedChanges = trim($output) ?: null;
15192 }
15193
15194
15195  
15196  if ($unpushedChanges && $i === 0) {
15197 $this->process->execute('git fetch composer && git fetch origin', $output, $path);
15198 }
15199
15200
15201  if (!$unpushedChanges) {
15202 break;
15203 }
15204 }
15205
15206 return $unpushedChanges;
15207 }
15208
15209
15210
15211
15212 protected function cleanChanges(PackageInterface $package, $path, $update)
15213 {
15214 GitUtil::cleanEnv();
15215 $path = $this->normalizePath($path);
15216
15217 $unpushed = $this->getUnpushedChanges($package, $path);
15218 if ($unpushed && ($this->io->isInteractive() || $this->config->get('discard-changes') !== true)) {
15219 throw new \RuntimeException('Source directory ' . $path . ' has unpushed changes on the current branch: '."\n".$unpushed);
15220 }
15221
15222 if (!$changes = $this->getLocalChanges($package, $path)) {
15223 return;
15224 }
15225
15226 if (!$this->io->isInteractive()) {
15227 $discardChanges = $this->config->get('discard-changes');
15228 if (true === $discardChanges) {
15229 return $this->discardChanges($path);
15230 }
15231 if ('stash' === $discardChanges) {
15232 if (!$update) {
15233 return parent::cleanChanges($package, $path, $update);
15234 }
15235
15236 return $this->stashChanges($path);
15237 }
15238
15239 return parent::cleanChanges($package, $path, $update);
15240 }
15241
15242 $changes = array_map(function ($elem) {
15243 return '    '.$elem;
15244 }, preg_split('{\s*\r?\n\s*}', $changes));
15245 $this->io->writeError('    <error>The package has modified files:</error>');
15246 $this->io->writeError(array_slice($changes, 0, 10));
15247 if (count($changes) > 10) {
15248 $this->io->writeError('    <info>' . (count($changes) - 10) . ' more files modified, choose "v" to view the full list</info>');
15249 }
15250
15251 while (true) {
15252 switch ($this->io->ask('    <info>Discard changes [y,n,v,d,'.($update ? 's,' : '').'?]?</info> ', '?')) {
15253 case 'y':
15254 $this->discardChanges($path);
15255 break 2;
15256
15257 case 's':
15258 if (!$update) {
15259 goto help;
15260 }
15261
15262 $this->stashChanges($path);
15263 break 2;
15264
15265 case 'n':
15266 throw new \RuntimeException('Update aborted');
15267
15268 case 'v':
15269 $this->io->writeError($changes);
15270 break;
15271
15272 case 'd':
15273 $this->viewDiff($path);
15274 break;
15275
15276 case '?':
15277 default:
15278 help:
15279 $this->io->writeError(array(
15280 '    y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
15281 '    n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
15282 '    v - view modified files',
15283 '    d - view local modifications (diff)',
15284 ));
15285 if ($update) {
15286 $this->io->writeError('    s - stash changes and try to reapply them after the update');
15287 }
15288 $this->io->writeError('    ? - print help');
15289 break;
15290 }
15291 }
15292 }
15293
15294
15295
15296
15297 protected function reapplyChanges($path)
15298 {
15299 $path = $this->normalizePath($path);
15300 if ($this->hasStashedChanges) {
15301 $this->hasStashedChanges = false;
15302 $this->io->writeError('    <info>Re-applying stashed changes</info>');
15303 if (0 !== $this->process->execute('git stash pop', $output, $path)) {
15304 throw new \RuntimeException("Failed to apply stashed changes:\n\n".$this->process->getErrorOutput());
15305 }
15306 }
15307
15308 $this->hasDiscardedChanges = false;
15309 }
15310
15311
15312
15313
15314
15315
15316
15317
15318
15319
15320
15321 protected function updateToCommit($path, $reference, $branch, $date)
15322 {
15323 $force = $this->hasDiscardedChanges || $this->hasStashedChanges ? '-f ' : '';
15324
15325
15326  
15327  
15328  
15329  
15330  $template = 'git checkout '.$force.'%s -- && git reset --hard %1$s --';
15331 $branch = preg_replace('{(?:^dev-|(?:\.x)?-dev$)}i', '', $branch);
15332
15333 $branches = null;
15334 if (0 === $this->process->execute('git branch -r', $output, $path)) {
15335 $branches = $output;
15336 }
15337
15338
15339  $gitRef = $reference;
15340 if (!preg_match('{^[a-f0-9]{40}$}', $reference)
15341 && $branches
15342 && preg_match('{^\s+composer/'.preg_quote($reference).'$}m', $branches)
15343 ) {
15344 $command = sprintf('git checkout '.$force.'-B %s %s -- && git reset --hard %2$s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$reference));
15345 if (0 === $this->process->execute($command, $output, $path)) {
15346 return;
15347 }
15348 }
15349
15350
15351  if (preg_match('{^[a-f0-9]{40}$}', $reference)) {
15352
15353  if (!preg_match('{^\s+composer/'.preg_quote($branch).'$}m', $branches) && preg_match('{^\s+composer/v'.preg_quote($branch).'$}m', $branches)) {
15354 $branch = 'v' . $branch;
15355 }
15356
15357 $command = sprintf('git checkout %s --', ProcessExecutor::escape($branch));
15358 $fallbackCommand = sprintf('git checkout '.$force.'-B %s %s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$branch));
15359 if (0 === $this->process->execute($command, $output, $path)
15360 || 0 === $this->process->execute($fallbackCommand, $output, $path)
15361 ) {
15362 $command = sprintf('git reset --hard %s --', ProcessExecutor::escape($reference));
15363 if (0 === $this->process->execute($command, $output, $path)) {
15364 return;
15365 }
15366 }
15367 }
15368
15369 $command = sprintf($template, ProcessExecutor::escape($gitRef));
15370 if (0 === $this->process->execute($command, $output, $path)) {
15371 return;
15372 }
15373
15374
15375  if (false !== strpos($this->process->getErrorOutput(), $reference)) {
15376 $this->io->writeError('    <warning>'.$reference.' is gone (history was rewritten?)</warning>');
15377 }
15378
15379 throw new \RuntimeException(GitUtil::sanitizeUrl('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()));
15380 }
15381
15382 protected function updateOriginUrl($path, $url)
15383 {
15384 $this->process->execute(sprintf('git remote set-url origin %s', ProcessExecutor::escape($url)), $output, $path);
15385 $this->setPushUrl($path, $url);
15386 }
15387
15388 protected function setPushUrl($path, $url)
15389 {
15390
15391  if (preg_match('{^(?:https?|git)://'.GitUtil::getGitHubDomainsRegex($this->config).'/([^/]+)/([^/]+?)(?:\.git)?$}', $url, $match)) {
15392 $protocols = $this->config->get('github-protocols');
15393 $pushUrl = 'git@'.$match[1].':'.$match[2].'/'.$match[3].'.git';
15394 if (!in_array('ssh', $protocols, true)) {
15395 $pushUrl = 'https://' . $match[1] . '/'.$match[2].'/'.$match[3].'.git';
15396 }
15397 $cmd = sprintf('git remote set-url --push origin %s', ProcessExecutor::escape($pushUrl));
15398 $this->process->execute($cmd, $ignoredOutput, $path);
15399 }
15400 }
15401
15402
15403
15404
15405 protected function getCommitLogs($fromReference, $toReference, $path)
15406 {
15407 $path = $this->normalizePath($path);
15408 $command = sprintf('git log %s..%s --pretty=format:"%%h - %%an: %%s"', $fromReference, $toReference);
15409
15410 if (0 !== $this->process->execute($command, $output, $path)) {
15411 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15412 }
15413
15414 return $output;
15415 }
15416
15417
15418
15419
15420
15421 protected function discardChanges($path)
15422 {
15423 $path = $this->normalizePath($path);
15424 if (0 !== $this->process->execute('git reset --hard', $output, $path)) {
15425 throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
15426 }
15427
15428 $this->hasDiscardedChanges = true;
15429 }
15430
15431
15432
15433
15434
15435 protected function stashChanges($path)
15436 {
15437 $path = $this->normalizePath($path);
15438 if (0 !== $this->process->execute('git stash --include-untracked', $output, $path)) {
15439 throw new \RuntimeException("Could not stash changes\n\n:".$this->process->getErrorOutput());
15440 }
15441
15442 $this->hasStashedChanges = true;
15443 }
15444
15445
15446
15447
15448
15449 protected function viewDiff($path)
15450 {
15451 $path = $this->normalizePath($path);
15452 if (0 !== $this->process->execute('git diff HEAD', $output, $path)) {
15453 throw new \RuntimeException("Could not view diff\n\n:".$this->process->getErrorOutput());
15454 }
15455
15456 $this->io->writeError($output);
15457 }
15458
15459 protected function normalizePath($path)
15460 {
15461 if (Platform::isWindows() && strlen($path) > 0) {
15462 $basePath = $path;
15463 $removed = array();
15464
15465 while (!is_dir($basePath) && $basePath !== '\\') {
15466 array_unshift($removed, basename($basePath));
15467 $basePath = dirname($basePath);
15468 }
15469
15470 if ($basePath === '\\') {
15471 return $path;
15472 }
15473
15474 $path = rtrim(realpath($basePath) . '/' . implode('/', $removed), '/');
15475 }
15476
15477 return $path;
15478 }
15479
15480
15481
15482
15483 protected function hasMetadataRepository($path)
15484 {
15485 $path = $this->normalizePath($path);
15486
15487 return is_dir($path.'/.git');
15488 }
15489
15490 protected function getShortHash($reference)
15491 {
15492 if (!$this->io->isVerbose() && preg_match('{^[0-9a-f]{40}$}', $reference)) {
15493 return substr($reference, 0, 10);
15494 }
15495
15496 return $reference;
15497 }
15498 }
15499 <?php
15500
15501
15502
15503
15504
15505
15506
15507
15508
15509
15510
15511 namespace Composer\Downloader;
15512
15513 use Composer\Config;
15514 use Composer\Cache;
15515 use Composer\EventDispatcher\EventDispatcher;
15516 use Composer\Package\PackageInterface;
15517 use Composer\Util\Platform;
15518 use Composer\Util\ProcessExecutor;
15519 use Composer\Util\RemoteFilesystem;
15520 use Composer\IO\IOInterface;
15521
15522
15523
15524
15525
15526
15527 class GzipDownloader extends ArchiveDownloader
15528 {
15529 protected $process;
15530
15531 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
15532 {
15533 $this->process = $process ?: new ProcessExecutor($io);
15534 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
15535 }
15536
15537 protected function extract($file, $path)
15538 {
15539 $targetFilepath = $path . DIRECTORY_SEPARATOR . basename(substr($file, 0, -3));
15540
15541
15542  if (!Platform::isWindows()) {
15543 $command = 'gzip -cd ' . ProcessExecutor::escape($file) . ' > ' . ProcessExecutor::escape($targetFilepath);
15544
15545 if (0 === $this->process->execute($command, $ignoredOutput)) {
15546 return;
15547 }
15548
15549 if (extension_loaded('zlib')) {
15550
15551  $this->extractUsingExt($file, $targetFilepath);
15552
15553 return;
15554 }
15555
15556 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
15557 throw new \RuntimeException($processError);
15558 }
15559
15560
15561  $this->extractUsingExt($file, $targetFilepath);
15562 }
15563
15564
15565
15566
15567 protected function getFileName(PackageInterface $package, $path)
15568 {
15569 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
15570 }
15571
15572 private function extractUsingExt($file, $targetFilepath)
15573 {
15574 $archiveFile = gzopen($file, 'rb');
15575 $targetFile = fopen($targetFilepath, 'wb');
15576 while ($string = gzread($archiveFile, 4096)) {
15577 fwrite($targetFile, $string, Platform::strlen($string));
15578 }
15579 gzclose($archiveFile);
15580 fclose($targetFile);
15581 }
15582 }
15583 <?php
15584
15585
15586
15587
15588
15589
15590
15591
15592
15593
15594
15595 namespace Composer\Downloader;
15596
15597 use Composer\Package\PackageInterface;
15598 use Composer\Util\ProcessExecutor;
15599
15600
15601
15602
15603 class HgDownloader extends VcsDownloader
15604 {
15605
15606
15607
15608 public function doDownload(PackageInterface $package, $path, $url)
15609 {
15610
15611  $this->config->prohibitUrlByConfig($url, $this->io);
15612
15613 $url = ProcessExecutor::escape($url);
15614 $ref = ProcessExecutor::escape($package->getSourceReference());
15615 $this->io->writeError("Cloning ".$package->getSourceReference());
15616 $command = sprintf('hg clone %s %s', $url, ProcessExecutor::escape($path));
15617 if (0 !== $this->process->execute($command, $ignoredOutput)) {
15618 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15619 }
15620 $command = sprintf('hg up %s', $ref);
15621 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
15622 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15623 }
15624 }
15625
15626
15627
15628
15629 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
15630 {
15631
15632  $this->config->prohibitUrlByConfig($url, $this->io);
15633
15634 $url = ProcessExecutor::escape($url);
15635 $ref = ProcessExecutor::escape($target->getSourceReference());
15636 $this->io->writeError(" Updating to ".$target->getSourceReference());
15637
15638 if (!$this->hasMetadataRepository($path)) {
15639 throw new \RuntimeException('The .hg directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
15640 }
15641
15642 $command = sprintf('hg pull %s && hg up %s', $url, $ref);
15643 if (0 !== $this->process->execute($command, $ignoredOutput, realpath($path))) {
15644 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15645 }
15646 }
15647
15648
15649
15650
15651 public function getLocalChanges(PackageInterface $package, $path)
15652 {
15653 if (!is_dir($path.'/.hg')) {
15654 return null;
15655 }
15656
15657 $this->process->execute('hg st', $output, realpath($path));
15658
15659 return trim($output) ?: null;
15660 }
15661
15662
15663
15664
15665 protected function getCommitLogs($fromReference, $toReference, $path)
15666 {
15667 $command = sprintf('hg log -r %s:%s --style compact', $fromReference, $toReference);
15668
15669 if (0 !== $this->process->execute($command, $output, realpath($path))) {
15670 throw new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
15671 }
15672
15673 return $output;
15674 }
15675
15676
15677
15678
15679 protected function hasMetadataRepository($path)
15680 {
15681 return is_dir($path . '/.hg');
15682 }
15683 }
15684 <?php
15685
15686
15687
15688
15689
15690
15691
15692
15693
15694
15695
15696 namespace Composer\Downloader;
15697
15698 use Composer\Package\Archiver\ArchivableFilesFinder;
15699 use Composer\Package\Dumper\ArrayDumper;
15700 use Composer\Package\PackageInterface;
15701 use Composer\Package\Version\VersionGuesser;
15702 use Composer\Package\Version\VersionParser;
15703 use Composer\Util\Platform;
15704 use Composer\Util\ProcessExecutor;
15705 use Composer\Util\Filesystem as ComposerFilesystem;
15706 use Symfony\Component\Filesystem\Exception\IOException;
15707 use Symfony\Component\Filesystem\Filesystem;
15708
15709
15710
15711
15712
15713
15714
15715 class PathDownloader extends FileDownloader implements VcsCapableDownloaderInterface
15716 {
15717 const STRATEGY_SYMLINK = 10;
15718 const STRATEGY_MIRROR = 20;
15719
15720
15721
15722
15723 public function download(PackageInterface $package, $path, $output = true)
15724 {
15725 $url = $package->getDistUrl();
15726 $realUrl = realpath($url);
15727 if (false === $realUrl || !file_exists($realUrl) || !is_dir($realUrl)) {
15728 throw new \RuntimeException(sprintf(
15729 'Source path "%s" is not found for package %s', $url, $package->getName()
15730 ));
15731 }
15732
15733 if (strpos(realpath($path) . DIRECTORY_SEPARATOR, $realUrl . DIRECTORY_SEPARATOR) === 0) {
15734
15735  
15736  
15737  
15738  throw new \RuntimeException(sprintf(
15739 'Package %s cannot install to "%s" inside its source at "%s"',
15740 $package->getName(), realpath($path), $realUrl
15741 ));
15742 }
15743
15744
15745  $transportOptions = $package->getTransportOptions() + array('symlink' => null);
15746
15747
15748  $currentStrategy = self::STRATEGY_SYMLINK;
15749 $allowedStrategies = array(self::STRATEGY_SYMLINK, self::STRATEGY_MIRROR);
15750
15751 $mirrorPathRepos = getenv('COMPOSER_MIRROR_PATH_REPOS');
15752 if ($mirrorPathRepos) {
15753 $currentStrategy = self::STRATEGY_MIRROR;
15754 }
15755
15756 if (true === $transportOptions['symlink']) {
15757 $currentStrategy = self::STRATEGY_SYMLINK;
15758 $allowedStrategies = array(self::STRATEGY_SYMLINK);
15759 } elseif (false === $transportOptions['symlink']) {
15760 $currentStrategy = self::STRATEGY_MIRROR;
15761 $allowedStrategies = array(self::STRATEGY_MIRROR);
15762 }
15763
15764 $fileSystem = new Filesystem();
15765 $this->filesystem->removeDirectory($path);
15766
15767 if ($output) {
15768 $this->io->writeError(sprintf(
15769 '  - Installing <info>%s</info> (<comment>%s</comment>): ',
15770 $package->getName(),
15771 $package->getFullPrettyVersion()
15772 ), false);
15773 }
15774
15775 $isFallback = false;
15776 if (self::STRATEGY_SYMLINK == $currentStrategy) {
15777 try {
15778 if (Platform::isWindows()) {
15779
15780  $this->io->writeError(sprintf('Junctioning from %s', $url), false);
15781 $this->filesystem->junction($realUrl, $path);
15782 } else {
15783 $absolutePath = $path;
15784 if (!$this->filesystem->isAbsolutePath($absolutePath)) {
15785 $absolutePath = getcwd() . DIRECTORY_SEPARATOR . $path;
15786 }
15787 $shortestPath = $this->filesystem->findShortestPath($absolutePath, $realUrl);
15788 $path = rtrim($path, "/");
15789 $this->io->writeError(sprintf('Symlinking from %s', $url), false);
15790 $fileSystem->symlink($shortestPath, $path);
15791 }
15792 } catch (IOException $e) {
15793 if (in_array(self::STRATEGY_MIRROR, $allowedStrategies)) {
15794 $this->io->writeError('');
15795 $this->io->writeError('    <error>Symlink failed, fallback to use mirroring!</error>');
15796 $currentStrategy = self::STRATEGY_MIRROR;
15797 $isFallback = true;
15798 } else {
15799 throw new \RuntimeException(sprintf('Symlink from "%s" to "%s" failed!', $realUrl, $path));
15800 }
15801 }
15802 }
15803
15804
15805  if (self::STRATEGY_MIRROR == $currentStrategy) {
15806 $fs = new ComposerFilesystem();
15807 $realUrl = $fs->normalizePath($realUrl);
15808
15809 $this->io->writeError(sprintf('%sMirroring from %s', $isFallback ? '    ' : '', $url), false);
15810 $iterator = new ArchivableFilesFinder($realUrl, array());
15811 $fileSystem->mirror($realUrl, $path, $iterator);
15812 }
15813
15814 $this->io->writeError('');
15815 }
15816
15817
15818
15819
15820 public function remove(PackageInterface $package, $path, $output = true)
15821 {
15822
15823
15824
15825
15826
15827 if (Platform::isWindows() && $this->filesystem->isJunction($path)) {
15828 if ($output) {
15829 $this->io->writeError("  - Removing junction for <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>)");
15830 }
15831 if (!$this->filesystem->removeJunction($path)) {
15832 $this->io->writeError("    <warn>Could not remove junction at " . $path . " - is another process locking it?</warn>");
15833 throw new \RuntimeException('Could not reliably remove junction for package ' . $package->getName());
15834 }
15835 } else {
15836 parent::remove($package, $path, $output);
15837 }
15838 }
15839
15840
15841
15842
15843 public function getVcsReference(PackageInterface $package, $path)
15844 {
15845 $parser = new VersionParser;
15846 $guesser = new VersionGuesser($this->config, new ProcessExecutor($this->io), $parser);
15847 $dumper = new ArrayDumper;
15848
15849 $packageConfig = $dumper->dump($package);
15850 if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
15851 return $packageVersion['commit'];
15852 }
15853 }
15854 }
15855 <?php
15856
15857
15858
15859
15860
15861
15862
15863
15864
15865
15866
15867 namespace Composer\Downloader;
15868
15869 use Composer\Util\Filesystem;
15870
15871
15872
15873
15874
15875
15876
15877
15878
15879
15880 class PearPackageExtractor
15881 {
15882 private static $rolesWithoutPackageNamePrefix = array('php', 'script', 'www');
15883
15884 private $filesystem;
15885 private $file;
15886
15887 public function __construct($file)
15888 {
15889 if (!is_file($file)) {
15890 throw new \UnexpectedValueException('PEAR package file is not found at '.$file);
15891 }
15892
15893 $this->filesystem = new Filesystem();
15894 $this->file = $file;
15895 }
15896
15897
15898
15899
15900
15901
15902
15903
15904
15905
15906 public function extractTo($target, array $roles = array('php' => '/', 'script' => '/bin'), $vars = array())
15907 {
15908 $extractionPath = $target.'/tarball';
15909
15910 try {
15911 $archive = new \PharData($this->file);
15912 $archive->extractTo($extractionPath, null, true);
15913
15914 if (!is_file($this->combine($extractionPath, '/package.xml'))) {
15915 throw new \RuntimeException('Invalid PEAR package. It must contain package.xml file.');
15916 }
15917
15918 $fileCopyActions = $this->buildCopyActions($extractionPath, $roles, $vars);
15919 $this->copyFiles($fileCopyActions, $extractionPath, $target, $roles, $vars);
15920 $this->filesystem->removeDirectory($extractionPath);
15921 } catch (\Exception $exception) {
15922 throw new \UnexpectedValueException(sprintf('Failed to extract PEAR package %s to %s. Reason: %s', $this->file, $target, $exception->getMessage()), 0, $exception);
15923 }
15924 }
15925
15926
15927
15928
15929
15930
15931
15932
15933
15934
15935 private function copyFiles($files, $source, $target, $roles, $vars)
15936 {
15937 foreach ($files as $file) {
15938 $from = $this->combine($source, $file['from']);
15939 $to = $this->combine($target, $roles[$file['role']]);
15940 $to = $this->combine($to, $file['to']);
15941 $tasks = $file['tasks'];
15942 $this->copyFile($from, $to, $tasks, $vars);
15943 }
15944 }
15945
15946 private function copyFile($from, $to, $tasks, $vars)
15947 {
15948 if (!is_file($from)) {
15949 throw new \RuntimeException('Invalid PEAR package. package.xml defines file that is not located inside tarball.');
15950 }
15951
15952 $this->filesystem->ensureDirectoryExists(dirname($to));
15953
15954 if (0 == count($tasks)) {
15955 $copied = copy($from, $to);
15956 } else {
15957 $content = file_get_contents($from);
15958 $replacements = array();
15959 foreach ($tasks as $task) {
15960 $pattern = $task['from'];
15961 $varName = $task['to'];
15962 if (isset($vars[$varName])) {
15963 if ($varName === 'php_bin' && false === strpos($to, '.bat')) {
15964 $replacements[$pattern] = preg_replace('{\.bat$}', '', $vars[$varName]);
15965 } else {
15966 $replacements[$pattern] = $vars[$varName];
15967 }
15968 }
15969 }
15970 $content = strtr($content, $replacements);
15971
15972 $copied = file_put_contents($to, $content);
15973 }
15974
15975 if (false === $copied) {
15976 throw new \RuntimeException(sprintf('Failed to copy %s to %s', $from, $to));
15977 }
15978 }
15979
15980
15981
15982
15983
15984
15985
15986
15987
15988
15989
15990 private function buildCopyActions($source, array $roles, $vars)
15991 {
15992
15993 $package = simplexml_load_string(file_get_contents($this->combine($source, 'package.xml')));
15994 if (false === $package) {
15995 throw new \RuntimeException('Package definition file is not valid.');
15996 }
15997
15998 $packageSchemaVersion = $package['version'];
15999 if ('1.0' == $packageSchemaVersion) {
16000 $children = $package->release->filelist->children();
16001 $packageName = (string) $package->name;
16002 $packageVersion = (string) $package->release->version;
16003 $sourceDir = $packageName . '-' . $packageVersion;
16004 $result = $this->buildSourceList10($children, $roles, $sourceDir, '', null, $packageName);
16005 } elseif ('2.0' == $packageSchemaVersion || '2.1' == $packageSchemaVersion) {
16006 $children = $package->contents->children();
16007 $packageName = (string) $package->name;
16008 $packageVersion = (string) $package->version->release;
16009 $sourceDir = $packageName . '-' . $packageVersion;
16010 $result = $this->buildSourceList20($children, $roles, $sourceDir, '', null, $packageName);
16011
16012 $namespaces = $package->getNamespaces();
16013 $package->registerXPathNamespace('ns', $namespaces['']);
16014 $releaseNodes = $package->xpath('ns:phprelease');
16015 $this->applyRelease($result, $releaseNodes, $vars);
16016 } else {
16017 throw new \RuntimeException('Unsupported schema version of package definition file.');
16018 }
16019
16020 return $result;
16021 }
16022
16023 private function applyRelease(&$actions, $releaseNodes, $vars)
16024 {
16025 foreach ($releaseNodes as $releaseNode) {
16026 $requiredOs = $releaseNode->installconditions && $releaseNode->installconditions->os && $releaseNode->installconditions->os->name ? (string) $releaseNode->installconditions->os->name : '';
16027 if ($requiredOs && $vars['os'] != $requiredOs) {
16028 continue;
16029 }
16030
16031 if ($releaseNode->filelist) {
16032 foreach ($releaseNode->filelist->children() as $action) {
16033 if ('install' == $action->getName()) {
16034 $name = (string) $action['name'];
16035 $as = (string) $action['as'];
16036 if (isset($actions[$name])) {
16037 $actions[$name]['to'] = $as;
16038 }
16039 } elseif ('ignore' == $action->getName()) {
16040 $name = (string) $action['name'];
16041 unset($actions[$name]);
16042 } else {
16043
16044  }
16045 }
16046 }
16047 break;
16048 }
16049 }
16050
16051 private function buildSourceList10($children, $targetRoles, $source, $target, $role, $packageName)
16052 {
16053 $result = array();
16054
16055
16056  foreach ($children as $child) {
16057
16058 if ($child->getName() == 'dir') {
16059 $dirSource = $this->combine($source, (string) $child['name']);
16060 $dirTarget = $child['baseinstalldir'] ?: $target;
16061 $dirRole = $child['role'] ?: $role;
16062 $dirFiles = $this->buildSourceList10($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
16063 $result = array_merge($result, $dirFiles);
16064 } elseif ($child->getName() == 'file') {
16065 $fileRole = (string) $child['role'] ?: $role;
16066 if (isset($targetRoles[$fileRole])) {
16067 $fileName = (string) ($child['name'] ?: $child[0]); 
16068  $fileSource = $this->combine($source, $fileName);
16069 $fileTarget = $this->combine((string) $child['baseinstalldir'] ?: $target, $fileName);
16070 if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
16071 $fileTarget = $packageName . '/' . $fileTarget;
16072 }
16073 $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => array());
16074 }
16075 }
16076 }
16077
16078 return $result;
16079 }
16080
16081 private function buildSourceList20($children, $targetRoles, $source, $target, $role, $packageName)
16082 {
16083 $result = array();
16084
16085
16086  foreach ($children as $child) {
16087
16088 if ('dir' == $child->getName()) {
16089 $dirSource = $this->combine($source, $child['name']);
16090 $dirTarget = $child['baseinstalldir'] ?: $target;
16091 $dirRole = $child['role'] ?: $role;
16092 $dirFiles = $this->buildSourceList20($child->children(), $targetRoles, $dirSource, $dirTarget, $dirRole, $packageName);
16093 $result = array_merge($result, $dirFiles);
16094 } elseif ('file' == $child->getName()) {
16095 $fileRole = (string) $child['role'] ?: $role;
16096 if (isset($targetRoles[$fileRole])) {
16097 $fileSource = $this->combine($source, (string) $child['name']);
16098 $fileTarget = $this->combine((string) ($child['baseinstalldir'] ?: $target), (string) $child['name']);
16099 $fileTasks = array();
16100 foreach ($child->children('http://pear.php.net/dtd/tasks-1.0') as $taskNode) {
16101 if ('replace' == $taskNode->getName()) {
16102 $fileTasks[] = array('from' => (string) $taskNode->attributes()->from, 'to' => (string) $taskNode->attributes()->to);
16103 }
16104 }
16105 if (!in_array($fileRole, self::$rolesWithoutPackageNamePrefix)) {
16106 $fileTarget = $packageName . '/' . $fileTarget;
16107 }
16108 $result[(string) $child['name']] = array('from' => $fileSource, 'to' => $fileTarget, 'role' => $fileRole, 'tasks' => $fileTasks);
16109 }
16110 }
16111 }
16112
16113 return $result;
16114 }
16115
16116 private function combine($left, $right)
16117 {
16118 return rtrim($left, '/') . '/' . ltrim($right, '/');
16119 }
16120 }
16121 <?php
16122
16123
16124
16125
16126
16127
16128
16129
16130
16131
16132
16133 namespace Composer\Downloader;
16134
16135 use Composer\Package\PackageInterface;
16136 use Composer\Repository\VcsRepository;
16137 use Composer\Util\Perforce;
16138
16139
16140
16141
16142 class PerforceDownloader extends VcsDownloader
16143 {
16144
16145 protected $perforce;
16146
16147
16148
16149
16150 public function doDownload(PackageInterface $package, $path, $url)
16151 {
16152 $ref = $package->getSourceReference();
16153 $label = $this->getLabelFromSourceReference($ref);
16154
16155 $this->io->writeError('Cloning ' . $ref);
16156 $this->initPerforce($package, $path, $url);
16157 $this->perforce->setStream($ref);
16158 $this->perforce->p4Login();
16159 $this->perforce->writeP4ClientSpec();
16160 $this->perforce->connectClient();
16161 $this->perforce->syncCodeBase($label);
16162 $this->perforce->cleanupClientSpec();
16163 }
16164
16165 private function getLabelFromSourceReference($ref)
16166 {
16167 $pos = strpos($ref, '@');
16168 if (false !== $pos) {
16169 return substr($ref, $pos + 1);
16170 }
16171
16172 return null;
16173 }
16174
16175 public function initPerforce(PackageInterface $package, $path, $url)
16176 {
16177 if (!empty($this->perforce)) {
16178 $this->perforce->initializePath($path);
16179
16180 return;
16181 }
16182
16183 $repository = $package->getRepository();
16184 $repoConfig = null;
16185 if ($repository instanceof VcsRepository) {
16186 $repoConfig = $this->getRepoConfig($repository);
16187 }
16188 $this->perforce = Perforce::create($repoConfig, $url, $path, $this->process, $this->io);
16189 }
16190
16191 private function getRepoConfig(VcsRepository $repository)
16192 {
16193 return $repository->getRepoConfig();
16194 }
16195
16196
16197
16198
16199 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
16200 {
16201 $this->doDownload($target, $path, $url);
16202 }
16203
16204
16205
16206
16207 public function getLocalChanges(PackageInterface $package, $path)
16208 {
16209 $this->io->writeError('Perforce driver does not check for local changes before overriding', true);
16210
16211 return;
16212 }
16213
16214
16215
16216
16217 protected function getCommitLogs($fromReference, $toReference, $path)
16218 {
16219 $commitLogs = $this->perforce->getCommitLogs($fromReference, $toReference);
16220
16221 return $commitLogs;
16222 }
16223
16224 public function setPerforce($perforce)
16225 {
16226 $this->perforce = $perforce;
16227 }
16228
16229
16230
16231
16232 protected function hasMetadataRepository($path)
16233 {
16234 return true;
16235 }
16236 }
16237 <?php
16238
16239
16240
16241
16242
16243
16244
16245
16246
16247
16248
16249 namespace Composer\Downloader;
16250
16251
16252
16253
16254
16255
16256 class PharDownloader extends ArchiveDownloader
16257 {
16258
16259
16260
16261 protected function extract($file, $path)
16262 {
16263
16264  $archive = new \Phar($file);
16265 $archive->extractTo($path, null, true);
16266
16267
16268
16269
16270
16271 }
16272 }
16273 <?php
16274
16275
16276
16277
16278
16279
16280
16281
16282
16283
16284
16285 namespace Composer\Downloader;
16286
16287 use Composer\Config;
16288 use Composer\Cache;
16289 use Composer\EventDispatcher\EventDispatcher;
16290 use Composer\Util\IniHelper;
16291 use Composer\Util\Platform;
16292 use Composer\Util\ProcessExecutor;
16293 use Composer\Util\RemoteFilesystem;
16294 use Composer\IO\IOInterface;
16295 use RarArchive;
16296
16297
16298
16299
16300
16301
16302
16303
16304 class RarDownloader extends ArchiveDownloader
16305 {
16306 protected $process;
16307
16308 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
16309 {
16310 $this->process = $process ?: new ProcessExecutor($io);
16311 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
16312 }
16313
16314 protected function extract($file, $path)
16315 {
16316 $processError = null;
16317
16318
16319  if (!Platform::isWindows()) {
16320 $command = 'unrar x ' . ProcessExecutor::escape($file) . ' ' . ProcessExecutor::escape($path) . ' >/dev/null && chmod -R u+w ' . ProcessExecutor::escape($path);
16321
16322 if (0 === $this->process->execute($command, $ignoredOutput)) {
16323 return;
16324 }
16325
16326 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
16327 }
16328
16329 if (!class_exists('RarArchive')) {
16330
16331  $iniMessage = IniHelper::getMessage();
16332
16333 $error = "Could not decompress the archive, enable the PHP rar extension or install unrar.\n"
16334 . $iniMessage . "\n" . $processError;
16335
16336 if (!Platform::isWindows()) {
16337 $error = "Could not decompress the archive, enable the PHP rar extension.\n" . $iniMessage;
16338 }
16339
16340 throw new \RuntimeException($error);
16341 }
16342
16343 $rarArchive = RarArchive::open($file);
16344
16345 if (false === $rarArchive) {
16346 throw new \UnexpectedValueException('Could not open RAR archive: ' . $file);
16347 }
16348
16349 $entries = $rarArchive->getEntries();
16350
16351 if (false === $entries) {
16352 throw new \RuntimeException('Could not retrieve RAR archive entries');
16353 }
16354
16355 foreach ($entries as $entry) {
16356 if (false === $entry->extract($path)) {
16357 throw new \RuntimeException('Could not extract entry');
16358 }
16359 }
16360
16361 $rarArchive->close();
16362 }
16363 }
16364 <?php
16365
16366
16367
16368
16369
16370
16371
16372
16373
16374
16375
16376 namespace Composer\Downloader;
16377
16378 use Composer\Package\PackageInterface;
16379 use Composer\Util\Svn as SvnUtil;
16380 use Composer\Repository\VcsRepository;
16381
16382
16383
16384
16385
16386 class SvnDownloader extends VcsDownloader
16387 {
16388 protected $cacheCredentials = true;
16389
16390
16391
16392
16393 public function doDownload(PackageInterface $package, $path, $url)
16394 {
16395 SvnUtil::cleanEnv();
16396 $ref = $package->getSourceReference();
16397
16398 $repo = $package->getRepository();
16399 if ($repo instanceof VcsRepository) {
16400 $repoConfig = $repo->getRepoConfig();
16401 if (array_key_exists('svn-cache-credentials', $repoConfig)) {
16402 $this->cacheCredentials = (bool) $repoConfig['svn-cache-credentials'];
16403 }
16404 }
16405
16406 $this->io->writeError(" Checking out ".$package->getSourceReference());
16407 $this->execute($url, "svn co", sprintf("%s/%s", $url, $ref), null, $path);
16408 }
16409
16410
16411
16412
16413 public function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url)
16414 {
16415 SvnUtil::cleanEnv();
16416 $ref = $target->getSourceReference();
16417
16418 if (!$this->hasMetadataRepository($path)) {
16419 throw new \RuntimeException('The .svn directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information');
16420 }
16421
16422 $flags = "";
16423 if (0 === $this->process->execute('svn --version', $output)) {
16424 if (preg_match('{(\d+(?:\.\d+)+)}', $output, $match) && version_compare($match[1], '1.7.0', '>=')) {
16425 $flags .= ' --ignore-ancestry';
16426 }
16427 }
16428
16429 $this->io->writeError(" Checking out " . $ref);
16430 $this->execute($url, "svn switch" . $flags, sprintf("%s/%s", $url, $ref), $path);
16431 }
16432
16433
16434
16435
16436 public function getLocalChanges(PackageInterface $package, $path)
16437 {
16438 if (!$this->hasMetadataRepository($path)) {
16439 return null;
16440 }
16441
16442 $this->process->execute('svn status --ignore-externals', $output, $path);
16443
16444 return preg_match('{^ *[^X ] +}m', $output) ? $output : null;
16445 }
16446
16447
16448
16449
16450
16451
16452
16453
16454
16455
16456
16457
16458
16459 protected function execute($baseUrl, $command, $url, $cwd = null, $path = null)
16460 {
16461 $util = new SvnUtil($baseUrl, $this->io, $this->config);
16462 $util->setCacheCredentials($this->cacheCredentials);
16463 try {
16464 return $util->execute($command, $url, $cwd, $path, $this->io->isVerbose());
16465 } catch (\RuntimeException $e) {
16466 throw new \RuntimeException(
16467 'Package could not be downloaded, '.$e->getMessage()
16468 );
16469 }
16470 }
16471
16472
16473
16474
16475 protected function cleanChanges(PackageInterface $package, $path, $update)
16476 {
16477 if (!$changes = $this->getLocalChanges($package, $path)) {
16478 return;
16479 }
16480
16481 if (!$this->io->isInteractive()) {
16482 if (true === $this->config->get('discard-changes')) {
16483 return $this->discardChanges($path);
16484 }
16485
16486 return parent::cleanChanges($package, $path, $update);
16487 }
16488
16489 $changes = array_map(function ($elem) {
16490 return '    '.$elem;
16491 }, preg_split('{\s*\r?\n\s*}', $changes));
16492 $this->io->writeError('    <error>The package has modified files:</error>');
16493 $this->io->writeError(array_slice($changes, 0, 10));
16494 if (count($changes) > 10) {
16495 $this->io->writeError('    <info>'.count($changes) - 10 . ' more files modified, choose "v" to view the full list</info>');
16496 }
16497
16498 while (true) {
16499 switch ($this->io->ask('    <info>Discard changes [y,n,v,?]?</info> ', '?')) {
16500 case 'y':
16501 $this->discardChanges($path);
16502 break 2;
16503
16504 case 'n':
16505 throw new \RuntimeException('Update aborted');
16506
16507 case 'v':
16508 $this->io->writeError($changes);
16509 break;
16510
16511 case '?':
16512 default:
16513 $this->io->writeError(array(
16514 '    y - discard changes and apply the '.($update ? 'update' : 'uninstall'),
16515 '    n - abort the '.($update ? 'update' : 'uninstall').' and let you manually clean things up',
16516 '    v - view modified files',
16517 '    ? - print help',
16518 ));
16519 break;
16520 }
16521 }
16522 }
16523
16524
16525
16526
16527 protected function getCommitLogs($fromReference, $toReference, $path)
16528 {
16529 if (preg_match('{.*@(\d+)$}', $fromReference) && preg_match('{.*@(\d+)$}', $toReference)) {
16530
16531  $fromRevision = preg_replace('{.*@(\d+)$}', '$1', $fromReference);
16532 $toRevision = preg_replace('{.*@(\d+)$}', '$1', $toReference);
16533
16534 $command = sprintf('svn log -r%s:%s --incremental', $fromRevision, $toRevision);
16535
16536 if (0 !== $this->process->execute($command, $output, $path)) {
16537 throw new \RuntimeException(
16538 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput()
16539 );
16540 }
16541 } else {
16542 $output = "Could not retrieve changes between $fromReference and $toReference due to missing revision information";
16543 }
16544
16545 return $output;
16546 }
16547
16548 protected function discardChanges($path)
16549 {
16550 if (0 !== $this->process->execute('svn revert -R .', $output, $path)) {
16551 throw new \RuntimeException("Could not reset changes\n\n:".$this->process->getErrorOutput());
16552 }
16553 }
16554
16555
16556
16557
16558 protected function hasMetadataRepository($path)
16559 {
16560 return is_dir($path.'/.svn');
16561 }
16562 }
16563 <?php
16564
16565
16566
16567
16568
16569
16570
16571
16572
16573
16574
16575 namespace Composer\Downloader;
16576
16577
16578
16579
16580
16581
16582 class TarDownloader extends ArchiveDownloader
16583 {
16584
16585
16586
16587 protected function extract($file, $path)
16588 {
16589
16590  $archive = new \PharData($file);
16591 $archive->extractTo($path, null, true);
16592 }
16593 }
16594 <?php
16595
16596
16597
16598
16599
16600
16601
16602
16603
16604
16605
16606 namespace Composer\Downloader;
16607
16608
16609
16610
16611 class TransportException extends \RuntimeException
16612 {
16613 protected $headers;
16614 protected $response;
16615 protected $statusCode;
16616
16617 public function setHeaders($headers)
16618 {
16619 $this->headers = $headers;
16620 }
16621
16622 public function getHeaders()
16623 {
16624 return $this->headers;
16625 }
16626
16627 public function setResponse($response)
16628 {
16629 $this->response = $response;
16630 }
16631
16632 public function getResponse()
16633 {
16634 return $this->response;
16635 }
16636
16637 public function setStatusCode($statusCode)
16638 {
16639 $this->statusCode = $statusCode;
16640 }
16641
16642 public function getStatusCode()
16643 {
16644 return $this->statusCode;
16645 }
16646 }
16647 <?php
16648
16649
16650
16651
16652
16653
16654
16655
16656
16657
16658
16659 namespace Composer\Downloader;
16660
16661 use Composer\Package\PackageInterface;
16662
16663
16664
16665
16666
16667
16668 interface VcsCapableDownloaderInterface
16669 {
16670
16671
16672
16673
16674
16675
16676
16677 public function getVcsReference(PackageInterface $package, $path);
16678 }
16679 <?php
16680
16681
16682
16683
16684
16685
16686
16687
16688
16689
16690
16691 namespace Composer\Downloader;
16692
16693 use Composer\Config;
16694 use Composer\Package\Dumper\ArrayDumper;
16695 use Composer\Package\PackageInterface;
16696 use Composer\Package\Version\VersionGuesser;
16697 use Composer\Package\Version\VersionParser;
16698 use Composer\Util\ProcessExecutor;
16699 use Composer\IO\IOInterface;
16700 use Composer\Util\Filesystem;
16701
16702
16703
16704
16705 abstract class VcsDownloader implements DownloaderInterface, ChangeReportInterface, VcsCapableDownloaderInterface
16706 {
16707
16708 protected $io;
16709
16710 protected $config;
16711
16712 protected $process;
16713
16714 protected $filesystem;
16715
16716 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, Filesystem $fs = null)
16717 {
16718 $this->io = $io;
16719 $this->config = $config;
16720 $this->process = $process ?: new ProcessExecutor($io);
16721 $this->filesystem = $fs ?: new Filesystem($this->process);
16722 }
16723
16724
16725
16726
16727 public function getInstallationSource()
16728 {
16729 return 'source';
16730 }
16731
16732
16733
16734
16735 public function download(PackageInterface $package, $path)
16736 {
16737 if (!$package->getSourceReference()) {
16738 throw new \InvalidArgumentException('Package '.$package->getPrettyName().' is missing reference information');
16739 }
16740
16741 $this->io->writeError("  - Installing <info>" . $package->getName() . "</info> (<comment>" . $package->getFullPrettyVersion() . "</comment>): ", false);
16742 $this->filesystem->emptyDirectory($path);
16743
16744 $urls = $package->getSourceUrls();
16745 while ($url = array_shift($urls)) {
16746 try {
16747 if (Filesystem::isLocalPath($url)) {
16748
16749  
16750  $needle = 'file://';
16751 $isFileProtocol = false;
16752 if (0 === strpos($url, $needle)) {
16753 $url = substr($url, strlen($needle));
16754 $isFileProtocol = true;
16755 }
16756
16757
16758  if (false !== strpos($url, '%')) {
16759 $url = rawurldecode($url);
16760 }
16761
16762 $url = realpath($url);
16763
16764 if ($isFileProtocol) {
16765 $url = $needle . $url;
16766 }
16767 }
16768 $this->doDownload($package, $path, $url);
16769 break;
16770 } catch (\Exception $e) {
16771
16772  if ($e instanceof \PHPUnit_Framework_Exception) {
16773 throw $e;
16774 }
16775 if ($this->io->isDebug()) {
16776 $this->io->writeError('Failed: ['.get_class($e).'] '.$e->getMessage());
16777 } elseif (count($urls)) {
16778 $this->io->writeError('    Failed, trying the next URL');
16779 }
16780 if (!count($urls)) {
16781 throw $e;
16782 }
16783 }
16784 }
16785 }
16786
16787
16788
16789
16790 public function update(PackageInterface $initial, PackageInterface $target, $path)
16791 {
16792 if (!$target->getSourceReference()) {
16793 throw new \InvalidArgumentException('Package '.$target->getPrettyName().' is missing reference information');
16794 }
16795
16796 $name = $target->getName();
16797 if ($initial->getPrettyVersion() == $target->getPrettyVersion()) {
16798 if ($target->getSourceType() === 'svn') {
16799 $from = $initial->getSourceReference();
16800 $to = $target->getSourceReference();
16801 } else {
16802 $from = substr($initial->getSourceReference(), 0, 7);
16803 $to = substr($target->getSourceReference(), 0, 7);
16804 }
16805 $name .= ' '.$initial->getPrettyVersion();
16806 } else {
16807 $from = $initial->getFullPrettyVersion();
16808 $to = $target->getFullPrettyVersion();
16809 }
16810
16811 $this->io->writeError("  - Updating <info>" . $name . "</info> (<comment>" . $from . "</comment> => <comment>" . $to . "</comment>): ", false);
16812
16813 $this->cleanChanges($initial, $path, true);
16814 $urls = $target->getSourceUrls();
16815
16816 $exception = null;
16817 while ($url = array_shift($urls)) {
16818 try {
16819 if (Filesystem::isLocalPath($url)) {
16820 $url = realpath($url);
16821 }
16822 $this->doUpdate($initial, $target, $path, $url);
16823
16824 $exception = null;
16825 break;
16826 } catch (\Exception $exception) {
16827
16828  if ($exception instanceof \PHPUnit_Framework_Exception) {
16829 throw $exception;
16830 }
16831 if ($this->io->isDebug()) {
16832 $this->io->writeError('Failed: ['.get_class($exception).'] '.$exception->getMessage());
16833 } elseif (count($urls)) {
16834 $this->io->writeError('    Failed, trying the next URL');
16835 }
16836 }
16837 }
16838
16839 $this->reapplyChanges($path);
16840
16841
16842  
16843  if (!$exception && $this->io->isVerbose() && $this->hasMetadataRepository($path)) {
16844 $message = 'Pulling in changes:';
16845 $logs = $this->getCommitLogs($initial->getSourceReference(), $target->getSourceReference(), $path);
16846
16847 if (!trim($logs)) {
16848 $message = 'Rolling back changes:';
16849 $logs = $this->getCommitLogs($target->getSourceReference(), $initial->getSourceReference(), $path);
16850 }
16851
16852 if (trim($logs)) {
16853 $logs = implode("\n", array_map(function ($line) {
16854 return '      ' . $line;
16855 }, explode("\n", $logs)));
16856
16857
16858  $logs = str_replace('<', '\<', $logs);
16859
16860 $this->io->writeError('    '.$message);
16861 $this->io->writeError($logs);
16862 }
16863 }
16864
16865 if (!$urls && $exception) {
16866 throw $exception;
16867 }
16868 }
16869
16870
16871
16872
16873 public function remove(PackageInterface $package, $path)
16874 {
16875 $this->io->writeError("  - Removing <info>" . $package->getName() . "</info> (<comment>" . $package->getPrettyVersion() . "</comment>)");
16876 $this->cleanChanges($package, $path, false);
16877 if (!$this->filesystem->removeDirectory($path)) {
16878 throw new \RuntimeException('Could not completely delete '.$path.', aborting.');
16879 }
16880 }
16881
16882
16883
16884
16885
16886 public function setOutputProgress($outputProgress)
16887 {
16888 return $this;
16889 }
16890
16891
16892
16893
16894 public function getVcsReference(PackageInterface $package, $path)
16895 {
16896 $parser = new VersionParser;
16897 $guesser = new VersionGuesser($this->config, $this->process, $parser);
16898 $dumper = new ArrayDumper;
16899
16900 $packageConfig = $dumper->dump($package);
16901 if ($packageVersion = $guesser->guessVersion($packageConfig, $path)) {
16902 return $packageVersion['commit'];
16903 }
16904 }
16905
16906
16907
16908
16909
16910
16911
16912
16913
16914
16915 protected function cleanChanges(PackageInterface $package, $path, $update)
16916 {
16917
16918  if (null !== $this->getLocalChanges($package, $path)) {
16919 throw new \RuntimeException('Source directory ' . $path . ' has uncommitted changes.');
16920 }
16921 }
16922
16923
16924
16925
16926
16927
16928
16929 protected function reapplyChanges($path)
16930 {
16931 }
16932
16933
16934
16935
16936
16937
16938
16939
16940 abstract protected function doDownload(PackageInterface $package, $path, $url);
16941
16942
16943
16944
16945
16946
16947
16948
16949
16950 abstract protected function doUpdate(PackageInterface $initial, PackageInterface $target, $path, $url);
16951
16952
16953
16954
16955
16956
16957
16958
16959
16960 abstract protected function getCommitLogs($fromReference, $toReference, $path);
16961
16962
16963
16964
16965
16966
16967
16968
16969 abstract protected function hasMetadataRepository($path);
16970 }
16971 <?php
16972
16973
16974
16975
16976
16977
16978
16979
16980
16981
16982
16983 namespace Composer\Downloader;
16984
16985 use Composer\Config;
16986 use Composer\Cache;
16987 use Composer\EventDispatcher\EventDispatcher;
16988 use Composer\Package\PackageInterface;
16989 use Composer\Util\ProcessExecutor;
16990 use Composer\Util\RemoteFilesystem;
16991 use Composer\IO\IOInterface;
16992
16993
16994
16995
16996
16997
16998
16999 class XzDownloader extends ArchiveDownloader
17000 {
17001 protected $process;
17002
17003 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
17004 {
17005 $this->process = $process ?: new ProcessExecutor($io);
17006
17007 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
17008 }
17009
17010 protected function extract($file, $path)
17011 {
17012 $command = 'tar -xJf ' . ProcessExecutor::escape($file) . ' -C ' . ProcessExecutor::escape($path);
17013
17014 if (0 === $this->process->execute($command, $ignoredOutput)) {
17015 return;
17016 }
17017
17018 $processError = 'Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput();
17019
17020 throw new \RuntimeException($processError);
17021 }
17022
17023
17024
17025
17026 protected function getFileName(PackageInterface $package, $path)
17027 {
17028 return $path.'/'.pathinfo(parse_url($package->getDistUrl(), PHP_URL_PATH), PATHINFO_BASENAME);
17029 }
17030 }
17031 <?php
17032
17033
17034
17035
17036
17037
17038
17039
17040
17041
17042
17043 namespace Composer\Downloader;
17044
17045 use Composer\Config;
17046 use Composer\Cache;
17047 use Composer\EventDispatcher\EventDispatcher;
17048 use Composer\Package\PackageInterface;
17049 use Composer\Util\IniHelper;
17050 use Composer\Util\Platform;
17051 use Composer\Util\ProcessExecutor;
17052 use Composer\Util\RemoteFilesystem;
17053 use Composer\IO\IOInterface;
17054 use Symfony\Component\Process\ExecutableFinder;
17055 use ZipArchive;
17056
17057
17058
17059
17060 class ZipDownloader extends ArchiveDownloader
17061 {
17062 protected static $hasSystemUnzip;
17063 private static $hasZipArchive;
17064 private static $isWindows;
17065
17066 protected $process;
17067 private $zipArchiveObject;
17068
17069 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, Cache $cache = null, ProcessExecutor $process = null, RemoteFilesystem $rfs = null)
17070 {
17071 $this->process = $process ?: new ProcessExecutor($io);
17072 parent::__construct($io, $config, $eventDispatcher, $cache, $rfs);
17073 }
17074
17075
17076
17077
17078 public function download(PackageInterface $package, $path, $output = true)
17079 {
17080 if (null === self::$hasSystemUnzip) {
17081 $finder = new ExecutableFinder;
17082 self::$hasSystemUnzip = (bool) $finder->find('unzip');
17083 }
17084
17085 if (null === self::$hasZipArchive) {
17086 self::$hasZipArchive = class_exists('ZipArchive');
17087 }
17088
17089 if (null === self::$isWindows) {
17090 self::$isWindows = Platform::isWindows();
17091 }
17092
17093 if (!self::$hasZipArchive && !self::$hasSystemUnzip) {
17094
17095  $iniMessage = IniHelper::getMessage();
17096 $error = "The zip extension and unzip command are both missing, skipping.\n" . $iniMessage;
17097
17098 throw new \RuntimeException($error);
17099 }
17100
17101 return parent::download($package, $path, $output);
17102 }
17103
17104
17105
17106
17107
17108
17109
17110
17111
17112 protected function extractWithSystemUnzip($file, $path, $isLastChance)
17113 {
17114 if (!self::$hasZipArchive) {
17115
17116  $isLastChance = true;
17117 }
17118
17119 if (!self::$hasSystemUnzip && !$isLastChance) {
17120
17121  
17122  return $this->extractWithZipArchive($file, $path, true);
17123 }
17124
17125 $processError = null;
17126
17127  $overwrite = $isLastChance ? '-o' : '';
17128
17129 $command = 'unzip -qq '.$overwrite.' '.ProcessExecutor::escape($file).' -d '.ProcessExecutor::escape($path);
17130
17131 try {
17132 if (0 === $this->process->execute($command, $ignoredOutput)) {
17133 return true;
17134 }
17135
17136 $processError = new \RuntimeException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput());
17137 } catch (\Exception $e) {
17138 $processError = $e;
17139 }
17140
17141 if ($isLastChance) {
17142 throw $processError;
17143 }
17144
17145 $this->io->writeError('    '.$processError->getMessage());
17146 $this->io->writeError('    The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems)');
17147 $this->io->writeError('    Unzip with unzip command failed, falling back to ZipArchive class');
17148
17149 return $this->extractWithZipArchive($file, $path, true);
17150 }
17151
17152
17153
17154
17155
17156
17157
17158
17159
17160 protected function extractWithZipArchive($file, $path, $isLastChance)
17161 {
17162 if (!self::$hasSystemUnzip) {
17163
17164  $isLastChance = true;
17165 }
17166
17167 if (!self::$hasZipArchive && !$isLastChance) {
17168
17169  
17170  return $this->extractWithSystemUnzip($file, $path, true);
17171 }
17172
17173 $processError = null;
17174 $zipArchive = $this->zipArchiveObject ?: new ZipArchive();
17175
17176 try {
17177 if (true === ($retval = $zipArchive->open($file))) {
17178 $extractResult = $zipArchive->extractTo($path);
17179
17180 if (true === $extractResult) {
17181 $zipArchive->close();
17182
17183 return true;
17184 }
17185
17186 $processError = new \RuntimeException(rtrim("There was an error extracting the ZIP file, it is either corrupted or using an invalid format.\n"));
17187 } else {
17188 $processError = new \UnexpectedValueException(rtrim($this->getErrorMessage($retval, $file)."\n"), $retval);
17189 }
17190 } catch (\ErrorException $e) {
17191 $processError = new \RuntimeException('The archive may contain identical file names with different capitalization (which fails on case insensitive filesystems): '.$e->getMessage(), 0, $e);
17192 } catch (\Exception $e) {
17193 $processError = $e;
17194 }
17195
17196 if ($isLastChance) {
17197 throw $processError;
17198 }
17199
17200 $this->io->writeError('    '.$processError->getMessage());
17201 $this->io->writeError('    Unzip with ZipArchive class failed, falling back to unzip command');
17202
17203 return $this->extractWithSystemUnzip($file, $path, true);
17204 }
17205
17206
17207
17208
17209
17210
17211
17212 public function extract($file, $path)
17213 {
17214
17215  if (self::$isWindows) {
17216 $this->extractWithZipArchive($file, $path, false);
17217 } else {
17218 $this->extractWithSystemUnzip($file, $path, false);
17219 }
17220 }
17221
17222
17223
17224
17225
17226
17227
17228
17229 protected function getErrorMessage($retval, $file)
17230 {
17231 switch ($retval) {
17232 case ZipArchive::ER_EXISTS:
17233 return sprintf("File '%s' already exists.", $file);
17234 case ZipArchive::ER_INCONS:
17235 return sprintf("Zip archive '%s' is inconsistent.", $file);
17236 case ZipArchive::ER_INVAL:
17237 return sprintf("Invalid argument (%s)", $file);
17238 case ZipArchive::ER_MEMORY:
17239 return sprintf("Malloc failure (%s)", $file);
17240 case ZipArchive::ER_NOENT:
17241 return sprintf("No such zip file: '%s'", $file);
17242 case ZipArchive::ER_NOZIP:
17243 return sprintf("'%s' is not a zip archive.", $file);
17244 case ZipArchive::ER_OPEN:
17245 return sprintf("Can't open zip file: %s", $file);
17246 case ZipArchive::ER_READ:
17247 return sprintf("Zip read error (%s)", $file);
17248 case ZipArchive::ER_SEEK:
17249 return sprintf("Zip seek error (%s)", $file);
17250 default:
17251 return sprintf("'%s' is not a valid zip archive, got error code: %s", $file, $retval);
17252 }
17253 }
17254 }
17255 <?php
17256
17257
17258
17259
17260
17261
17262
17263
17264
17265
17266
17267 namespace Composer\EventDispatcher;
17268
17269
17270
17271
17272
17273
17274 class Event
17275 {
17276
17277
17278
17279 protected $name;
17280
17281
17282
17283
17284 protected $args;
17285
17286
17287
17288
17289 protected $flags;
17290
17291
17292
17293
17294 private $propagationStopped = false;
17295
17296
17297
17298
17299
17300
17301
17302
17303 public function __construct($name, array $args = array(), array $flags = array())
17304 {
17305 $this->name = $name;
17306 $this->args = $args;
17307 $this->flags = $flags;
17308 }
17309
17310
17311
17312
17313
17314
17315 public function getName()
17316 {
17317 return $this->name;
17318 }
17319
17320
17321
17322
17323
17324
17325 public function getArguments()
17326 {
17327 return $this->args;
17328 }
17329
17330
17331
17332
17333
17334
17335 public function getFlags()
17336 {
17337 return $this->flags;
17338 }
17339
17340
17341
17342
17343
17344
17345 public function isPropagationStopped()
17346 {
17347 return $this->propagationStopped;
17348 }
17349
17350
17351
17352
17353 public function stopPropagation()
17354 {
17355 $this->propagationStopped = true;
17356 }
17357 }
17358 <?php
17359
17360
17361
17362
17363
17364
17365
17366
17367
17368
17369
17370 namespace Composer\EventDispatcher;
17371
17372 use Composer\DependencyResolver\PolicyInterface;
17373 use Composer\DependencyResolver\Pool;
17374 use Composer\DependencyResolver\Request;
17375 use Composer\Installer\InstallerEvent;
17376 use Composer\IO\IOInterface;
17377 use Composer\Composer;
17378 use Composer\DependencyResolver\Operation\OperationInterface;
17379 use Composer\Repository\CompositeRepository;
17380 use Composer\Script;
17381 use Composer\Installer\PackageEvent;
17382 use Composer\Installer\BinaryInstaller;
17383 use Composer\Util\ProcessExecutor;
17384 use Composer\Script\Event as ScriptEvent;
17385 use Symfony\Component\Process\PhpExecutableFinder;
17386
17387
17388
17389
17390
17391
17392
17393
17394
17395
17396
17397
17398
17399
17400 class EventDispatcher
17401 {
17402 protected $composer;
17403 protected $io;
17404 protected $loader;
17405 protected $process;
17406 protected $listeners;
17407 private $eventStack;
17408
17409
17410
17411
17412
17413
17414
17415
17416 public function __construct(Composer $composer, IOInterface $io, ProcessExecutor $process = null)
17417 {
17418 $this->composer = $composer;
17419 $this->io = $io;
17420 $this->process = $process ?: new ProcessExecutor($io);
17421 $this->eventStack = array();
17422 }
17423
17424
17425
17426
17427
17428
17429
17430
17431
17432 public function dispatch($eventName, Event $event = null)
17433 {
17434 if (null === $event) {
17435 $event = new Event($eventName);
17436 }
17437
17438 return $this->doDispatch($event);
17439 }
17440
17441
17442
17443
17444
17445
17446
17447
17448
17449
17450
17451 public function dispatchScript($eventName, $devMode = false, $additionalArgs = array(), $flags = array())
17452 {
17453 return $this->doDispatch(new Script\Event($eventName, $this->composer, $this->io, $devMode, $additionalArgs, $flags));
17454 }
17455
17456
17457
17458
17459
17460
17461
17462
17463
17464
17465
17466
17467
17468
17469
17470
17471 public function dispatchPackageEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
17472 {
17473 return $this->doDispatch(new PackageEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations, $operation));
17474 }
17475
17476
17477
17478
17479
17480
17481
17482
17483
17484
17485
17486
17487
17488
17489
17490 public function dispatchInstallerEvent($eventName, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
17491 {
17492 return $this->doDispatch(new InstallerEvent($eventName, $this->composer, $this->io, $devMode, $policy, $pool, $installedRepo, $request, $operations));
17493 }
17494
17495
17496
17497
17498
17499
17500
17501
17502
17503 protected function doDispatch(Event $event)
17504 {
17505 $pathStr = 'PATH';
17506 if (!isset($_SERVER[$pathStr]) && isset($_SERVER['Path'])) {
17507 $pathStr = 'Path';
17508 }
17509
17510
17511  $binDir = $this->composer->getConfig()->get('bin-dir');
17512 if (is_dir($binDir)) {
17513 $binDir = realpath($binDir);
17514 if (isset($_SERVER[$pathStr]) && !preg_match('{(^|'.PATH_SEPARATOR.')'.preg_quote($binDir).'($|'.PATH_SEPARATOR.')}', $_SERVER[$pathStr])) {
17515 $_SERVER[$pathStr] = $binDir.PATH_SEPARATOR.getenv($pathStr);
17516 putenv($pathStr.'='.$_SERVER[$pathStr]);
17517 }
17518 }
17519
17520 $listeners = $this->getListeners($event);
17521
17522 $this->pushEvent($event);
17523
17524 $return = 0;
17525 foreach ($listeners as $callable) {
17526 if (!is_string($callable) && is_callable($callable)) {
17527 $event = $this->checkListenerExpectedEvent($callable, $event);
17528 $return = false === call_user_func($callable, $event) ? 1 : 0;
17529 } elseif ($this->isComposerScript($callable)) {
17530 $this->io->writeError(sprintf('> %s: %s', $event->getName(), $callable), true, IOInterface::VERBOSE);
17531 $scriptName = substr($callable, 1);
17532 $args = $event->getArguments();
17533 $flags = $event->getFlags();
17534 if (substr($callable, 0, 10) === '@composer ') {
17535 $exec = $this->getPhpExecCommand() . ' ' . ProcessExecutor::escape(getenv('COMPOSER_BINARY')) . substr($callable, 9);
17536 if (0 !== ($exitCode = $this->process->execute($exec))) {
17537 $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()), true, IOInterface::QUIET);
17538
17539 throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
17540 }
17541 } else {
17542 if (!$this->getListeners(new Event($scriptName))) {
17543 $this->io->writeError(sprintf('<warning>You made a reference to a non-existent script %s</warning>', $callable), true, IOInterface::QUIET);
17544 }
17545
17546 $return = $this->dispatch($scriptName, new Script\Event($scriptName, $event->getComposer(), $event->getIO(), $event->isDevMode(), $args, $flags));
17547 }
17548 } elseif ($this->isPhpScript($callable)) {
17549 $className = substr($callable, 0, strpos($callable, '::'));
17550 $methodName = substr($callable, strpos($callable, '::') + 2);
17551
17552 if (!class_exists($className)) {
17553 $this->io->writeError('<warning>Class '.$className.' is not autoloadable, can not call '.$event->getName().' script</warning>', true, IOInterface::QUIET);
17554 continue;
17555 }
17556 if (!is_callable($callable)) {
17557 $this->io->writeError('<warning>Method '.$callable.' is not callable, can not call '.$event->getName().' script</warning>', true, IOInterface::QUIET);
17558 continue;
17559 }
17560
17561 try {
17562 $return = false === $this->executeEventPhpScript($className, $methodName, $event) ? 1 : 0;
17563 } catch (\Exception $e) {
17564 $message = "Script %s handling the %s event terminated with an exception";
17565 $this->io->writeError('<error>'.sprintf($message, $callable, $event->getName()).'</error>', true, IOInterface::QUIET);
17566 throw $e;
17567 }
17568 } else {
17569 $args = implode(' ', array_map(array('Composer\Util\ProcessExecutor', 'escape'), $event->getArguments()));
17570 $exec = $callable . ($args === '' ? '' : ' '.$args);
17571 if ($this->io->isVerbose()) {
17572 $this->io->writeError(sprintf('> %s: %s', $event->getName(), $exec));
17573 } else {
17574 $this->io->writeError(sprintf('> %s', $exec));
17575 }
17576
17577 $possibleLocalBinaries = $this->composer->getPackage()->getBinaries();
17578 if ($possibleLocalBinaries) {
17579 foreach ($possibleLocalBinaries as $localExec) {
17580 if (preg_match('{\b'.preg_quote($callable).'$}', $localExec)) {
17581 $caller = BinaryInstaller::determineBinaryCaller($localExec);
17582 $exec = preg_replace('{^'.preg_quote($callable).'}', $caller . ' ' . $localExec, $exec);
17583 break;
17584 }
17585 }
17586 }
17587
17588 if (substr($exec, 0, 5) === '@php ') {
17589 $exec = $this->getPhpExecCommand() . ' ' . substr($exec, 5);
17590 }
17591
17592 if (0 !== ($exitCode = $this->process->execute($exec))) {
17593 $this->io->writeError(sprintf('<error>Script %s handling the %s event returned with error code '.$exitCode.'</error>', $callable, $event->getName()), true, IOInterface::QUIET);
17594
17595 throw new ScriptExecutionException('Error Output: '.$this->process->getErrorOutput(), $exitCode);
17596 }
17597 }
17598
17599 if ($event->isPropagationStopped()) {
17600 break;
17601 }
17602 }
17603
17604 $this->popEvent();
17605
17606 return $return;
17607 }
17608
17609 protected function getPhpExecCommand()
17610 {
17611 $finder = new PhpExecutableFinder();
17612 $phpPath = $finder->find();
17613 if (!$phpPath) {
17614 throw new \RuntimeException('Failed to locate PHP binary to execute '.$scriptName);
17615 }
17616
17617 $allowUrlFOpenFlag = ' -d allow_url_fopen=' . ProcessExecutor::escape(ini_get('allow_url_fopen'));
17618 $disableFunctionsFlag = ' -d disable_functions=' . ProcessExecutor::escape(ini_get('disable_functions'));
17619 $memoryLimitFlag = ' -d memory_limit=' . ProcessExecutor::escape(ini_get('memory_limit'));
17620
17621 return ProcessExecutor::escape($phpPath) . $allowUrlFOpenFlag . $disableFunctionsFlag . $memoryLimitFlag;
17622 }
17623
17624
17625
17626
17627
17628
17629 protected function executeEventPhpScript($className, $methodName, Event $event)
17630 {
17631 $event = $this->checkListenerExpectedEvent(array($className, $methodName), $event);
17632
17633 if ($this->io->isVerbose()) {
17634 $this->io->writeError(sprintf('> %s: %s::%s', $event->getName(), $className, $methodName));
17635 } else {
17636 $this->io->writeError(sprintf('> %s::%s', $className, $methodName));
17637 }
17638
17639 return $className::$methodName($event);
17640 }
17641
17642
17643
17644
17645
17646
17647 protected function checkListenerExpectedEvent($target, Event $event)
17648 {
17649 if (in_array($event->getName(), array(
17650 'init',
17651 'command',
17652 'pre-file-download',
17653 ), true)) {
17654 return $event;
17655 }
17656
17657 try {
17658 $reflected = new \ReflectionParameter($target, 0);
17659 } catch (\Exception $e) {
17660 return $event;
17661 }
17662
17663 $typehint = $reflected->getClass();
17664
17665 if (!$typehint instanceof \ReflectionClass) {
17666 return $event;
17667 }
17668
17669 $expected = $typehint->getName();
17670
17671
17672  if (!$event instanceof $expected && $expected === 'Composer\Script\CommandEvent') {
17673 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);
17674 $event = new \Composer\Script\CommandEvent(
17675 $event->getName(), $event->getComposer(), $event->getIO(), $event->isDevMode(), $event->getArguments()
17676 );
17677 }
17678 if (!$event instanceof $expected && $expected === 'Composer\Script\PackageEvent') {
17679 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);
17680 $event = new \Composer\Script\PackageEvent(
17681 $event->getName(), $event->getComposer(), $event->getIO(), $event->isDevMode(),
17682 $event->getPolicy(), $event->getPool(), $event->getInstalledRepo(), $event->getRequest(),
17683 $event->getOperations(), $event->getOperation()
17684 );
17685 }
17686 if (!$event instanceof $expected && $expected === 'Composer\Script\Event') {
17687 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);
17688 $event = new \Composer\Script\Event(
17689 $event->getName(), $event->getComposer(), $event->getIO(), $event->isDevMode(),
17690 $event->getArguments(), $event->getFlags()
17691 );
17692 }
17693
17694 return $event;
17695 }
17696
17697 private function serializeCallback($cb)
17698 {
17699 if (is_array($cb) && count($cb) === 2) {
17700 if (is_object($cb[0])) {
17701 $cb[0] = get_class($cb[0]);
17702 }
17703 if (is_string($cb[0]) && is_string($cb[1])) {
17704 $cb = implode('::', $cb);
17705 }
17706 }
17707 if (is_string($cb)) {
17708 return $cb;
17709 }
17710
17711 return var_export($cb, true);
17712 }
17713
17714
17715
17716
17717
17718
17719
17720
17721 public function addListener($eventName, $listener, $priority = 0)
17722 {
17723 $this->listeners[$eventName][$priority][] = $listener;
17724 }
17725
17726
17727
17728
17729
17730
17731
17732
17733 public function addSubscriber(EventSubscriberInterface $subscriber)
17734 {
17735 foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
17736 if (is_string($params)) {
17737 $this->addListener($eventName, array($subscriber, $params));
17738 } elseif (is_string($params[0])) {
17739 $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0);
17740 } else {
17741 foreach ($params as $listener) {
17742 $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0);
17743 }
17744 }
17745 }
17746 }
17747
17748
17749
17750
17751
17752
17753
17754 protected function getListeners(Event $event)
17755 {
17756 $scriptListeners = $this->getScriptListeners($event);
17757
17758 if (!isset($this->listeners[$event->getName()][0])) {
17759 $this->listeners[$event->getName()][0] = array();
17760 }
17761 krsort($this->listeners[$event->getName()]);
17762
17763 $listeners = $this->listeners;
17764 $listeners[$event->getName()][0] = array_merge($listeners[$event->getName()][0], $scriptListeners);
17765
17766 return call_user_func_array('array_merge', $listeners[$event->getName()]);
17767 }
17768
17769
17770
17771
17772
17773
17774
17775 public function hasEventListeners(Event $event)
17776 {
17777 $listeners = $this->getListeners($event);
17778
17779 return count($listeners) > 0;
17780 }
17781
17782
17783
17784
17785
17786
17787
17788 protected function getScriptListeners(Event $event)
17789 {
17790 $package = $this->composer->getPackage();
17791 $scripts = $package->getScripts();
17792
17793 if (empty($scripts[$event->getName()])) {
17794 return array();
17795 }
17796
17797 if ($this->loader) {
17798 $this->loader->unregister();
17799 }
17800
17801 $generator = $this->composer->getAutoloadGenerator();
17802 if ($event instanceof ScriptEvent) {
17803 $generator->setDevMode($event->isDevMode());
17804 }
17805
17806 $packages = $this->composer->getRepositoryManager()->getLocalRepository()->getCanonicalPackages();
17807 $packageMap = $generator->buildPackageMap($this->composer->getInstallationManager(), $package, $packages);
17808 $map = $generator->parseAutoloads($packageMap, $package);
17809 $this->loader = $generator->createLoader($map);
17810 $this->loader->register();
17811
17812 return $scripts[$event->getName()];
17813 }
17814
17815
17816
17817
17818
17819
17820
17821 protected function isPhpScript($callable)
17822 {
17823 return false === strpos($callable, ' ') && false !== strpos($callable, '::');
17824 }
17825
17826
17827
17828
17829
17830
17831
17832 protected function isComposerScript($callable)
17833 {
17834 return '@' === substr($callable, 0, 1) && '@php ' !== substr($callable, 0, 5);
17835 }
17836
17837
17838
17839
17840
17841
17842
17843
17844 protected function pushEvent(Event $event)
17845 {
17846 $eventName = $event->getName();
17847 if (in_array($eventName, $this->eventStack)) {
17848 throw new \RuntimeException(sprintf("Circular call to script handler '%s' detected", $eventName));
17849 }
17850
17851 return array_push($this->eventStack, $eventName);
17852 }
17853
17854
17855
17856
17857
17858
17859 protected function popEvent()
17860 {
17861 return array_pop($this->eventStack);
17862 }
17863 }
17864 <?php
17865
17866
17867
17868
17869
17870
17871
17872
17873
17874
17875
17876 namespace Composer\EventDispatcher;
17877
17878
17879
17880
17881
17882
17883
17884
17885
17886
17887
17888
17889
17890 interface EventSubscriberInterface
17891 {
17892
17893
17894
17895
17896
17897
17898
17899
17900
17901
17902
17903
17904
17905
17906
17907
17908
17909
17910 public static function getSubscribedEvents();
17911 }
17912 <?php
17913
17914
17915
17916
17917
17918
17919
17920
17921
17922
17923
17924 namespace Composer\EventDispatcher;
17925
17926
17927
17928
17929 class ScriptExecutionException extends \RuntimeException
17930 {
17931 }
17932 <?php
17933
17934
17935
17936
17937
17938
17939
17940
17941
17942
17943
17944 namespace Composer\Exception;
17945
17946
17947
17948
17949 class NoSslException extends \RuntimeException
17950 {
17951 }
17952 <?php
17953
17954
17955
17956
17957
17958
17959
17960
17961
17962
17963
17964 namespace Composer;
17965
17966 use Composer\Config\JsonConfigSource;
17967 use Composer\Json\JsonFile;
17968 use Composer\IO\IOInterface;
17969 use Composer\Package\Archiver;
17970 use Composer\Package\Version\VersionGuesser;
17971 use Composer\Repository\RepositoryManager;
17972 use Composer\Repository\RepositoryFactory;
17973 use Composer\Repository\WritableRepositoryInterface;
17974 use Composer\Util\Filesystem;
17975 use Composer\Util\Platform;
17976 use Composer\Util\ProcessExecutor;
17977 use Composer\Util\RemoteFilesystem;
17978 use Composer\Util\Silencer;
17979 use Composer\Plugin\PluginEvents;
17980 use Composer\EventDispatcher\Event;
17981 use Seld\JsonLint\DuplicateKeyException;
17982 use Symfony\Component\Console\Formatter\OutputFormatter;
17983 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
17984 use Symfony\Component\Console\Output\ConsoleOutput;
17985 use Composer\EventDispatcher\EventDispatcher;
17986 use Composer\Autoload\AutoloadGenerator;
17987 use Composer\Package\Version\VersionParser;
17988 use Composer\Downloader\TransportException;
17989 use Seld\JsonLint\JsonParser;
17990
17991
17992
17993
17994
17995
17996
17997
17998
17999 class Factory
18000 {
18001
18002
18003
18004
18005 protected static function getHomeDir()
18006 {
18007 $home = getenv('COMPOSER_HOME');
18008 if ($home) {
18009 return $home;
18010 }
18011
18012 if (Platform::isWindows()) {
18013 if (!getenv('APPDATA')) {
18014 throw new \RuntimeException('The APPDATA or COMPOSER_HOME environment variable must be set for composer to run correctly');
18015 }
18016
18017 return rtrim(strtr(getenv('APPDATA'), '\\', '/'), '/') . '/Composer';
18018 }
18019
18020 $userDir = self::getUserDir();
18021 if (is_dir($userDir . '/.composer')) {
18022 return $userDir . '/.composer';
18023 }
18024
18025 if (self::useXdg()) {
18026
18027  $xdgConfig = getenv('XDG_CONFIG_HOME') ?: $userDir . '/.config';
18028
18029 return $xdgConfig . '/composer';
18030 }
18031
18032 return $userDir . '/.composer';
18033 }
18034
18035
18036
18037
18038
18039 protected static function getCacheDir($home)
18040 {
18041 $cacheDir = getenv('COMPOSER_CACHE_DIR');
18042 if ($cacheDir) {
18043 return $cacheDir;
18044 }
18045
18046 $homeEnv = getenv('COMPOSER_HOME');
18047 if ($homeEnv) {
18048 return $homeEnv . '/cache';
18049 }
18050
18051 if (Platform::isWindows()) {
18052 if ($cacheDir = getenv('LOCALAPPDATA')) {
18053 $cacheDir .= '/Composer';
18054 } else {
18055 $cacheDir = $home . '/cache';
18056 }
18057
18058 return rtrim(strtr($cacheDir, '\\', '/'), '/');
18059 }
18060
18061 $userDir = self::getUserDir();
18062 if ($home === $userDir . '/.composer' && is_dir($home . '/cache')) {
18063 return $home . '/cache';
18064 }
18065
18066 if (self::useXdg()) {
18067 $xdgCache = getenv('XDG_CACHE_HOME') ?: $userDir . '/.cache';
18068
18069 return $xdgCache . '/composer';
18070 }
18071
18072 return $home . '/cache';
18073 }
18074
18075
18076
18077
18078
18079 protected static function getDataDir($home)
18080 {
18081 $homeEnv = getenv('COMPOSER_HOME');
18082 if ($homeEnv) {
18083 return $homeEnv;
18084 }
18085
18086 if (Platform::isWindows()) {
18087 return strtr($home, '\\', '/');
18088 }
18089
18090 $userDir = self::getUserDir();
18091 if ($home !== $userDir . '/.composer' && self::useXdg()) {
18092 $xdgData = getenv('XDG_DATA_HOME') ?: $userDir . '/.local/share';
18093
18094 return $xdgData . '/composer';
18095 }
18096
18097 return $home;
18098 }
18099
18100
18101
18102
18103
18104 public static function createConfig(IOInterface $io = null, $cwd = null)
18105 {
18106 $cwd = $cwd ?: getcwd();
18107
18108 $config = new Config(true, $cwd);
18109
18110
18111  $home = self::getHomeDir();
18112 $config->merge(array('config' => array(
18113 'home' => $home,
18114 'cache-dir' => self::getCacheDir($home),
18115 'data-dir' => self::getDataDir($home),
18116 )));
18117
18118 $htaccessProtect = (bool) $config->get('htaccess-protect');
18119 if ($htaccessProtect) {
18120
18121  
18122  
18123  $dirs = array($config->get('home'), $config->get('cache-dir'), $config->get('data-dir'));
18124 foreach ($dirs as $dir) {
18125 if (!file_exists($dir . '/.htaccess')) {
18126 if (!is_dir($dir)) {
18127 Silencer::call('mkdir', $dir, 0777, true);
18128 }
18129 Silencer::call('file_put_contents', $dir . '/.htaccess', 'Deny from all');
18130 }
18131 }
18132 }
18133
18134
18135  $file = new JsonFile($config->get('home').'/config.json');
18136 if ($file->exists()) {
18137 if ($io && $io->isDebug()) {
18138 $io->writeError('Loading config file ' . $file->getPath());
18139 }
18140 $config->merge($file->read());
18141 }
18142 $config->setConfigSource(new JsonConfigSource($file));
18143
18144
18145  $file = new JsonFile($config->get('home').'/auth.json');
18146 if ($file->exists()) {
18147 if ($io && $io->isDebug()) {
18148 $io->writeError('Loading config file ' . $file->getPath());
18149 }
18150 $config->merge(array('config' => $file->read()));
18151 }
18152 $config->setAuthConfigSource(new JsonConfigSource($file, true));
18153
18154
18155  if ($composerAuthEnv = getenv('COMPOSER_AUTH')) {
18156 $authData = json_decode($composerAuthEnv, true);
18157
18158 if (is_null($authData)) {
18159 throw new \UnexpectedValueException('COMPOSER_AUTH environment variable is malformed, should be a valid JSON object');
18160 }
18161
18162 if ($io && $io->isDebug()) {
18163 $io->writeError('Loading auth config from COMPOSER_AUTH');
18164 }
18165 $config->merge(array('config' => $authData));
18166 }
18167
18168 return $config;
18169 }
18170
18171 public static function getComposerFile()
18172 {
18173 return trim(getenv('COMPOSER')) ?: './composer.json';
18174 }
18175
18176 public static function createAdditionalStyles()
18177 {
18178 return array(
18179 'highlight' => new OutputFormatterStyle('red'),
18180 'warning' => new OutputFormatterStyle('black', 'yellow'),
18181 );
18182 }
18183
18184
18185
18186
18187
18188
18189 public static function createOutput()
18190 {
18191 $styles = self::createAdditionalStyles();
18192 $formatter = new OutputFormatter(null, $styles);
18193
18194 return new ConsoleOutput(ConsoleOutput::VERBOSITY_NORMAL, null, $formatter);
18195 }
18196
18197
18198
18199
18200 public static function createDefaultRepositories(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
18201 {
18202 return RepositoryFactory::defaultRepos($io, $config, $rm);
18203 }
18204
18205
18206
18207
18208
18209
18210
18211
18212
18213
18214
18215
18216
18217 public function createComposer(IOInterface $io, $localConfig = null, $disablePlugins = false, $cwd = null, $fullLoad = true)
18218 {
18219 $cwd = $cwd ?: getcwd();
18220
18221
18222  if (null === $localConfig) {
18223 $localConfig = static::getComposerFile();
18224 }
18225
18226 if (is_string($localConfig)) {
18227 $composerFile = $localConfig;
18228
18229 $file = new JsonFile($localConfig, null, $io);
18230
18231 if (!$file->exists()) {
18232 if ($localConfig === './composer.json' || $localConfig === 'composer.json') {
18233 $message = 'Composer could not find a composer.json file in '.$cwd;
18234 } else {
18235 $message = 'Composer could not find the config file: '.$localConfig;
18236 }
18237 $instructions = 'To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section';
18238 throw new \InvalidArgumentException($message.PHP_EOL.$instructions);
18239 }
18240
18241 $file->validateSchema(JsonFile::LAX_SCHEMA);
18242 $jsonParser = new JsonParser;
18243 try {
18244 $jsonParser->parse(file_get_contents($localConfig), JsonParser::DETECT_KEY_CONFLICTS);
18245 } catch (DuplicateKeyException $e) {
18246 $details = $e->getDetails();
18247 $io->writeError('<warning>Key '.$details['key'].' is a duplicate in '.$localConfig.' at line '.$details['line'].'</warning>');
18248 }
18249
18250 $localConfig = $file->read();
18251 }
18252
18253
18254  $config = static::createConfig($io, $cwd);
18255 $config->merge($localConfig);
18256 if (isset($composerFile)) {
18257 $io->writeError('Loading config file ' . $composerFile, true, IOInterface::DEBUG);
18258 $config->setConfigSource(new JsonConfigSource(new JsonFile(realpath($composerFile), null, $io)));
18259
18260 $localAuthFile = new JsonFile(dirname(realpath($composerFile)) . '/auth.json', null, $io);
18261 if ($localAuthFile->exists()) {
18262 $io->writeError('Loading config file ' . $localAuthFile->getPath(), true, IOInterface::DEBUG);
18263 $config->merge(array('config' => $localAuthFile->read()));
18264 $config->setAuthConfigSource(new JsonConfigSource($localAuthFile, true));
18265 }
18266 }
18267
18268 $vendorDir = $config->get('vendor-dir');
18269
18270
18271  $composer = new Composer();
18272 $composer->setConfig($config);
18273
18274 if ($fullLoad) {
18275
18276  $io->loadConfiguration($config);
18277 }
18278
18279 $rfs = self::createRemoteFilesystem($io, $config);
18280
18281
18282  $dispatcher = new EventDispatcher($composer, $io);
18283 $composer->setEventDispatcher($dispatcher);
18284
18285
18286  $rm = RepositoryFactory::manager($io, $config, $dispatcher, $rfs);
18287 $composer->setRepositoryManager($rm);
18288
18289
18290  $this->addLocalRepository($io, $rm, $vendorDir);
18291
18292
18293  
18294  if (!$fullLoad && !isset($localConfig['version'])) {
18295 $localConfig['version'] = '1.0.0';
18296 }
18297
18298
18299  $parser = new VersionParser;
18300 $guesser = new VersionGuesser($config, new ProcessExecutor($io), $parser);
18301 $loader = new Package\Loader\RootPackageLoader($rm, $config, $parser, $guesser);
18302 $package = $loader->load($localConfig, 'Composer\Package\RootPackage', $cwd);
18303 $composer->setPackage($package);
18304
18305
18306  $im = $this->createInstallationManager();
18307 $composer->setInstallationManager($im);
18308
18309 if ($fullLoad) {
18310
18311  $dm = $this->createDownloadManager($io, $config, $dispatcher, $rfs);
18312 $composer->setDownloadManager($dm);
18313
18314
18315  $generator = new AutoloadGenerator($dispatcher, $io);
18316 $composer->setAutoloadGenerator($generator);
18317
18318
18319  $am = $this->createArchiveManager($config, $dm);
18320 $composer->setArchiveManager($am);
18321 }
18322
18323
18324  $this->createDefaultInstallers($im, $composer, $io);
18325
18326 if ($fullLoad) {
18327 $globalComposer = null;
18328 if (realpath($config->get('home')) !== $cwd) {
18329 $globalComposer = $this->createGlobalComposer($io, $config, $disablePlugins);
18330 }
18331
18332 $pm = $this->createPluginManager($io, $composer, $globalComposer, $disablePlugins);
18333 $composer->setPluginManager($pm);
18334
18335 $pm->loadInstalledPlugins();
18336 }
18337
18338
18339  if ($fullLoad && isset($composerFile)) {
18340 $lockFile = "json" === pathinfo($composerFile, PATHINFO_EXTENSION)
18341 ? substr($composerFile, 0, -4).'lock'
18342 : $composerFile . '.lock';
18343
18344 $locker = new Package\Locker($io, new JsonFile($lockFile, null, $io), $rm, $im, file_get_contents($composerFile));
18345 $composer->setLocker($locker);
18346 }
18347
18348 if ($fullLoad) {
18349 $initEvent = new Event(PluginEvents::INIT);
18350 $composer->getEventDispatcher()->dispatch($initEvent->getName(), $initEvent);
18351
18352
18353  
18354  if ($rm->getLocalRepository()) {
18355 $this->purgePackages($rm->getLocalRepository(), $im);
18356 }
18357 }
18358
18359 return $composer;
18360 }
18361
18362
18363
18364
18365
18366
18367 public static function createGlobal(IOInterface $io, $disablePlugins = false)
18368 {
18369 $factory = new static();
18370
18371 return $factory->createGlobalComposer($io, static::createConfig($io), $disablePlugins, true);
18372 }
18373
18374
18375
18376
18377
18378 protected function addLocalRepository(IOInterface $io, RepositoryManager $rm, $vendorDir)
18379 {
18380 $rm->setLocalRepository(new Repository\InstalledFilesystemRepository(new JsonFile($vendorDir.'/composer/installed.json', null, $io)));
18381 }
18382
18383
18384
18385
18386
18387 protected function createGlobalComposer(IOInterface $io, Config $config, $disablePlugins, $fullLoad = false)
18388 {
18389 $composer = null;
18390 try {
18391 $composer = self::createComposer($io, $config->get('home') . '/composer.json', $disablePlugins, $config->get('home'), $fullLoad);
18392 } catch (\Exception $e) {
18393 $io->writeError('Failed to initialize global composer: '.$e->getMessage(), true, IOInterface::DEBUG);
18394 }
18395
18396 return $composer;
18397 }
18398
18399
18400
18401
18402
18403
18404
18405 public function createDownloadManager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
18406 {
18407 $cache = null;
18408 if ($config->get('cache-files-ttl') > 0) {
18409 $cache = new Cache($io, $config->get('cache-files-dir'), 'a-z0-9_./');
18410 }
18411
18412 $dm = new Downloader\DownloadManager($io);
18413 switch ($preferred = $config->get('preferred-install')) {
18414 case 'dist':
18415 $dm->setPreferDist(true);
18416 break;
18417 case 'source':
18418 $dm->setPreferSource(true);
18419 break;
18420 case 'auto':
18421 default:
18422
18423  break;
18424 }
18425
18426 if (is_array($preferred)) {
18427 $dm->setPreferences($preferred);
18428 }
18429
18430 $executor = new ProcessExecutor($io);
18431 $fs = new Filesystem($executor);
18432
18433 $dm->setDownloader('git', new Downloader\GitDownloader($io, $config, $executor, $fs));
18434 $dm->setDownloader('svn', new Downloader\SvnDownloader($io, $config, $executor, $fs));
18435 $dm->setDownloader('fossil', new Downloader\FossilDownloader($io, $config, $executor, $fs));
18436 $dm->setDownloader('hg', new Downloader\HgDownloader($io, $config, $executor, $fs));
18437 $dm->setDownloader('perforce', new Downloader\PerforceDownloader($io, $config));
18438 $dm->setDownloader('zip', new Downloader\ZipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
18439 $dm->setDownloader('rar', new Downloader\RarDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
18440 $dm->setDownloader('tar', new Downloader\TarDownloader($io, $config, $eventDispatcher, $cache, $rfs));
18441 $dm->setDownloader('gzip', new Downloader\GzipDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
18442 $dm->setDownloader('xz', new Downloader\XzDownloader($io, $config, $eventDispatcher, $cache, $executor, $rfs));
18443 $dm->setDownloader('phar', new Downloader\PharDownloader($io, $config, $eventDispatcher, $cache, $rfs));
18444 $dm->setDownloader('file', new Downloader\FileDownloader($io, $config, $eventDispatcher, $cache, $rfs));
18445 $dm->setDownloader('path', new Downloader\PathDownloader($io, $config, $eventDispatcher, $cache, $rfs));
18446
18447 return $dm;
18448 }
18449
18450
18451
18452
18453
18454
18455 public function createArchiveManager(Config $config, Downloader\DownloadManager $dm = null)
18456 {
18457 if (null === $dm) {
18458 $io = new IO\NullIO();
18459 $io->loadConfiguration($config);
18460 $dm = $this->createDownloadManager($io, $config);
18461 }
18462
18463 $am = new Archiver\ArchiveManager($dm);
18464 $am->addArchiver(new Archiver\ZipArchiver);
18465 $am->addArchiver(new Archiver\PharArchiver);
18466
18467 return $am;
18468 }
18469
18470
18471
18472
18473
18474
18475
18476
18477 protected function createPluginManager(IOInterface $io, Composer $composer, Composer $globalComposer = null, $disablePlugins = false)
18478 {
18479 return new Plugin\PluginManager($io, $composer, $globalComposer, $disablePlugins);
18480 }
18481
18482
18483
18484
18485 protected function createInstallationManager()
18486 {
18487 return new Installer\InstallationManager();
18488 }
18489
18490
18491
18492
18493
18494
18495 protected function createDefaultInstallers(Installer\InstallationManager $im, Composer $composer, IOInterface $io)
18496 {
18497 $im->addInstaller(new Installer\LibraryInstaller($io, $composer, null));
18498 $im->addInstaller(new Installer\PearInstaller($io, $composer, 'pear-library'));
18499 $im->addInstaller(new Installer\PluginInstaller($io, $composer));
18500 $im->addInstaller(new Installer\MetapackageInstaller($io));
18501 }
18502
18503
18504
18505
18506
18507 protected function purgePackages(WritableRepositoryInterface $repo, Installer\InstallationManager $im)
18508 {
18509 foreach ($repo->getPackages() as $package) {
18510 if (!$im->isPackageInstalled($repo, $package)) {
18511 $repo->removePackage($package);
18512 }
18513 }
18514 }
18515
18516
18517
18518
18519
18520
18521
18522
18523 public static function create(IOInterface $io, $config = null, $disablePlugins = false)
18524 {
18525 $factory = new static();
18526
18527 return $factory->createComposer($io, $config, $disablePlugins);
18528 }
18529
18530
18531
18532
18533
18534
18535
18536 public static function createRemoteFilesystem(IOInterface $io, Config $config = null, $options = array())
18537 {
18538 static $warned = false;
18539 $disableTls = false;
18540 if ($config && $config->get('disable-tls') === true) {
18541 if (!$warned) {
18542 $io->write('<warning>You are running Composer with SSL/TLS protection disabled.</warning>');
18543 }
18544 $warned = true;
18545 $disableTls = true;
18546 } elseif (!extension_loaded('openssl')) {
18547 throw new Exception\NoSslException('The openssl extension is required for SSL/TLS protection but is not available. '
18548 . '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.');
18549 }
18550 $remoteFilesystemOptions = array();
18551 if ($disableTls === false) {
18552 if ($config && $config->get('cafile')) {
18553 $remoteFilesystemOptions['ssl']['cafile'] = $config->get('cafile');
18554 }
18555 if ($config && $config->get('capath')) {
18556 $remoteFilesystemOptions['ssl']['capath'] = $config->get('capath');
18557 }
18558 $remoteFilesystemOptions = array_replace_recursive($remoteFilesystemOptions, $options);
18559 }
18560 try {
18561 $remoteFilesystem = new RemoteFilesystem($io, $config, $remoteFilesystemOptions, $disableTls);
18562 } catch (TransportException $e) {
18563 if (false !== strpos($e->getMessage(), 'cafile')) {
18564 $io->write('<error>Unable to locate a valid CA certificate file. You must set a valid \'cafile\' option.</error>');
18565 $io->write('<error>A valid CA certificate file is required for SSL/TLS protection.</error>');
18566 if (PHP_VERSION_ID < 50600) {
18567 $io->write('<error>It is recommended you upgrade to PHP 5.6+ which can detect your system CA file automatically.</error>');
18568 }
18569 $io->write('<error>You can disable this error, at your own risk, by setting the \'disable-tls\' option to true.</error>');
18570 }
18571 throw $e;
18572 }
18573
18574 return $remoteFilesystem;
18575 }
18576
18577
18578
18579
18580 private static function useXdg()
18581 {
18582 foreach (array_keys($_SERVER) as $key) {
18583 if (substr($key, 0, 4) === 'XDG_') {
18584 return true;
18585 }
18586 }
18587
18588 return false;
18589 }
18590
18591
18592
18593
18594
18595 private static function getUserDir()
18596 {
18597 $home = getenv('HOME');
18598 if (!$home) {
18599 throw new \RuntimeException('The HOME or COMPOSER_HOME environment variable must be set for composer to run correctly');
18600 }
18601
18602 return rtrim(strtr($home, '\\', '/'), '/');
18603 }
18604 }
18605 <?php
18606
18607
18608
18609
18610
18611
18612
18613
18614
18615
18616
18617 namespace Composer\IO;
18618
18619 use Composer\Config;
18620 use Composer\Util\ProcessExecutor;
18621 use Psr\Log\LoggerInterface;
18622 use Psr\Log\LogLevel;
18623
18624 abstract class BaseIO implements IOInterface, LoggerInterface
18625 {
18626 protected $authentications = array();
18627
18628
18629
18630
18631 public function getAuthentications()
18632 {
18633 return $this->authentications;
18634 }
18635
18636
18637
18638
18639 public function hasAuthentication($repositoryName)
18640 {
18641 return isset($this->authentications[$repositoryName]);
18642 }
18643
18644
18645
18646
18647 public function getAuthentication($repositoryName)
18648 {
18649 if (isset($this->authentications[$repositoryName])) {
18650 return $this->authentications[$repositoryName];
18651 }
18652
18653 return array('username' => null, 'password' => null);
18654 }
18655
18656
18657
18658
18659 public function setAuthentication($repositoryName, $username, $password = null)
18660 {
18661 $this->authentications[$repositoryName] = array('username' => $username, 'password' => $password);
18662 }
18663
18664
18665
18666
18667
18668
18669
18670
18671 protected function checkAndSetAuthentication($repositoryName, $username, $password = null)
18672 {
18673 if ($this->hasAuthentication($repositoryName)) {
18674 $auth = $this->getAuthentication($repositoryName);
18675 if ($auth['username'] === $username && $auth['password'] === $password) {
18676 return;
18677 }
18678
18679 $this->writeError(
18680 sprintf(
18681 "<warning>Warning: You should avoid overwriting already defined auth settings for %s.</warning>",
18682 $repositoryName
18683 )
18684 );
18685 }
18686 $this->setAuthentication($repositoryName, $username, $password);
18687 }
18688
18689
18690
18691
18692 public function loadConfiguration(Config $config)
18693 {
18694 $bitbucketOauth = $config->get('bitbucket-oauth') ?: array();
18695 $githubOauth = $config->get('github-oauth') ?: array();
18696 $gitlabOauth = $config->get('gitlab-oauth') ?: array();
18697 $gitlabToken = $config->get('gitlab-token') ?: array();
18698 $httpBasic = $config->get('http-basic') ?: array();
18699
18700
18701
18702 foreach ($bitbucketOauth as $domain => $cred) {
18703 $this->checkAndSetAuthentication($domain, $cred['consumer-key'], $cred['consumer-secret']);
18704 }
18705
18706 foreach ($githubOauth as $domain => $token) {
18707 if (!preg_match('{^[.a-z0-9]+$}', $token)) {
18708 throw new \UnexpectedValueException('Your github oauth token for '.$domain.' contains invalid characters: "'.$token.'"');
18709 }
18710 $this->checkAndSetAuthentication($domain, $token, 'x-oauth-basic');
18711 }
18712
18713 foreach ($gitlabOauth as $domain => $token) {
18714 $this->checkAndSetAuthentication($domain, $token, 'oauth2');
18715 }
18716
18717 foreach ($gitlabToken as $domain => $token) {
18718 $this->checkAndSetAuthentication($domain, $token, 'private-token');
18719 }
18720
18721
18722  foreach ($httpBasic as $domain => $cred) {
18723 $this->checkAndSetAuthentication($domain, $cred['username'], $cred['password']);
18724 }
18725
18726
18727  ProcessExecutor::setTimeout((int) $config->get('process-timeout'));
18728 }
18729
18730
18731
18732
18733
18734
18735
18736
18737 public function emergency($message, array $context = array())
18738 {
18739 return $this->log(LogLevel::EMERGENCY, $message, $context);
18740 }
18741
18742
18743
18744
18745
18746
18747
18748
18749
18750
18751
18752 public function alert($message, array $context = array())
18753 {
18754 return $this->log(LogLevel::ALERT, $message, $context);
18755 }
18756
18757
18758
18759
18760
18761
18762
18763
18764
18765
18766 public function critical($message, array $context = array())
18767 {
18768 return $this->log(LogLevel::CRITICAL, $message, $context);
18769 }
18770
18771
18772
18773
18774
18775
18776
18777
18778
18779 public function error($message, array $context = array())
18780 {
18781 return $this->log(LogLevel::ERROR, $message, $context);
18782 }
18783
18784
18785
18786
18787
18788
18789
18790
18791
18792
18793
18794 public function warning($message, array $context = array())
18795 {
18796 return $this->log(LogLevel::WARNING, $message, $context);
18797 }
18798
18799
18800
18801
18802
18803
18804
18805
18806 public function notice($message, array $context = array())
18807 {
18808 return $this->log(LogLevel::NOTICE, $message, $context);
18809 }
18810
18811
18812
18813
18814
18815
18816
18817
18818
18819
18820 public function info($message, array $context = array())
18821 {
18822 return $this->log(LogLevel::INFO, $message, $context);
18823 }
18824
18825
18826
18827
18828
18829
18830
18831
18832 public function debug($message, array $context = array())
18833 {
18834 return $this->log(LogLevel::DEBUG, $message, $context);
18835 }
18836
18837
18838
18839
18840
18841
18842
18843
18844
18845 public function log($level, $message, array $context = array())
18846 {
18847 if (in_array($level, array(LogLevel::EMERGENCY, LogLevel::ALERT, LogLevel::CRITICAL, LogLevel::ERROR))) {
18848 $this->writeError('<error>'.$message.'</error>', true, self::NORMAL);
18849 } elseif ($level === LogLevel::WARNING) {
18850 $this->writeError('<warning>'.$message.'</warning>', true, self::NORMAL);
18851 } elseif ($level === LogLevel::NOTICE) {
18852 $this->writeError('<info>'.$message.'</info>', true, self::VERBOSE);
18853 } elseif ($level === LogLevel::INFO) {
18854 $this->writeError('<info>'.$message.'</info>', true, self::VERY_VERBOSE);
18855 } else {
18856 $this->writeError($message, true, self::DEBUG);
18857 }
18858 }
18859 }
18860 <?php
18861
18862
18863
18864
18865
18866
18867
18868
18869
18870
18871
18872 namespace Composer\IO;
18873
18874 use Symfony\Component\Console\Output\StreamOutput;
18875 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
18876 use Symfony\Component\Console\Input\StringInput;
18877 use Symfony\Component\Console\Helper\HelperSet;
18878
18879
18880
18881
18882 class BufferIO extends ConsoleIO
18883 {
18884
18885
18886
18887
18888
18889 public function __construct($input = '', $verbosity = StreamOutput::VERBOSITY_NORMAL, OutputFormatterInterface $formatter = null)
18890 {
18891 $input = new StringInput($input);
18892 $input->setInteractive(false);
18893
18894 $output = new StreamOutput(fopen('php://memory', 'rw'), $verbosity, $formatter ? $formatter->isDecorated() : false, $formatter);
18895
18896 parent::__construct($input, $output, new HelperSet(array()));
18897 }
18898
18899 public function getOutput()
18900 {
18901 fseek($this->output->getStream(), 0);
18902
18903 $output = stream_get_contents($this->output->getStream());
18904
18905 $output = preg_replace_callback("{(?<=^|\n|\x08)(.+?)(\x08+)}", function ($matches) {
18906 $pre = strip_tags($matches[1]);
18907
18908 if (strlen($pre) === strlen($matches[2])) {
18909 return '';
18910 }
18911
18912
18913  return rtrim($matches[1])."\n";
18914 }, $output);
18915
18916 return $output;
18917 }
18918 }
18919 <?php
18920
18921
18922
18923
18924
18925
18926
18927
18928
18929
18930
18931 namespace Composer\IO;
18932
18933 use Symfony\Component\Console\Input\InputInterface;
18934 use Symfony\Component\Console\Output\ConsoleOutputInterface;
18935 use Symfony\Component\Console\Output\OutputInterface;
18936 use Symfony\Component\Console\Helper\HelperSet;
18937 use Composer\Question\StrictConfirmationQuestion;
18938 use Symfony\Component\Console\Question\Question;
18939
18940
18941
18942
18943
18944
18945
18946 class ConsoleIO extends BaseIO
18947 {
18948
18949 protected $input;
18950
18951 protected $output;
18952
18953 protected $helperSet;
18954
18955 protected $lastMessage;
18956
18957 protected $lastMessageErr;
18958
18959
18960 private $startTime;
18961
18962 private $verbosityMap;
18963
18964
18965
18966
18967
18968
18969
18970
18971 public function __construct(InputInterface $input, OutputInterface $output, HelperSet $helperSet)
18972 {
18973 $this->input = $input;
18974 $this->output = $output;
18975 $this->helperSet = $helperSet;
18976 $this->verbosityMap = array(
18977 self::QUIET => OutputInterface::VERBOSITY_QUIET,
18978 self::NORMAL => OutputInterface::VERBOSITY_NORMAL,
18979 self::VERBOSE => OutputInterface::VERBOSITY_VERBOSE,
18980 self::VERY_VERBOSE => OutputInterface::VERBOSITY_VERY_VERBOSE,
18981 self::DEBUG => OutputInterface::VERBOSITY_DEBUG,
18982 );
18983 }
18984
18985
18986
18987
18988 public function enableDebugging($startTime)
18989 {
18990 $this->startTime = $startTime;
18991 }
18992
18993
18994
18995
18996 public function isInteractive()
18997 {
18998 return $this->input->isInteractive();
18999 }
19000
19001
19002
19003
19004 public function isDecorated()
19005 {
19006 return $this->output->isDecorated();
19007 }
19008
19009
19010
19011
19012 public function isVerbose()
19013 {
19014 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERBOSE;
19015 }
19016
19017
19018
19019
19020 public function isVeryVerbose()
19021 {
19022 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_VERY_VERBOSE;
19023 }
19024
19025
19026
19027
19028 public function isDebug()
19029 {
19030 return $this->output->getVerbosity() >= OutputInterface::VERBOSITY_DEBUG;
19031 }
19032
19033
19034
19035
19036 public function write($messages, $newline = true, $verbosity = self::NORMAL)
19037 {
19038 $this->doWrite($messages, $newline, false, $verbosity);
19039 }
19040
19041
19042
19043
19044 public function writeError($messages, $newline = true, $verbosity = self::NORMAL)
19045 {
19046 $this->doWrite($messages, $newline, true, $verbosity);
19047 }
19048
19049
19050
19051
19052
19053
19054
19055 private function doWrite($messages, $newline, $stderr, $verbosity)
19056 {
19057 $sfVerbosity = $this->verbosityMap[$verbosity];
19058 if ($sfVerbosity > $this->output->getVerbosity()) {
19059 return;
19060 }
19061
19062
19063  
19064  
19065  if (OutputInterface::VERBOSITY_QUIET === 0) {
19066 $sfVerbosity = OutputInterface::OUTPUT_NORMAL;
19067 }
19068
19069 if (null !== $this->startTime) {
19070 $memoryUsage = memory_get_usage() / 1024 / 1024;
19071 $timeSpent = microtime(true) - $this->startTime;
19072 $messages = array_map(function ($message) use ($memoryUsage, $timeSpent) {
19073 return sprintf('[%.1fMB/%.2fs] %s', $memoryUsage, $timeSpent, $message);
19074 }, (array) $messages);
19075 }
19076
19077 if (true === $stderr && $this->output instanceof ConsoleOutputInterface) {
19078 $this->output->getErrorOutput()->write($messages, $newline, $sfVerbosity);
19079 $this->lastMessageErr = implode($newline ? "\n" : '', (array) $messages);
19080
19081 return;
19082 }
19083
19084 $this->output->write($messages, $newline, $sfVerbosity);
19085 $this->lastMessage = implode($newline ? "\n" : '', (array) $messages);
19086 }
19087
19088
19089
19090
19091 public function overwrite($messages, $newline = true, $size = null, $verbosity = self::NORMAL)
19092 {
19093 $this->doOverwrite($messages, $newline, $size, false, $verbosity);
19094 }
19095
19096
19097
19098
19099 public function overwriteError($messages, $newline = true, $size = null, $verbosity = self::NORMAL)
19100 {
19101 $this->doOverwrite($messages, $newline, $size, true, $verbosity);
19102 }
19103
19104
19105
19106
19107
19108
19109
19110
19111 private function doOverwrite($messages, $newline, $size, $stderr, $verbosity)
19112 {
19113
19114  $messages = implode($newline ? "\n" : '', (array) $messages);
19115
19116
19117  if (!isset($size)) {
19118
19119  $size = strlen(strip_tags($stderr ? $this->lastMessageErr : $this->lastMessage));
19120 }
19121
19122  $this->doWrite(str_repeat("\x08", $size), false, $stderr, $verbosity);
19123
19124
19125  $this->doWrite($messages, false, $stderr, $verbosity);
19126
19127
19128  
19129  
19130  $fill = $size - strlen(strip_tags($messages));
19131 if ($fill > 0) {
19132
19133  $this->doWrite(str_repeat(' ', $fill), false, $stderr, $verbosity);
19134
19135  $this->doWrite(str_repeat("\x08", $fill), false, $stderr, $verbosity);
19136 }
19137
19138 if ($newline) {
19139 $this->doWrite('', true, $stderr, $verbosity);
19140 }
19141
19142 if ($stderr) {
19143 $this->lastMessageErr = $messages;
19144 } else {
19145 $this->lastMessage = $messages;
19146 }
19147 }
19148
19149
19150
19151
19152 public function ask($question, $default = null)
19153 {
19154
19155 $helper = $this->helperSet->get('question');
19156 $question = new Question($question, $default);
19157
19158 return $helper->ask($this->input, $this->getErrorOutput(), $question);
19159 }
19160
19161
19162
19163
19164 public function askConfirmation($question, $default = true)
19165 {
19166
19167 $helper = $this->helperSet->get('question');
19168 $question = new StrictConfirmationQuestion($question, $default);
19169
19170 return $helper->ask($this->input, $this->getErrorOutput(), $question);
19171 }
19172
19173
19174
19175
19176 public function askAndValidate($question, $validator, $attempts = null, $default = null)
19177 {
19178
19179 $helper = $this->helperSet->get('question');
19180 $question = new Question($question, $default);
19181 $question->setValidator($validator);
19182 $question->setMaxAttempts($attempts);
19183
19184 return $helper->ask($this->input, $this->getErrorOutput(), $question);
19185 }
19186
19187
19188
19189
19190 public function askAndHideAnswer($question)
19191 {
19192 $this->writeError($question, false);
19193
19194 return \Seld\CliPrompt\CliPrompt::hiddenPrompt(true);
19195 }
19196
19197
19198
19199
19200 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
19201 {
19202 if ($this->isInteractive()) {
19203 return $this->helperSet->get('dialog')->select($this->getErrorOutput(), $question, $choices, $default, $attempts, $errorMessage, $multiselect);
19204 }
19205
19206 return $default;
19207 }
19208
19209
19210
19211
19212 private function getErrorOutput()
19213 {
19214 if ($this->output instanceof ConsoleOutputInterface) {
19215 return $this->output->getErrorOutput();
19216 }
19217
19218 return $this->output;
19219 }
19220 }
19221 <?php
19222
19223
19224
19225
19226
19227
19228
19229
19230
19231
19232
19233 namespace Composer\IO;
19234
19235 use Composer\Config;
19236
19237
19238
19239
19240
19241
19242 interface IOInterface
19243 {
19244 const QUIET = 1;
19245 const NORMAL = 2;
19246 const VERBOSE = 4;
19247 const VERY_VERBOSE = 8;
19248 const DEBUG = 16;
19249
19250
19251
19252
19253
19254
19255 public function isInteractive();
19256
19257
19258
19259
19260
19261
19262 public function isVerbose();
19263
19264
19265
19266
19267
19268
19269 public function isVeryVerbose();
19270
19271
19272
19273
19274
19275
19276 public function isDebug();
19277
19278
19279
19280
19281
19282
19283 public function isDecorated();
19284
19285
19286
19287
19288
19289
19290
19291
19292 public function write($messages, $newline = true, $verbosity = self::NORMAL);
19293
19294
19295
19296
19297
19298
19299
19300
19301 public function writeError($messages, $newline = true, $verbosity = self::NORMAL);
19302
19303
19304
19305
19306
19307
19308
19309
19310
19311 public function overwrite($messages, $newline = true, $size = null, $verbosity = self::NORMAL);
19312
19313
19314
19315
19316
19317
19318
19319
19320
19321 public function overwriteError($messages, $newline = true, $size = null, $verbosity = self::NORMAL);
19322
19323
19324
19325
19326
19327
19328
19329
19330
19331
19332 public function ask($question, $default = null);
19333
19334
19335
19336
19337
19338
19339
19340
19341
19342
19343
19344 public function askConfirmation($question, $default = true);
19345
19346
19347
19348
19349
19350
19351
19352
19353
19354
19355
19356
19357
19358
19359
19360
19361 public function askAndValidate($question, $validator, $attempts = null, $default = null);
19362
19363
19364
19365
19366
19367
19368
19369
19370 public function askAndHideAnswer($question);
19371
19372
19373
19374
19375
19376
19377
19378
19379
19380
19381
19382
19383
19384
19385 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false);
19386
19387
19388
19389
19390
19391
19392 public function getAuthentications();
19393
19394
19395
19396
19397
19398
19399
19400
19401 public function hasAuthentication($repositoryName);
19402
19403
19404
19405
19406
19407
19408
19409
19410 public function getAuthentication($repositoryName);
19411
19412
19413
19414
19415
19416
19417
19418
19419 public function setAuthentication($repositoryName, $username, $password = null);
19420
19421
19422
19423
19424
19425
19426 public function loadConfiguration(Config $config);
19427 }
19428 <?php
19429
19430
19431
19432
19433
19434
19435
19436
19437
19438
19439
19440 namespace Composer\IO;
19441
19442
19443
19444
19445
19446
19447 class NullIO extends BaseIO
19448 {
19449
19450
19451
19452 public function isInteractive()
19453 {
19454 return false;
19455 }
19456
19457
19458
19459
19460 public function isVerbose()
19461 {
19462 return false;
19463 }
19464
19465
19466
19467
19468 public function isVeryVerbose()
19469 {
19470 return false;
19471 }
19472
19473
19474
19475
19476 public function isDebug()
19477 {
19478 return false;
19479 }
19480
19481
19482
19483
19484 public function isDecorated()
19485 {
19486 return false;
19487 }
19488
19489
19490
19491
19492 public function write($messages, $newline = true, $verbosity = self::NORMAL)
19493 {
19494 }
19495
19496
19497
19498
19499 public function writeError($messages, $newline = true, $verbosity = self::NORMAL)
19500 {
19501 }
19502
19503
19504
19505
19506 public function overwrite($messages, $newline = true, $size = 80, $verbosity = self::NORMAL)
19507 {
19508 }
19509
19510
19511
19512
19513 public function overwriteError($messages, $newline = true, $size = 80, $verbosity = self::NORMAL)
19514 {
19515 }
19516
19517
19518
19519
19520 public function ask($question, $default = null)
19521 {
19522 return $default;
19523 }
19524
19525
19526
19527
19528 public function askConfirmation($question, $default = true)
19529 {
19530 return $default;
19531 }
19532
19533
19534
19535
19536 public function askAndValidate($question, $validator, $attempts = false, $default = null)
19537 {
19538 return $default;
19539 }
19540
19541
19542
19543
19544 public function askAndHideAnswer($question)
19545 {
19546 return null;
19547 }
19548
19549
19550
19551
19552 public function select($question, $choices, $default, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
19553 {
19554 return $default;
19555 }
19556 }
19557 <?php
19558
19559
19560
19561
19562
19563
19564
19565
19566
19567
19568
19569 namespace Composer;
19570
19571 use Composer\Autoload\AutoloadGenerator;
19572 use Composer\DependencyResolver\DefaultPolicy;
19573 use Composer\DependencyResolver\Operation\UpdateOperation;
19574 use Composer\DependencyResolver\Operation\InstallOperation;
19575 use Composer\DependencyResolver\Operation\UninstallOperation;
19576 use Composer\DependencyResolver\Operation\OperationInterface;
19577 use Composer\DependencyResolver\PolicyInterface;
19578 use Composer\DependencyResolver\Pool;
19579 use Composer\DependencyResolver\Request;
19580 use Composer\DependencyResolver\Rule;
19581 use Composer\DependencyResolver\Solver;
19582 use Composer\DependencyResolver\SolverProblemsException;
19583 use Composer\Downloader\DownloadManager;
19584 use Composer\EventDispatcher\EventDispatcher;
19585 use Composer\Installer\InstallationManager;
19586 use Composer\Installer\InstallerEvents;
19587 use Composer\Installer\NoopInstaller;
19588 use Composer\Installer\SuggestedPackagesReporter;
19589 use Composer\IO\IOInterface;
19590 use Composer\Package\AliasPackage;
19591 use Composer\Package\CompletePackage;
19592 use Composer\Package\Link;
19593 use Composer\Package\Loader\ArrayLoader;
19594 use Composer\Package\Dumper\ArrayDumper;
19595 use Composer\Semver\Constraint\Constraint;
19596 use Composer\Package\Locker;
19597 use Composer\Package\PackageInterface;
19598 use Composer\Package\RootPackageInterface;
19599 use Composer\Repository\CompositeRepository;
19600 use Composer\Repository\InstalledArrayRepository;
19601 use Composer\Repository\PlatformRepository;
19602 use Composer\Repository\RepositoryInterface;
19603 use Composer\Repository\RepositoryManager;
19604 use Composer\Repository\WritableRepositoryInterface;
19605 use Composer\Script\ScriptEvents;
19606
19607
19608
19609
19610
19611
19612
19613 class Installer
19614 {
19615
19616
19617
19618 protected $io;
19619
19620
19621
19622
19623 protected $config;
19624
19625
19626
19627
19628 protected $package;
19629
19630
19631
19632
19633 protected $downloadManager;
19634
19635
19636
19637
19638 protected $repositoryManager;
19639
19640
19641
19642
19643 protected $locker;
19644
19645
19646
19647
19648 protected $installationManager;
19649
19650
19651
19652
19653 protected $eventDispatcher;
19654
19655
19656
19657
19658 protected $autoloadGenerator;
19659
19660 protected $preferSource = false;
19661 protected $preferDist = false;
19662 protected $optimizeAutoloader = false;
19663 protected $classMapAuthoritative = false;
19664 protected $apcuAutoloader = false;
19665 protected $devMode = false;
19666 protected $dryRun = false;
19667 protected $verbose = false;
19668 protected $update = false;
19669 protected $dumpAutoloader = true;
19670 protected $runScripts = true;
19671 protected $ignorePlatformReqs = false;
19672 protected $preferStable = false;
19673 protected $preferLowest = false;
19674 protected $skipSuggest = false;
19675 protected $writeLock = true;
19676 protected $executeOperations = true;
19677
19678
19679
19680
19681
19682
19683 protected $updateWhitelist = null;
19684 protected $whitelistDependencies = false;
19685
19686
19687
19688
19689 protected $suggestedPackagesReporter;
19690
19691
19692
19693
19694 protected $additionalInstalledRepository;
19695
19696
19697
19698
19699
19700
19701
19702
19703
19704
19705
19706
19707
19708
19709 public function __construct(IOInterface $io, Config $config, RootPackageInterface $package, DownloadManager $downloadManager, RepositoryManager $repositoryManager, Locker $locker, InstallationManager $installationManager, EventDispatcher $eventDispatcher, AutoloadGenerator $autoloadGenerator)
19710 {
19711 $this->io = $io;
19712 $this->config = $config;
19713 $this->package = $package;
19714 $this->downloadManager = $downloadManager;
19715 $this->repositoryManager = $repositoryManager;
19716 $this->locker = $locker;
19717 $this->installationManager = $installationManager;
19718 $this->eventDispatcher = $eventDispatcher;
19719 $this->autoloadGenerator = $autoloadGenerator;
19720 }
19721
19722
19723
19724
19725
19726
19727
19728 public function run()
19729 {
19730
19731  
19732  
19733  
19734  gc_collect_cycles();
19735 gc_disable();
19736
19737
19738  if (!$this->update && !$this->locker->isLocked()) {
19739 $this->update = true;
19740 }
19741
19742 if ($this->dryRun) {
19743 $this->verbose = true;
19744 $this->runScripts = false;
19745 $this->executeOperations = false;
19746 $this->writeLock = false;
19747 $this->dumpAutoloader = false;
19748 $this->installationManager->addInstaller(new NoopInstaller);
19749 $this->mockLocalRepositories($this->repositoryManager);
19750 }
19751
19752 if ($this->runScripts) {
19753
19754  $eventName = $this->update ? ScriptEvents::PRE_UPDATE_CMD : ScriptEvents::PRE_INSTALL_CMD;
19755 $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
19756 }
19757
19758 $this->downloadManager->setPreferSource($this->preferSource);
19759 $this->downloadManager->setPreferDist($this->preferDist);
19760
19761
19762  $localRepo = $this->repositoryManager->getLocalRepository();
19763 if ($this->update) {
19764 $platformOverrides = $this->config->get('platform') ?: array();
19765 } else {
19766 $platformOverrides = $this->locker->getPlatformOverrides();
19767 }
19768 $platformRepo = new PlatformRepository(array(), $platformOverrides);
19769 $installedRepo = $this->createInstalledRepo($localRepo, $platformRepo);
19770
19771 $aliases = $this->getRootAliases();
19772 $this->aliasPlatformPackages($platformRepo, $aliases);
19773
19774 if (!$this->suggestedPackagesReporter) {
19775 $this->suggestedPackagesReporter = new SuggestedPackagesReporter($this->io);
19776 }
19777
19778 try {
19779 list($res, $devPackages) = $this->doInstall($localRepo, $installedRepo, $platformRepo, $aliases);
19780 if ($res !== 0) {
19781 return $res;
19782 }
19783 } catch (\Exception $e) {
19784 if ($this->executeOperations) {
19785 $this->installationManager->notifyInstalls($this->io);
19786 }
19787
19788 throw $e;
19789 }
19790 if ($this->executeOperations) {
19791 $this->installationManager->notifyInstalls($this->io);
19792 }
19793
19794
19795  if ($this->devMode && !$this->skipSuggest) {
19796 $this->suggestedPackagesReporter->output($installedRepo);
19797 }
19798
19799
19800  foreach ($localRepo->getPackages() as $package) {
19801 if (!$package instanceof CompletePackage || !$package->isAbandoned()) {
19802 continue;
19803 }
19804
19805 $replacement = (is_string($package->getReplacementPackage()))
19806 ? 'Use ' . $package->getReplacementPackage() . ' instead'
19807 : 'No replacement was suggested';
19808
19809 $this->io->writeError(
19810 sprintf(
19811 "<warning>Package %s is abandoned, you should avoid using it. %s.</warning>",
19812 $package->getPrettyName(),
19813 $replacement
19814 )
19815 );
19816 }
19817
19818
19819  if ($this->update && $this->writeLock) {
19820 $localRepo->reload();
19821
19822 $platformReqs = $this->extractPlatformRequirements($this->package->getRequires());
19823 $platformDevReqs = $this->extractPlatformRequirements($this->package->getDevRequires());
19824
19825 $updatedLock = $this->locker->setLockData(
19826 array_diff($localRepo->getCanonicalPackages(), $devPackages),
19827 $devPackages,
19828 $platformReqs,
19829 $platformDevReqs,
19830 $aliases,
19831 $this->package->getMinimumStability(),
19832 $this->package->getStabilityFlags(),
19833 $this->preferStable || $this->package->getPreferStable(),
19834 $this->preferLowest,
19835 $this->config->get('platform') ?: array()
19836 );
19837 if ($updatedLock) {
19838 $this->io->writeError('<info>Writing lock file</info>');
19839 }
19840 }
19841
19842 if ($this->dumpAutoloader) {
19843
19844  if ($this->optimizeAutoloader) {
19845 $this->io->writeError('<info>Generating optimized autoload files</info>');
19846 } else {
19847 $this->io->writeError('<info>Generating autoload files</info>');
19848 }
19849
19850 $this->autoloadGenerator->setDevMode($this->devMode);
19851 $this->autoloadGenerator->setClassMapAuthoritative($this->classMapAuthoritative);
19852 $this->autoloadGenerator->setApcu($this->apcuAutoloader);
19853 $this->autoloadGenerator->setRunScripts($this->runScripts);
19854 $this->autoloadGenerator->dump($this->config, $localRepo, $this->package, $this->installationManager, 'composer', $this->optimizeAutoloader);
19855 }
19856
19857 if ($this->runScripts) {
19858 $devMode = (int) $this->devMode;
19859 putenv("COMPOSER_DEV_MODE=$devMode");
19860
19861
19862  $eventName = $this->update ? ScriptEvents::POST_UPDATE_CMD : ScriptEvents::POST_INSTALL_CMD;
19863 $this->eventDispatcher->dispatchScript($eventName, $this->devMode);
19864 }
19865
19866 if ($this->executeOperations) {
19867
19868  foreach ($localRepo->getPackages() as $package) {
19869 $this->installationManager->ensureBinariesPresence($package);
19870 }
19871
19872 $vendorDir = $this->config->get('vendor-dir');
19873 if (is_dir($vendorDir)) {
19874
19875  
19876  @touch($vendorDir);
19877 }
19878 }
19879
19880
19881  if (!defined('HHVM_VERSION')) {
19882 gc_enable();
19883 }
19884
19885 return 0;
19886 }
19887
19888
19889
19890
19891
19892
19893
19894
19895 protected function doInstall($localRepo, $installedRepo, $platformRepo, $aliases)
19896 {
19897
19898  $lockedRepository = null;
19899 $repositories = null;
19900
19901
19902  
19903  
19904  if (!$this->update || (!empty($this->updateWhitelist) && $this->locker->isLocked())) {
19905 try {
19906 $lockedRepository = $this->locker->getLockedRepository($this->devMode);
19907 } catch (\RuntimeException $e) {
19908
19909  if ($this->package->getDevRequires()) {
19910 throw $e;
19911 }
19912
19913  $lockedRepository = $this->locker->getLockedRepository();
19914 }
19915 }
19916
19917 $this->whitelistUpdateDependencies(
19918 $lockedRepository ?: $localRepo,
19919 $this->package->getRequires(),
19920 $this->package->getDevRequires()
19921 );
19922
19923 $this->io->writeError('<info>Loading composer repositories with package information</info>');
19924
19925
19926  $policy = $this->createPolicy();
19927 $pool = $this->createPool($this->update ? null : $lockedRepository);
19928 $pool->addRepository($installedRepo, $aliases);
19929 if ($this->update) {
19930 $repositories = $this->repositoryManager->getRepositories();
19931 foreach ($repositories as $repository) {
19932 $pool->addRepository($repository, $aliases);
19933 }
19934 }
19935
19936  
19937  
19938  if ($lockedRepository) {
19939 $pool->addRepository($lockedRepository, $aliases);
19940 }
19941
19942
19943  $request = $this->createRequest($this->package, $platformRepo);
19944
19945 if ($this->update) {
19946
19947  $removedUnstablePackages = array();
19948 foreach ($localRepo->getPackages() as $package) {
19949 if (
19950 !$pool->isPackageAcceptable($package->getNames(), $package->getStability())
19951 && $this->installationManager->isPackageInstalled($localRepo, $package)
19952 ) {
19953 $removedUnstablePackages[$package->getName()] = true;
19954 $request->remove($package->getName(), new Constraint('=', $package->getVersion()));
19955 }
19956 }
19957
19958 $this->io->writeError('<info>Updating dependencies'.($this->devMode ? ' (including require-dev)' : '').'</info>');
19959
19960 $request->updateAll();
19961
19962 $links = array_merge($this->package->getRequires(), $this->package->getDevRequires());
19963
19964 foreach ($links as $link) {
19965 $request->install($link->getTarget(), $link->getConstraint());
19966 }
19967
19968
19969  
19970  if ($this->updateWhitelist) {
19971 $currentPackages = $this->getCurrentPackages($installedRepo);
19972
19973
19974  $candidates = array();
19975 foreach ($links as $link) {
19976 $candidates[$link->getTarget()] = true;
19977 $rootRequires[$link->getTarget()] = $link;
19978 }
19979 foreach ($currentPackages as $package) {
19980 $candidates[$package->getName()] = true;
19981 }
19982
19983
19984  foreach ($candidates as $candidate => $dummy) {
19985 foreach ($currentPackages as $curPackage) {
19986 if ($curPackage->getName() === $candidate) {
19987 if (!$this->isUpdateable($curPackage) && !isset($removedUnstablePackages[$curPackage->getName()])) {
19988 $constraint = new Constraint('=', $curPackage->getVersion());
19989 $description = $this->locker->isLocked() ? '(locked at' : '(installed at';
19990 $requiredAt = isset($rootRequires[$candidate]) ? ', required as ' . $rootRequires[$candidate]->getPrettyConstraint() : '';
19991 $constraint->setPrettyString($description . ' ' . $curPackage->getPrettyVersion() . $requiredAt . ')');
19992 $request->install($curPackage->getName(), $constraint);
19993 }
19994 break;
19995 }
19996 }
19997 }
19998 }
19999 } else {
20000 $this->io->writeError('<info>Installing dependencies'.($this->devMode ? ' (including require-dev)' : '').' from lock file</info>');
20001
20002 if (!$this->locker->isFresh()) {
20003 $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);
20004 }
20005
20006 foreach ($lockedRepository->getPackages() as $package) {
20007 $version = $package->getVersion();
20008 if (isset($aliases[$package->getName()][$version])) {
20009 $version = $aliases[$package->getName()][$version]['alias_normalized'];
20010 }
20011 $constraint = new Constraint('=', $version);
20012 $constraint->setPrettyString($package->getPrettyVersion());
20013 $request->install($package->getName(), $constraint);
20014 }
20015
20016 foreach ($this->locker->getPlatformRequirements($this->devMode) as $link) {
20017 $request->install($link->getTarget(), $link->getConstraint());
20018 }
20019 }
20020
20021
20022  $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, 'force-links');
20023
20024
20025  $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request);
20026 $solver = new Solver($policy, $pool, $installedRepo, $this->io);
20027 try {
20028 $operations = $solver->solve($request, $this->ignorePlatformReqs);
20029 } catch (SolverProblemsException $e) {
20030 $this->io->writeError('<error>Your requirements could not be resolved to an installable set of packages.</error>', true, IOInterface::QUIET);
20031 $this->io->writeError($e->getMessage());
20032 if ($this->update && !$this->devMode) {
20033 $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);
20034 }
20035
20036 return array(max(1, $e->getCode()), array());
20037 }
20038
20039
20040  $operations = $this->processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, 'force-updates', $operations);
20041
20042 $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, $this->devMode, $policy, $pool, $installedRepo, $request, $operations);
20043
20044 $this->io->writeError("Analyzed ".count($pool)." packages to resolve dependencies", true, IOInterface::VERBOSE);
20045 $this->io->writeError("Analyzed ".$solver->getRuleSetSize()." rules to resolve dependencies", true, IOInterface::VERBOSE);
20046
20047
20048  if (!$operations) {
20049 $this->io->writeError('Nothing to install or update');
20050 }
20051
20052 $operations = $this->movePluginsToFront($operations);
20053 $operations = $this->moveUninstallsToFront($operations);
20054
20055
20056  
20057  if ($this->update) {
20058 $devPackages = $this->extractDevPackages($operations, $localRepo, $platformRepo, $aliases);
20059 if (!$this->devMode) {
20060 $operations = $this->filterDevPackageOperations($devPackages, $operations, $localRepo);
20061 }
20062 } else {
20063 $devPackages = null;
20064 }
20065
20066 if ($operations) {
20067 $installs = $updates = $uninstalls = array();
20068 foreach ($operations as $operation) {
20069 if ($operation instanceof InstallOperation) {
20070 $installs[] = $operation->getPackage()->getPrettyName().':'.$operation->getPackage()->getFullPrettyVersion();
20071 } elseif ($operation instanceof UpdateOperation) {
20072 $updates[] = $operation->getTargetPackage()->getPrettyName().':'.$operation->getTargetPackage()->getFullPrettyVersion();
20073 } elseif ($operation instanceof UninstallOperation) {
20074 $uninstalls[] = $operation->getPackage()->getPrettyName();
20075 }
20076 }
20077
20078 $this->io->writeError(
20079 sprintf("<info>Package operations: %d install%s, %d update%s, %d removal%s</info>",
20080 count($installs),
20081 1 === count($installs) ? '' : 's',
20082 count($updates),
20083 1 === count($updates) ? '' : 's',
20084 count($uninstalls),
20085 1 === count($uninstalls) ? '' : 's')
20086 );
20087 if ($installs) {
20088 $this->io->writeError("Installs: ".implode(', ', $installs), true, IOInterface::VERBOSE);
20089 }
20090 if ($updates) {
20091 $this->io->writeError("Updates: ".implode(', ', $updates), true, IOInterface::VERBOSE);
20092 }
20093 if ($uninstalls) {
20094 $this->io->writeError("Removals: ".implode(', ', $uninstalls), true, IOInterface::VERBOSE);
20095 }
20096 }
20097
20098 foreach ($operations as $operation) {
20099
20100  if ('install' === $operation->getJobType()) {
20101 $this->suggestedPackagesReporter->addSuggestionsFromPackage($operation->getPackage());
20102 }
20103
20104
20105  if ($this->update) {
20106 $package = null;
20107 if ('update' === $operation->getJobType()) {
20108 $package = $operation->getTargetPackage();
20109 } elseif ('install' === $operation->getJobType()) {
20110 $package = $operation->getPackage();
20111 }
20112 if ($package && $package->isDev()) {
20113 $references = $this->package->getReferences();
20114 if (isset($references[$package->getName()])) {
20115 $this->updateInstallReferences($package, $references[$package->getName()]);
20116 }
20117 }
20118 if ('update' === $operation->getJobType()
20119 && $operation->getTargetPackage()->isDev()
20120 && $operation->getTargetPackage()->getVersion() === $operation->getInitialPackage()->getVersion()
20121 && (!$operation->getTargetPackage()->getSourceReference() || $operation->getTargetPackage()->getSourceReference() === $operation->getInitialPackage()->getSourceReference())
20122 && (!$operation->getTargetPackage()->getDistReference() || $operation->getTargetPackage()->getDistReference() === $operation->getInitialPackage()->getDistReference())
20123 ) {
20124 $this->io->writeError('  - Skipping update of '. $operation->getTargetPackage()->getPrettyName().' to the same reference-locked version', true, IOInterface::DEBUG);
20125 $this->io->writeError('', true, IOInterface::DEBUG);
20126
20127 continue;
20128 }
20129 }
20130
20131 $event = 'Composer\Installer\PackageEvents::PRE_PACKAGE_'.strtoupper($operation->getJobType());
20132 if (defined($event) && $this->runScripts) {
20133 $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
20134 }
20135
20136
20137  if (!$this->executeOperations && false === strpos($operation->getJobType(), 'Alias')) {
20138 $this->io->writeError('  - ' . $operation);
20139 } elseif ($this->io->isDebug() && false !== strpos($operation->getJobType(), 'Alias')) {
20140 $this->io->writeError('  - ' . $operation);
20141 }
20142
20143 $this->installationManager->execute($localRepo, $operation);
20144
20145
20146  if ($this->verbose && $this->io->isVeryVerbose() && in_array($operation->getJobType(), array('install', 'update'))) {
20147 $reason = $operation->getReason();
20148 if ($reason instanceof Rule) {
20149 switch ($reason->getReason()) {
20150 case Rule::RULE_JOB_INSTALL:
20151 $this->io->writeError('    REASON: Required by the root package: '.$reason->getPrettyString($pool));
20152 $this->io->writeError('');
20153 break;
20154 case Rule::RULE_PACKAGE_REQUIRES:
20155 $this->io->writeError('    REASON: '.$reason->getPrettyString($pool));
20156 $this->io->writeError('');
20157 break;
20158 }
20159 }
20160 }
20161
20162 $event = 'Composer\Installer\PackageEvents::POST_PACKAGE_'.strtoupper($operation->getJobType());
20163 if (defined($event) && $this->runScripts) {
20164 $this->eventDispatcher->dispatchPackageEvent(constant($event), $this->devMode, $policy, $pool, $installedRepo, $request, $operations, $operation);
20165 }
20166
20167 if ($this->executeOperations || $this->writeLock) {
20168 $localRepo->write();
20169 }
20170 }
20171
20172 if ($this->executeOperations) {
20173
20174  $this->processPackageUrls($pool, $policy, $localRepo, $repositories);
20175 $localRepo->write();
20176 }
20177
20178 return array(0, $devPackages);
20179 }
20180
20181
20182
20183
20184
20185
20186
20187
20188
20189
20190
20191 private function extractDevPackages(array $operations, RepositoryInterface $localRepo, PlatformRepository $platformRepo, array $aliases)
20192 {
20193 if (!$this->package->getDevRequires()) {
20194 return array();
20195 }
20196
20197
20198  $tempLocalRepo = clone $localRepo;
20199 foreach ($operations as $operation) {
20200 switch ($operation->getJobType()) {
20201 case 'install':
20202 case 'markAliasInstalled':
20203 if (!$tempLocalRepo->hasPackage($operation->getPackage())) {
20204 $tempLocalRepo->addPackage(clone $operation->getPackage());
20205 }
20206 break;
20207
20208 case 'uninstall':
20209 case 'markAliasUninstalled':
20210 $tempLocalRepo->removePackage($operation->getPackage());
20211 break;
20212
20213 case 'update':
20214 $tempLocalRepo->removePackage($operation->getInitialPackage());
20215 if (!$tempLocalRepo->hasPackage($operation->getTargetPackage())) {
20216 $tempLocalRepo->addPackage(clone $operation->getTargetPackage());
20217 }
20218 break;
20219
20220 default:
20221 throw new \LogicException('Unknown type: '.$operation->getJobType());
20222 }
20223 }
20224
20225
20226  
20227  
20228  $localRepo = new InstalledArrayRepository(array());
20229 $loader = new ArrayLoader(null, true);
20230 $dumper = new ArrayDumper();
20231 foreach ($tempLocalRepo->getCanonicalPackages() as $pkg) {
20232 $localRepo->addPackage($loader->load($dumper->dump($pkg)));
20233 }
20234 unset($tempLocalRepo, $loader, $dumper);
20235
20236 $policy = $this->createPolicy();
20237 $pool = $this->createPool();
20238 $installedRepo = $this->createInstalledRepo($localRepo, $platformRepo);
20239 $pool->addRepository($installedRepo, $aliases);
20240
20241
20242  $request = $this->createRequest($this->package, $platformRepo);
20243 $request->updateAll();
20244 foreach ($this->package->getRequires() as $link) {
20245 $request->install($link->getTarget(), $link->getConstraint());
20246 }
20247
20248
20249  $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::PRE_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request);
20250 $solver = new Solver($policy, $pool, $installedRepo, $this->io);
20251 $ops = $solver->solve($request, $this->ignorePlatformReqs);
20252 $this->eventDispatcher->dispatchInstallerEvent(InstallerEvents::POST_DEPENDENCIES_SOLVING, false, $policy, $pool, $installedRepo, $request, $ops);
20253
20254 $devPackages = array();
20255 foreach ($ops as $op) {
20256 if ($op->getJobType() === 'uninstall') {
20257 $devPackages[] = $op->getPackage();
20258 }
20259 }
20260
20261 return $devPackages;
20262 }
20263
20264
20265
20266
20267 private function filterDevPackageOperations(array $devPackages, array $operations, RepositoryInterface $localRepo)
20268 {
20269 $finalOps = array();
20270 $packagesToSkip = array();
20271 foreach ($devPackages as $pkg) {
20272 $packagesToSkip[$pkg->getName()] = true;
20273 if ($installedDevPkg = $localRepo->findPackage($pkg->getName(), '*')) {
20274 $finalOps[] = new UninstallOperation($installedDevPkg, 'non-dev install removing it');
20275 }
20276 }
20277
20278
20279  foreach ($operations as $op) {
20280 $package = $op->getJobType() === 'update' ? $op->getTargetPackage() : $op->getPackage();
20281 if (isset($packagesToSkip[$package->getName()])) {
20282 continue;
20283 }
20284
20285 $finalOps[] = $op;
20286 }
20287
20288 return $finalOps;
20289 }
20290
20291
20292
20293
20294
20295
20296
20297
20298
20299
20300
20301
20302
20303
20304 private function movePluginsToFront(array $operations)
20305 {
20306 $pluginsNoDeps = array();
20307 $pluginsWithDeps = array();
20308 $pluginRequires = array();
20309
20310 foreach (array_reverse($operations, true) as $idx => $op) {
20311 if ($op instanceof InstallOperation) {
20312 $package = $op->getPackage();
20313 } elseif ($op instanceof UpdateOperation) {
20314 $package = $op->getTargetPackage();
20315 } else {
20316 continue;
20317 }
20318
20319
20320  $isPlugin = $package->getType() === 'composer-plugin' || $package->getType() === 'composer-installer';
20321
20322
20323  if ($isPlugin || count(array_intersect($package->getNames(), $pluginRequires))) {
20324
20325  $requires = array_filter(array_keys($package->getRequires()), function($req) {
20326 return $req !== 'composer-plugin-api' && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req);
20327 });
20328
20329
20330  if ($isPlugin && !count($requires)) {
20331
20332  array_unshift($pluginsNoDeps, $op);
20333 } else {
20334
20335  $pluginRequires = array_merge($pluginRequires, $requires);
20336
20337  array_unshift($pluginsWithDeps, $op);
20338 }
20339
20340 unset($operations[$idx]);
20341 }
20342 }
20343
20344 return array_merge($pluginsNoDeps, $pluginsWithDeps, $operations);
20345 }
20346
20347
20348
20349
20350
20351
20352
20353
20354 private function moveUninstallsToFront(array $operations)
20355 {
20356 $uninstOps = array();
20357 foreach ($operations as $idx => $op) {
20358 if ($op instanceof UninstallOperation) {
20359 $uninstOps[] = $op;
20360 unset($operations[$idx]);
20361 }
20362 }
20363
20364 return array_merge($uninstOps, $operations);
20365 }
20366
20367
20368
20369
20370 private function createInstalledRepo(RepositoryInterface $localRepo, PlatformRepository $platformRepo)
20371 {
20372
20373  
20374  
20375  $installedRootPackage = clone $this->package;
20376 $installedRootPackage->setRequires(array());
20377 $installedRootPackage->setDevRequires(array());
20378
20379 $repos = array(
20380 $localRepo,
20381 new InstalledArrayRepository(array($installedRootPackage)),
20382 $platformRepo,
20383 );
20384 $installedRepo = new CompositeRepository($repos);
20385 if ($this->additionalInstalledRepository) {
20386 $installedRepo->addRepository($this->additionalInstalledRepository);
20387 }
20388
20389 return $installedRepo;
20390 }
20391
20392
20393
20394
20395
20396 private function createPool(RepositoryInterface $lockedRepository = null)
20397 {
20398 if ($this->update) {
20399 $minimumStability = $this->package->getMinimumStability();
20400 $stabilityFlags = $this->package->getStabilityFlags();
20401
20402 $requires = array_merge($this->package->getRequires(), $this->package->getDevRequires());
20403 } else {
20404 $minimumStability = $this->locker->getMinimumStability();
20405 $stabilityFlags = $this->locker->getStabilityFlags();
20406
20407 $requires = array();
20408 foreach ($lockedRepository->getPackages() as $package) {
20409 $constraint = new Constraint('=', $package->getVersion());
20410 $constraint->setPrettyString($package->getPrettyVersion());
20411 $requires[$package->getName()] = $constraint;
20412 }
20413 }
20414
20415 $rootConstraints = array();
20416 foreach ($requires as $req => $constraint) {
20417
20418  if ($this->ignorePlatformReqs && preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $req)) {
20419 continue;
20420 }
20421 if ($constraint instanceof Link) {
20422 $rootConstraints[$req] = $constraint->getConstraint();
20423 } else {
20424 $rootConstraints[$req] = $constraint;
20425 }
20426 }
20427
20428 return new Pool($minimumStability, $stabilityFlags, $rootConstraints);
20429 }
20430
20431
20432
20433
20434 private function createPolicy()
20435 {
20436 $preferStable = null;
20437 $preferLowest = null;
20438 if (!$this->update) {
20439 $preferStable = $this->locker->getPreferStable();
20440 $preferLowest = $this->locker->getPreferLowest();
20441 }
20442
20443  
20444  if (null === $preferStable) {
20445 $preferStable = $this->preferStable || $this->package->getPreferStable();
20446 }
20447 if (null === $preferLowest) {
20448 $preferLowest = $this->preferLowest;
20449 }
20450
20451 return new DefaultPolicy($preferStable, $preferLowest);
20452 }
20453
20454
20455
20456
20457
20458
20459 private function createRequest(RootPackageInterface $rootPackage, PlatformRepository $platformRepo)
20460 {
20461 $request = new Request();
20462
20463 $constraint = new Constraint('=', $rootPackage->getVersion());
20464 $constraint->setPrettyString($rootPackage->getPrettyVersion());
20465 $request->install($rootPackage->getName(), $constraint);
20466
20467 $fixedPackages = $platformRepo->getPackages();
20468 if ($this->additionalInstalledRepository) {
20469 $additionalFixedPackages = $this->additionalInstalledRepository->getPackages();
20470 $fixedPackages = array_merge($fixedPackages, $additionalFixedPackages);
20471 }
20472
20473
20474  
20475  $provided = $rootPackage->getProvides();
20476 foreach ($fixedPackages as $package) {
20477 $constraint = new Constraint('=', $package->getVersion());
20478 $constraint->setPrettyString($package->getPrettyVersion());
20479
20480
20481  if ($package->getRepository() !== $platformRepo
20482 || !isset($provided[$package->getName()])
20483 || !$provided[$package->getName()]->getConstraint()->matches($constraint)
20484 ) {
20485 $request->fix($package->getName(), $constraint);
20486 }
20487 }
20488
20489 return $request;
20490 }
20491
20492
20493
20494
20495
20496
20497
20498
20499
20500
20501
20502
20503 private function processDevPackages($localRepo, $pool, $policy, $repositories, $installedRepo, $lockedRepository, $task, array $operations = null)
20504 {
20505 if ($task === 'force-updates' && null === $operations) {
20506 throw new \InvalidArgumentException('Missing operations argument');
20507 }
20508 if ($task === 'force-links') {
20509 $operations = array();
20510 }
20511
20512 if ($this->update && $this->updateWhitelist) {
20513 $currentPackages = $this->getCurrentPackages($installedRepo);
20514 }
20515
20516 foreach ($localRepo->getCanonicalPackages() as $package) {
20517
20518  if (!$package->isDev()) {
20519 continue;
20520 }
20521
20522
20523  foreach ($operations as $operation) {
20524 if (('update' === $operation->getJobType() && $operation->getInitialPackage()->equals($package))
20525 || ('uninstall' === $operation->getJobType() && $operation->getPackage()->equals($package))
20526 ) {
20527 continue 2;
20528 }
20529 }
20530
20531 if ($this->update) {
20532
20533  if ($this->updateWhitelist && !$this->isUpdateable($package)) {
20534
20535  foreach ($currentPackages as $curPackage) {
20536 if ($curPackage->isDev() && $curPackage->getName() === $package->getName() && $curPackage->getVersion() === $package->getVersion()) {
20537 if ($task === 'force-links') {
20538 $package->setRequires($curPackage->getRequires());
20539 $package->setConflicts($curPackage->getConflicts());
20540 $package->setProvides($curPackage->getProvides());
20541 $package->setReplaces($curPackage->getReplaces());
20542 } elseif ($task === 'force-updates') {
20543 if (($curPackage->getSourceReference() && $curPackage->getSourceReference() !== $package->getSourceReference())
20544 || ($curPackage->getDistReference() && $curPackage->getDistReference() !== $package->getDistReference())
20545 ) {
20546 $operations[] = new UpdateOperation($package, $curPackage);
20547 }
20548 }
20549
20550 break;
20551 }
20552 }
20553
20554 continue;
20555 }
20556
20557
20558  $matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion()));
20559 foreach ($matches as $index => $match) {
20560
20561  if (!in_array($match->getRepository(), $repositories, true)) {
20562 unset($matches[$index]);
20563 continue;
20564 }
20565
20566
20567  if ($match->getName() !== $package->getName()) {
20568 unset($matches[$index]);
20569 continue;
20570 }
20571
20572 $matches[$index] = $match->getId();
20573 }
20574
20575
20576  if ($matches && $matches = $policy->selectPreferredPackages($pool, array(), $matches)) {
20577 $newPackage = $pool->literalToPackage($matches[0]);
20578
20579 if ($task === 'force-links' && $newPackage) {
20580 $package->setRequires($newPackage->getRequires());
20581 $package->setConflicts($newPackage->getConflicts());
20582 $package->setProvides($newPackage->getProvides());
20583 $package->setReplaces($newPackage->getReplaces());
20584 }
20585
20586 if ($task === 'force-updates' && $newPackage && (
20587 (($newPackage->getSourceReference() && $newPackage->getSourceReference() !== $package->getSourceReference())
20588 || ($newPackage->getDistReference() && $newPackage->getDistReference() !== $package->getDistReference())
20589 )
20590 )) {
20591 $operations[] = new UpdateOperation($package, $newPackage);
20592
20593 continue;
20594 }
20595 }
20596
20597 if ($task === 'force-updates') {
20598
20599  $references = $this->package->getReferences();
20600
20601 if (isset($references[$package->getName()]) && $references[$package->getName()] !== $package->getSourceReference()) {
20602
20603  $operations[] = new UpdateOperation($package, clone $package);
20604 }
20605 }
20606 } else {
20607
20608  foreach ($lockedRepository->findPackages($package->getName()) as $lockedPackage) {
20609 if ($lockedPackage->isDev() && $lockedPackage->getVersion() === $package->getVersion()) {
20610 if ($task === 'force-links') {
20611 $package->setRequires($lockedPackage->getRequires());
20612 $package->setConflicts($lockedPackage->getConflicts());
20613 $package->setProvides($lockedPackage->getProvides());
20614 $package->setReplaces($lockedPackage->getReplaces());
20615 } elseif ($task === 'force-updates') {
20616 if (($lockedPackage->getSourceReference() && $lockedPackage->getSourceReference() !== $package->getSourceReference())
20617 || ($lockedPackage->getDistReference() && $lockedPackage->getDistReference() !== $package->getDistReference())
20618 ) {
20619 $operations[] = new UpdateOperation($package, $lockedPackage);
20620 }
20621 }
20622
20623 break;
20624 }
20625 }
20626 }
20627 }
20628
20629 return $operations;
20630 }
20631
20632
20633
20634
20635
20636
20637 private function getCurrentPackages($installedRepo)
20638 {
20639 if ($this->locker->isLocked()) {
20640 try {
20641 return $this->locker->getLockedRepository(true)->getPackages();
20642 } catch (\RuntimeException $e) {
20643
20644  return $this->locker->getLockedRepository()->getPackages();
20645 }
20646 }
20647
20648 return $installedRepo->getPackages();
20649 }
20650
20651
20652
20653
20654 private function getRootAliases()
20655 {
20656 if ($this->update) {
20657 $aliases = $this->package->getAliases();
20658 } else {
20659 $aliases = $this->locker->getAliases();
20660 }
20661
20662 $normalizedAliases = array();
20663
20664 foreach ($aliases as $alias) {
20665 $normalizedAliases[$alias['package']][$alias['version']] = array(
20666 'alias' => $alias['alias'],
20667 'alias_normalized' => $alias['alias_normalized'],
20668 );
20669 }
20670
20671 return $normalizedAliases;
20672 }
20673
20674
20675
20676
20677
20678
20679
20680 private function processPackageUrls($pool, $policy, $localRepo, $repositories)
20681 {
20682 if (!$this->update) {
20683 return;
20684 }
20685
20686 $rootRefs = $this->package->getReferences();
20687
20688 foreach ($localRepo->getCanonicalPackages() as $package) {
20689
20690  $matches = $pool->whatProvides($package->getName(), new Constraint('=', $package->getVersion()));
20691 foreach ($matches as $index => $match) {
20692
20693  if (!in_array($match->getRepository(), $repositories, true)) {
20694 unset($matches[$index]);
20695 continue;
20696 }
20697
20698
20699  if ($match->getName() !== $package->getName()) {
20700 unset($matches[$index]);
20701 continue;
20702 }
20703
20704 $matches[$index] = $match->getId();
20705 }
20706
20707
20708  if ($matches && $matches = $policy->selectPreferredPackages($pool, array(), $matches)) {
20709 $newPackage = $pool->literalToPackage($matches[0]);
20710
20711
20712  $sourceUrl = $package->getSourceUrl();
20713 $newSourceUrl = $newPackage->getSourceUrl();
20714 $newReference = $newPackage->getSourceReference();
20715
20716 if ($package->isDev() && isset($rootRefs[$package->getName()]) && $package->getSourceReference() === $rootRefs[$package->getName()]) {
20717 $newReference = $rootRefs[$package->getName()];
20718 }
20719
20720 $this->updatePackageUrl($package, $newSourceUrl, $newPackage->getSourceType(), $newReference, $newPackage->getDistUrl());
20721
20722 if ($package instanceof CompletePackage && $newPackage instanceof CompletePackage) {
20723 $package->setAbandoned($newPackage->getReplacementPackage() ?: $newPackage->isAbandoned());
20724 }
20725
20726 $package->setDistMirrors($newPackage->getDistMirrors());
20727 $package->setSourceMirrors($newPackage->getSourceMirrors());
20728 }
20729 }
20730 }
20731
20732 private function updatePackageUrl(PackageInterface $package, $sourceUrl, $sourceType, $sourceReference, $distUrl)
20733 {
20734 $oldSourceRef = $package->getSourceReference();
20735
20736 if ($package->getSourceUrl() !== $sourceUrl) {
20737 $package->setSourceType($sourceType);
20738 $package->setSourceUrl($sourceUrl);
20739 $package->setSourceReference($sourceReference);
20740 }
20741
20742
20743  
20744  if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com)/}i', $distUrl)) {
20745 $package->setDistUrl($distUrl);
20746 $this->updateInstallReferences($package, $sourceReference);
20747 }
20748
20749 if ($this->updateWhitelist && !$this->isUpdateable($package)) {
20750 $this->updateInstallReferences($package, $oldSourceRef);
20751 }
20752 }
20753
20754 private function updateInstallReferences(PackageInterface $package, $reference)
20755 {
20756 if (!$reference) {
20757 return;
20758 }
20759
20760 $package->setSourceReference($reference);
20761
20762 if (preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com)/}i', $package->getDistUrl())) {
20763 $package->setDistReference($reference);
20764 $package->setDistUrl(preg_replace('{(?<=/)[a-f0-9]{40}(?=/|$)}i', $reference, $package->getDistUrl()));
20765 } else if ($package->getDistReference()) { 
20766  $package->setDistReference($reference);
20767 }
20768 }
20769
20770
20771
20772
20773
20774 private function aliasPlatformPackages(PlatformRepository $platformRepo, $aliases)
20775 {
20776 foreach ($aliases as $package => $versions) {
20777 foreach ($versions as $version => $alias) {
20778 $packages = $platformRepo->findPackages($package, $version);
20779 foreach ($packages as $package) {
20780 $aliasPackage = new AliasPackage($package, $alias['alias_normalized'], $alias['alias']);
20781 $aliasPackage->setRootPackageAlias(true);
20782 $platformRepo->addPackage($aliasPackage);
20783 }
20784 }
20785 }
20786 }
20787
20788
20789
20790
20791
20792 private function isUpdateable(PackageInterface $package)
20793 {
20794 if (!$this->updateWhitelist) {
20795 throw new \LogicException('isUpdateable should only be called when a whitelist is present');
20796 }
20797
20798 foreach ($this->updateWhitelist as $whiteListedPattern => $void) {
20799 $patternRegexp = $this->packageNameToRegexp($whiteListedPattern);
20800 if (preg_match($patternRegexp, $package->getName())) {
20801 return true;
20802 }
20803 }
20804
20805 return false;
20806 }
20807
20808
20809
20810
20811
20812
20813
20814 private function packageNameToRegexp($whiteListedPattern)
20815 {
20816 $cleanedWhiteListedPattern = str_replace('\\*', '.*', preg_quote($whiteListedPattern));
20817
20818 return "{^" . $cleanedWhiteListedPattern . "$}i";
20819 }
20820
20821
20822
20823
20824
20825 private function extractPlatformRequirements($links)
20826 {
20827 $platformReqs = array();
20828 foreach ($links as $link) {
20829 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
20830 $platformReqs[$link->getTarget()] = $link->getPrettyConstraint();
20831 }
20832 }
20833
20834 return $platformReqs;
20835 }
20836
20837
20838
20839
20840
20841
20842
20843
20844
20845
20846
20847
20848
20849
20850 private function whitelistUpdateDependencies($localOrLockRepo, array $rootRequires, array $rootDevRequires)
20851 {
20852 if (!$this->updateWhitelist) {
20853 return;
20854 }
20855
20856 $rootRequires = array_merge($rootRequires, $rootDevRequires);
20857
20858 $requiredPackageNames = array();
20859 foreach ($rootRequires as $require) {
20860 $requiredPackageNames[] = $require->getTarget();
20861 }
20862
20863 $skipPackages = array();
20864 foreach ($rootRequires as $require) {
20865 $skipPackages[$require->getTarget()] = true;
20866 }
20867
20868 $pool = new Pool('dev');
20869 $pool->addRepository($localOrLockRepo);
20870
20871 $seen = array();
20872
20873 $rootRequiredPackageNames = array_keys($rootRequires);
20874
20875 foreach ($this->updateWhitelist as $packageName => $void) {
20876 $packageQueue = new \SplQueue;
20877
20878 $depPackages = $pool->whatProvides($packageName);
20879
20880 $nameMatchesRequiredPackage = in_array($packageName, $requiredPackageNames, true);
20881
20882
20883  if (!$nameMatchesRequiredPackage) {
20884 $whitelistPatternRegexp = $this->packageNameToRegexp($packageName);
20885 foreach ($rootRequiredPackageNames as $rootRequiredPackageName) {
20886 if (preg_match($whitelistPatternRegexp, $rootRequiredPackageName)) {
20887 $nameMatchesRequiredPackage = true;
20888 break;
20889 }
20890 }
20891 }
20892
20893 if (count($depPackages) == 0 && !$nameMatchesRequiredPackage && !in_array($packageName, array('nothing', 'lock', 'mirrors'))) {
20894 $this->io->writeError('<warning>Package "' . $packageName . '" listed for update is not installed. Ignoring.</warning>');
20895 }
20896
20897 foreach ($depPackages as $depPackage) {
20898 $packageQueue->enqueue($depPackage);
20899 }
20900
20901 while (!$packageQueue->isEmpty()) {
20902 $package = $packageQueue->dequeue();
20903 if (isset($seen[$package->getId()])) {
20904 continue;
20905 }
20906
20907 $seen[$package->getId()] = true;
20908 $this->updateWhitelist[$package->getName()] = true;
20909
20910 if (!$this->whitelistDependencies) {
20911 continue;
20912 }
20913
20914 $requires = $package->getRequires();
20915
20916 foreach ($requires as $require) {
20917 $requirePackages = $pool->whatProvides($require->getTarget());
20918
20919 foreach ($requirePackages as $requirePackage) {
20920 if (isset($this->updateWhitelist[$requirePackage->getName()])) {
20921 continue;
20922 }
20923
20924 if (isset($skipPackages[$requirePackage->getName()])) {
20925 $this->io->writeError('<warning>Dependency "' . $requirePackage->getName() . '" is also a root requirement, but is not explicitly whitelisted. Ignoring.</warning>');
20926 continue;
20927 }
20928
20929 $packageQueue->enqueue($requirePackage);
20930 }
20931 }
20932 }
20933 }
20934 }
20935
20936
20937
20938
20939
20940
20941
20942
20943 private function mockLocalRepositories(RepositoryManager $rm)
20944 {
20945 $packages = array();
20946 foreach ($rm->getLocalRepository()->getPackages() as $package) {
20947 $packages[(string) $package] = clone $package;
20948 }
20949 foreach ($packages as $key => $package) {
20950 if ($package instanceof AliasPackage) {
20951 $alias = (string) $package->getAliasOf();
20952 $packages[$key] = new AliasPackage($packages[$alias], $package->getVersion(), $package->getPrettyVersion());
20953 }
20954 }
20955 $rm->setLocalRepository(
20956 new InstalledArrayRepository($packages)
20957 );
20958 }
20959
20960
20961
20962
20963
20964
20965
20966
20967 public static function create(IOInterface $io, Composer $composer)
20968 {
20969 return new static(
20970 $io,
20971 $composer->getConfig(),
20972 $composer->getPackage(),
20973 $composer->getDownloadManager(),
20974 $composer->getRepositoryManager(),
20975 $composer->getLocker(),
20976 $composer->getInstallationManager(),
20977 $composer->getEventDispatcher(),
20978 $composer->getAutoloadGenerator()
20979 );
20980 }
20981
20982
20983
20984
20985
20986 public function setAdditionalInstalledRepository(RepositoryInterface $additionalInstalledRepository)
20987 {
20988 $this->additionalInstalledRepository = $additionalInstalledRepository;
20989
20990 return $this;
20991 }
20992
20993
20994
20995
20996
20997
20998
20999 public function setDryRun($dryRun = true)
21000 {
21001 $this->dryRun = (bool) $dryRun;
21002
21003 return $this;
21004 }
21005
21006
21007
21008
21009
21010
21011 public function isDryRun()
21012 {
21013 return $this->dryRun;
21014 }
21015
21016
21017
21018
21019
21020
21021
21022 public function setPreferSource($preferSource = true)
21023 {
21024 $this->preferSource = (bool) $preferSource;
21025
21026 return $this;
21027 }
21028
21029
21030
21031
21032
21033
21034
21035 public function setPreferDist($preferDist = true)
21036 {
21037 $this->preferDist = (bool) $preferDist;
21038
21039 return $this;
21040 }
21041
21042
21043
21044
21045
21046
21047
21048 public function setOptimizeAutoloader($optimizeAutoloader = false)
21049 {
21050 $this->optimizeAutoloader = (bool) $optimizeAutoloader;
21051 if (!$this->optimizeAutoloader) {
21052
21053  
21054  $this->setClassMapAuthoritative(false);
21055 }
21056
21057 return $this;
21058 }
21059
21060
21061
21062
21063
21064
21065
21066
21067 public function setClassMapAuthoritative($classMapAuthoritative = false)
21068 {
21069 $this->classMapAuthoritative = (bool) $classMapAuthoritative;
21070 if ($this->classMapAuthoritative) {
21071
21072  $this->setOptimizeAutoloader(true);
21073 }
21074
21075 return $this;
21076 }
21077
21078
21079
21080
21081
21082
21083
21084 public function setApcuAutoloader($apcuAutoloader = false)
21085 {
21086 $this->apcuAutoloader = (bool) $apcuAutoloader;
21087
21088 return $this;
21089 }
21090
21091
21092
21093
21094
21095
21096
21097 public function setUpdate($update = true)
21098 {
21099 $this->update = (bool) $update;
21100
21101 return $this;
21102 }
21103
21104
21105
21106
21107
21108
21109
21110 public function setDevMode($devMode = true)
21111 {
21112 $this->devMode = (bool) $devMode;
21113
21114 return $this;
21115 }
21116
21117
21118
21119
21120
21121
21122
21123
21124
21125 public function setDumpAutoloader($dumpAutoloader = true)
21126 {
21127 $this->dumpAutoloader = (bool) $dumpAutoloader;
21128
21129 return $this;
21130 }
21131
21132
21133
21134
21135
21136
21137
21138
21139
21140 public function setRunScripts($runScripts = true)
21141 {
21142 $this->runScripts = (bool) $runScripts;
21143
21144 return $this;
21145 }
21146
21147
21148
21149
21150
21151
21152
21153 public function setConfig(Config $config)
21154 {
21155 $this->config = $config;
21156
21157 return $this;
21158 }
21159
21160
21161
21162
21163
21164
21165
21166 public function setVerbose($verbose = true)
21167 {
21168 $this->verbose = (bool) $verbose;
21169
21170 return $this;
21171 }
21172
21173
21174
21175
21176
21177
21178 public function isVerbose()
21179 {
21180 return $this->verbose;
21181 }
21182
21183
21184
21185
21186
21187
21188
21189 public function setIgnorePlatformRequirements($ignorePlatformReqs = false)
21190 {
21191 $this->ignorePlatformReqs = (bool) $ignorePlatformReqs;
21192
21193 return $this;
21194 }
21195
21196
21197
21198
21199
21200
21201
21202
21203 public function setUpdateWhitelist(array $packages)
21204 {
21205 $this->updateWhitelist = array_flip(array_map('strtolower', $packages));
21206
21207 return $this;
21208 }
21209
21210
21211
21212
21213
21214
21215
21216 public function setWhitelistDependencies($updateDependencies = true)
21217 {
21218 $this->whitelistDependencies = (bool) $updateDependencies;
21219
21220 return $this;
21221 }
21222
21223
21224
21225
21226
21227
21228
21229 public function setPreferStable($preferStable = true)
21230 {
21231 $this->preferStable = (bool) $preferStable;
21232
21233 return $this;
21234 }
21235
21236
21237
21238
21239
21240
21241
21242 public function setPreferLowest($preferLowest = true)
21243 {
21244 $this->preferLowest = (bool) $preferLowest;
21245
21246 return $this;
21247 }
21248
21249
21250
21251
21252
21253
21254
21255
21256
21257 public function setWriteLock($writeLock = true)
21258 {
21259 $this->writeLock = (bool) $writeLock;
21260
21261 return $this;
21262 }
21263
21264
21265
21266
21267
21268
21269
21270
21271
21272 public function setExecuteOperations($executeOperations = true)
21273 {
21274 $this->executeOperations = (bool) $executeOperations;
21275
21276 return $this;
21277 }
21278
21279
21280
21281
21282
21283
21284
21285 public function setSkipSuggest($skipSuggest = true)
21286 {
21287 $this->skipSuggest = (bool) $skipSuggest;
21288
21289 return $this;
21290 }
21291
21292
21293
21294
21295
21296
21297
21298
21299
21300
21301 public function disablePlugins()
21302 {
21303 $this->installationManager->disablePlugins();
21304
21305 return $this;
21306 }
21307
21308
21309
21310
21311
21312 public function setSuggestedPackagesReporter(SuggestedPackagesReporter $suggestedPackagesReporter)
21313 {
21314 $this->suggestedPackagesReporter = $suggestedPackagesReporter;
21315
21316 return $this;
21317 }
21318 }
21319 <?php
21320
21321
21322
21323
21324
21325
21326
21327
21328
21329
21330
21331 namespace Composer\Installer;
21332
21333 use Composer\IO\IOInterface;
21334 use Composer\Package\PackageInterface;
21335 use Composer\Util\Filesystem;
21336 use Composer\Util\Platform;
21337 use Composer\Util\ProcessExecutor;
21338 use Composer\Util\Silencer;
21339
21340
21341
21342
21343
21344
21345
21346
21347 class BinaryInstaller
21348 {
21349 protected $binDir;
21350 protected $binCompat;
21351 protected $io;
21352 protected $filesystem;
21353
21354
21355
21356
21357
21358
21359
21360 public function __construct(IOInterface $io, $binDir, $binCompat, Filesystem $filesystem = null)
21361 {
21362 $this->binDir = $binDir;
21363 $this->binCompat = $binCompat;
21364 $this->io = $io;
21365 $this->filesystem = $filesystem ?: new Filesystem();
21366 }
21367
21368 public function installBinaries(PackageInterface $package, $installPath, $warnOnOverwrite = true)
21369 {
21370 $binaries = $this->getBinaries($package);
21371 if (!$binaries) {
21372 return;
21373 }
21374 foreach ($binaries as $bin) {
21375 $binPath = $installPath.'/'.$bin;
21376 if (!file_exists($binPath)) {
21377 $this->io->writeError('    <warning>Skipped installation of bin '.$bin.' for package '.$package->getName().': file not found in package</warning>');
21378 continue;
21379 }
21380
21381
21382  
21383  
21384  
21385  $binPath = realpath($binPath);
21386
21387 $this->initializeBinDir();
21388 $link = $this->binDir.'/'.basename($bin);
21389 if (file_exists($link)) {
21390 if (is_link($link)) {
21391
21392  
21393  
21394  Silencer::call('chmod', $link, 0777 & ~umask());
21395 }
21396 if ($warnOnOverwrite) {
21397 $this->io->writeError('    Skipped installation of bin '.$bin.' for package '.$package->getName().': name conflicts with an existing file');
21398 }
21399 continue;
21400 }
21401
21402 if ($this->binCompat === "auto") {
21403 if (Platform::isWindows()) {
21404 $this->installFullBinaries($binPath, $link, $bin, $package);
21405 } else {
21406 $this->installSymlinkBinaries($binPath, $link);
21407 }
21408 } elseif ($this->binCompat === "full") {
21409 $this->installFullBinaries($binPath, $link, $bin, $package);
21410 }
21411 Silencer::call('chmod', $link, 0777 & ~umask());
21412 }
21413 }
21414
21415 public function removeBinaries(PackageInterface $package)
21416 {
21417 $this->initializeBinDir();
21418
21419 $binaries = $this->getBinaries($package);
21420 if (!$binaries) {
21421 return;
21422 }
21423 foreach ($binaries as $bin) {
21424 $link = $this->binDir.'/'.basename($bin);
21425 if (is_link($link) || file_exists($link)) {
21426 $this->filesystem->unlink($link);
21427 }
21428 if (file_exists($link.'.bat')) {
21429 $this->filesystem->unlink($link.'.bat');
21430 }
21431 }
21432
21433
21434  if ((is_dir($this->binDir)) && ($this->filesystem->isDirEmpty($this->binDir))) {
21435 Silencer::call('rmdir', $this->binDir);
21436 }
21437 }
21438
21439 public static function determineBinaryCaller($bin)
21440 {
21441 if ('.bat' === substr($bin, -4) || '.exe' === substr($bin, -4)) {
21442 return 'call';
21443 }
21444
21445 $handle = fopen($bin, 'r');
21446 $line = fgets($handle);
21447 fclose($handle);
21448 if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) {
21449 return trim($match[1]);
21450 }
21451
21452 return 'php';
21453 }
21454
21455 protected function getBinaries(PackageInterface $package)
21456 {
21457 return $package->getBinaries();
21458 }
21459
21460 protected function installFullBinaries($binPath, $link, $bin, PackageInterface $package)
21461 {
21462
21463  if ('.bat' !== substr($binPath, -4)) {
21464 $this->installUnixyProxyBinaries($binPath, $link);
21465 @chmod($link, 0777 & ~umask());
21466 $link .= '.bat';
21467 if (file_exists($link)) {
21468 $this->io->writeError('    Skipped installation of bin '.$bin.'.bat proxy for package '.$package->getName().': a .bat proxy was already installed');
21469 }
21470 }
21471 if (!file_exists($link)) {
21472 file_put_contents($link, $this->generateWindowsProxyCode($binPath, $link));
21473 }
21474 }
21475
21476 protected function installSymlinkBinaries($binPath, $link)
21477 {
21478 if (!$this->filesystem->relativeSymlink($binPath, $link)) {
21479 $this->installUnixyProxyBinaries($binPath, $link);
21480 }
21481 }
21482
21483 protected function installUnixyProxyBinaries($binPath, $link)
21484 {
21485 file_put_contents($link, $this->generateUnixyProxyCode($binPath, $link));
21486 }
21487
21488 protected function initializeBinDir()
21489 {
21490 $this->filesystem->ensureDirectoryExists($this->binDir);
21491 $this->binDir = realpath($this->binDir);
21492 }
21493
21494 protected function generateWindowsProxyCode($bin, $link)
21495 {
21496 $binPath = $this->filesystem->findShortestPath($link, $bin);
21497 $caller = self::determineBinaryCaller($bin);
21498
21499 return "@ECHO OFF\r\n".
21500 "setlocal DISABLEDELAYEDEXPANSION\r\n".
21501 "SET BIN_TARGET=%~dp0/".trim(ProcessExecutor::escape($binPath), '"\'')."\r\n".
21502 "{$caller} \"%BIN_TARGET%\" %*\r\n";
21503 }
21504
21505 protected function generateUnixyProxyCode($bin, $link)
21506 {
21507 $binPath = $this->filesystem->findShortestPath($link, $bin);
21508
21509 $binDir = ProcessExecutor::escape(dirname($binPath));
21510 $binFile = basename($binPath);
21511
21512 $proxyCode = <<<PROXY
21513 #!/usr/bin/env sh
21514
21515 dir=$(d=\${0%[/\\\\]*}; cd "\$d" > /dev/null; cd $binDir && pwd)
21516
21517 # See if we are running in Cygwin by checking for cygpath program
21518 if command -v 'cygpath' >/dev/null 2>&1; then
21519         # Cygwin paths start with /cygdrive/ which will break windows PHP,
21520         # so we need to translate the dir path to windows format. However
21521         # we could be using cygwin PHP which does not require this, so we
21522         # test if the path to PHP starts with /cygdrive/ rather than /usr/bin
21523         if [[ $(which php) == /cygdrive/* ]]; then
21524                 dir=$(cygpath -m "\$dir");
21525         fi
21526 fi
21527
21528 dir=$(echo \$dir | sed 's/ /\ /g')
21529 "\${dir}/$binFile" "$@"
21530
21531 PROXY;
21532
21533 return $proxyCode;
21534 }
21535 }
21536 <?php
21537
21538
21539
21540
21541
21542
21543
21544
21545
21546
21547
21548 namespace Composer\Installer;
21549
21550 use Composer\Package\PackageInterface;
21551
21552
21553
21554
21555
21556
21557 interface BinaryPresenceInterface
21558 {
21559
21560
21561
21562
21563
21564 public function ensureBinariesPresence(PackageInterface $package);
21565 }
21566 <?php
21567
21568
21569
21570
21571
21572
21573
21574
21575
21576
21577
21578 namespace Composer\Installer;
21579
21580 use Composer\IO\IOInterface;
21581 use Composer\Package\PackageInterface;
21582 use Composer\Package\AliasPackage;
21583 use Composer\Repository\RepositoryInterface;
21584 use Composer\Repository\InstalledRepositoryInterface;
21585 use Composer\DependencyResolver\Operation\OperationInterface;
21586 use Composer\DependencyResolver\Operation\InstallOperation;
21587 use Composer\DependencyResolver\Operation\UpdateOperation;
21588 use Composer\DependencyResolver\Operation\UninstallOperation;
21589 use Composer\DependencyResolver\Operation\MarkAliasInstalledOperation;
21590 use Composer\DependencyResolver\Operation\MarkAliasUninstalledOperation;
21591 use Composer\Util\StreamContextFactory;
21592
21593
21594
21595
21596
21597
21598
21599
21600 class InstallationManager
21601 {
21602 private $installers = array();
21603 private $cache = array();
21604 private $notifiablePackages = array();
21605
21606 public function reset()
21607 {
21608 $this->notifiablePackages = array();
21609 }
21610
21611
21612
21613
21614
21615
21616 public function addInstaller(InstallerInterface $installer)
21617 {
21618 array_unshift($this->installers, $installer);
21619 $this->cache = array();
21620 }
21621
21622
21623
21624
21625
21626
21627 public function removeInstaller(InstallerInterface $installer)
21628 {
21629 if (false !== ($key = array_search($installer, $this->installers, true))) {
21630 array_splice($this->installers, $key, 1);
21631 $this->cache = array();
21632 }
21633 }
21634
21635
21636
21637
21638
21639
21640
21641
21642 public function disablePlugins()
21643 {
21644 foreach ($this->installers as $i => $installer) {
21645 if (!$installer instanceof PluginInstaller) {
21646 continue;
21647 }
21648
21649 unset($this->installers[$i]);
21650 }
21651 }
21652
21653
21654
21655
21656
21657
21658
21659
21660
21661 public function getInstaller($type)
21662 {
21663 $type = strtolower($type);
21664
21665 if (isset($this->cache[$type])) {
21666 return $this->cache[$type];
21667 }
21668
21669 foreach ($this->installers as $installer) {
21670 if ($installer->supports($type)) {
21671 return $this->cache[$type] = $installer;
21672 }
21673 }
21674
21675 throw new \InvalidArgumentException('Unknown installer type: '.$type);
21676 }
21677
21678
21679
21680
21681
21682
21683
21684
21685
21686 public function isPackageInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
21687 {
21688 if ($package instanceof AliasPackage) {
21689 return $repo->hasPackage($package) && $this->isPackageInstalled($repo, $package->getAliasOf());
21690 }
21691
21692 return $this->getInstaller($package->getType())->isInstalled($repo, $package);
21693 }
21694
21695
21696
21697
21698
21699
21700
21701 public function ensureBinariesPresence(PackageInterface $package)
21702 {
21703 try {
21704 $installer = $this->getInstaller($package->getType());
21705 } catch (\InvalidArgumentException $e) {
21706
21707  return;
21708 }
21709
21710
21711  if ($installer instanceof BinaryPresenceInterface) {
21712 $installer->ensureBinariesPresence($package);
21713 }
21714 }
21715
21716
21717
21718
21719
21720
21721
21722 public function execute(RepositoryInterface $repo, OperationInterface $operation)
21723 {
21724 $method = $operation->getJobType();
21725 $this->$method($repo, $operation);
21726 }
21727
21728
21729
21730
21731
21732
21733
21734 public function install(RepositoryInterface $repo, InstallOperation $operation)
21735 {
21736 $package = $operation->getPackage();
21737 $installer = $this->getInstaller($package->getType());
21738 $installer->install($repo, $package);
21739 $this->markForNotification($package);
21740 }
21741
21742
21743
21744
21745
21746
21747
21748 public function update(RepositoryInterface $repo, UpdateOperation $operation)
21749 {
21750 $initial = $operation->getInitialPackage();
21751 $target = $operation->getTargetPackage();
21752
21753 $initialType = $initial->getType();
21754 $targetType = $target->getType();
21755
21756 if ($initialType === $targetType) {
21757 $installer = $this->getInstaller($initialType);
21758 $installer->update($repo, $initial, $target);
21759 $this->markForNotification($target);
21760 } else {
21761 $this->getInstaller($initialType)->uninstall($repo, $initial);
21762 $this->getInstaller($targetType)->install($repo, $target);
21763 }
21764 }
21765
21766
21767
21768
21769
21770
21771
21772 public function uninstall(RepositoryInterface $repo, UninstallOperation $operation)
21773 {
21774 $package = $operation->getPackage();
21775 $installer = $this->getInstaller($package->getType());
21776 $installer->uninstall($repo, $package);
21777 }
21778
21779
21780
21781
21782
21783
21784
21785 public function markAliasInstalled(RepositoryInterface $repo, MarkAliasInstalledOperation $operation)
21786 {
21787 $package = $operation->getPackage();
21788
21789 if (!$repo->hasPackage($package)) {
21790 $repo->addPackage(clone $package);
21791 }
21792 }
21793
21794
21795
21796
21797
21798
21799
21800 public function markAliasUninstalled(RepositoryInterface $repo, MarkAliasUninstalledOperation $operation)
21801 {
21802 $package = $operation->getPackage();
21803
21804 $repo->removePackage($package);
21805 }
21806
21807
21808
21809
21810
21811
21812
21813 public function getInstallPath(PackageInterface $package)
21814 {
21815 $installer = $this->getInstaller($package->getType());
21816
21817 return $installer->getInstallPath($package);
21818 }
21819
21820 public function notifyInstalls(IOInterface $io)
21821 {
21822 foreach ($this->notifiablePackages as $repoUrl => $packages) {
21823 $repositoryName = parse_url($repoUrl, PHP_URL_HOST);
21824 if ($io->hasAuthentication($repositoryName)) {
21825 $auth = $io->getAuthentication($repositoryName);
21826 $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
21827 $authHeader = 'Authorization: Basic '.$authStr;
21828 }
21829
21830
21831  if (strpos($repoUrl, '%package%')) {
21832 foreach ($packages as $package) {
21833 $url = str_replace('%package%', $package->getPrettyName(), $repoUrl);
21834
21835 $params = array(
21836 'version' => $package->getPrettyVersion(),
21837 'version_normalized' => $package->getVersion(),
21838 );
21839 $opts = array('http' =>
21840 array(
21841 'method' => 'POST',
21842 'header' => array('Content-type: application/x-www-form-urlencoded'),
21843 'content' => http_build_query($params, '', '&'),
21844 'timeout' => 3,
21845 ),
21846 );
21847 if (isset($authHeader)) {
21848 $opts['http']['header'][] = $authHeader;
21849 }
21850
21851 $context = StreamContextFactory::getContext($url, $opts);
21852 @file_get_contents($url, false, $context);
21853 }
21854
21855 continue;
21856 }
21857
21858 $postData = array('downloads' => array());
21859 foreach ($packages as $package) {
21860 $postData['downloads'][] = array(
21861 'name' => $package->getPrettyName(),
21862 'version' => $package->getVersion(),
21863 );
21864 }
21865
21866 $opts = array('http' =>
21867 array(
21868 'method' => 'POST',
21869 'header' => array('Content-Type: application/json'),
21870 'content' => json_encode($postData),
21871 'timeout' => 6,
21872 ),
21873 );
21874 if (isset($authHeader)) {
21875 $opts['http']['header'][] = $authHeader;
21876 }
21877
21878 $context = StreamContextFactory::getContext($repoUrl, $opts);
21879 @file_get_contents($repoUrl, false, $context);
21880 }
21881
21882 $this->reset();
21883 }
21884
21885 private function markForNotification(PackageInterface $package)
21886 {
21887 if ($package->getNotificationUrl()) {
21888 $this->notifiablePackages[$package->getNotificationUrl()][$package->getName()] = $package;
21889 }
21890 }
21891 }
21892 <?php
21893
21894
21895
21896
21897
21898
21899
21900
21901
21902
21903
21904 namespace Composer\Installer;
21905
21906 use Composer\Composer;
21907 use Composer\DependencyResolver\PolicyInterface;
21908 use Composer\DependencyResolver\Operation\OperationInterface;
21909 use Composer\DependencyResolver\Pool;
21910 use Composer\DependencyResolver\Request;
21911 use Composer\EventDispatcher\Event;
21912 use Composer\IO\IOInterface;
21913 use Composer\Repository\CompositeRepository;
21914
21915
21916
21917
21918
21919
21920 class InstallerEvent extends Event
21921 {
21922
21923
21924
21925 private $composer;
21926
21927
21928
21929
21930 private $io;
21931
21932
21933
21934
21935 private $devMode;
21936
21937
21938
21939
21940 private $policy;
21941
21942
21943
21944
21945 private $pool;
21946
21947
21948
21949
21950 private $installedRepo;
21951
21952
21953
21954
21955 private $request;
21956
21957
21958
21959
21960 private $operations;
21961
21962
21963
21964
21965
21966
21967
21968
21969
21970
21971
21972
21973
21974
21975 public function __construct($eventName, Composer $composer, IOInterface $io, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations = array())
21976 {
21977 parent::__construct($eventName);
21978
21979 $this->composer = $composer;
21980 $this->io = $io;
21981 $this->devMode = $devMode;
21982 $this->policy = $policy;
21983 $this->pool = $pool;
21984 $this->installedRepo = $installedRepo;
21985 $this->request = $request;
21986 $this->operations = $operations;
21987 }
21988
21989
21990
21991
21992 public function getComposer()
21993 {
21994 return $this->composer;
21995 }
21996
21997
21998
21999
22000 public function getIO()
22001 {
22002 return $this->io;
22003 }
22004
22005
22006
22007
22008 public function isDevMode()
22009 {
22010 return $this->devMode;
22011 }
22012
22013
22014
22015
22016 public function getPolicy()
22017 {
22018 return $this->policy;
22019 }
22020
22021
22022
22023
22024 public function getPool()
22025 {
22026 return $this->pool;
22027 }
22028
22029
22030
22031
22032 public function getInstalledRepo()
22033 {
22034 return $this->installedRepo;
22035 }
22036
22037
22038
22039
22040 public function getRequest()
22041 {
22042 return $this->request;
22043 }
22044
22045
22046
22047
22048 public function getOperations()
22049 {
22050 return $this->operations;
22051 }
22052 }
22053 <?php
22054
22055
22056
22057
22058
22059
22060
22061
22062
22063
22064
22065 namespace Composer\Installer;
22066
22067
22068
22069
22070
22071
22072 class InstallerEvents
22073 {
22074
22075
22076
22077
22078
22079
22080
22081
22082
22083 const PRE_DEPENDENCIES_SOLVING = 'pre-dependencies-solving';
22084
22085
22086
22087
22088
22089
22090
22091
22092
22093
22094 const POST_DEPENDENCIES_SOLVING = 'post-dependencies-solving';
22095 }
22096 <?php
22097
22098
22099
22100
22101
22102
22103
22104
22105
22106
22107
22108 namespace Composer\Installer;
22109
22110 use Composer\Package\PackageInterface;
22111 use Composer\Repository\InstalledRepositoryInterface;
22112 use InvalidArgumentException;
22113
22114
22115
22116
22117
22118
22119
22120 interface InstallerInterface
22121 {
22122
22123
22124
22125
22126
22127
22128 public function supports($packageType);
22129
22130
22131
22132
22133
22134
22135
22136
22137
22138 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package);
22139
22140
22141
22142
22143
22144
22145
22146 public function install(InstalledRepositoryInterface $repo, PackageInterface $package);
22147
22148
22149
22150
22151
22152
22153
22154
22155
22156
22157 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target);
22158
22159
22160
22161
22162
22163
22164
22165 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package);
22166
22167
22168
22169
22170
22171
22172
22173 public function getInstallPath(PackageInterface $package);
22174 }
22175 <?php
22176
22177
22178
22179
22180
22181
22182
22183
22184
22185
22186
22187 namespace Composer\Installer;
22188
22189 use Composer\Composer;
22190 use Composer\IO\IOInterface;
22191 use Composer\Repository\InstalledRepositoryInterface;
22192 use Composer\Package\PackageInterface;
22193 use Composer\Util\Filesystem;
22194 use Composer\Util\Silencer;
22195
22196
22197
22198
22199
22200
22201
22202 class LibraryInstaller implements InstallerInterface, BinaryPresenceInterface
22203 {
22204 protected $composer;
22205 protected $vendorDir;
22206 protected $binDir;
22207 protected $downloadManager;
22208 protected $io;
22209 protected $type;
22210 protected $filesystem;
22211 protected $binCompat;
22212 protected $binaryInstaller;
22213
22214
22215
22216
22217
22218
22219
22220
22221
22222
22223 public function __construct(IOInterface $io, Composer $composer, $type = 'library', Filesystem $filesystem = null, BinaryInstaller $binaryInstaller = null)
22224 {
22225 $this->composer = $composer;
22226 $this->downloadManager = $composer->getDownloadManager();
22227 $this->io = $io;
22228 $this->type = $type;
22229
22230 $this->filesystem = $filesystem ?: new Filesystem();
22231 $this->vendorDir = rtrim($composer->getConfig()->get('vendor-dir'), '/');
22232 $this->binaryInstaller = $binaryInstaller ?: new BinaryInstaller($this->io, rtrim($composer->getConfig()->get('bin-dir'), '/'), $composer->getConfig()->get('bin-compat'), $this->filesystem);
22233 }
22234
22235
22236
22237
22238 public function supports($packageType)
22239 {
22240 return $packageType === $this->type || null === $this->type;
22241 }
22242
22243
22244
22245
22246 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
22247 {
22248 return $repo->hasPackage($package) && is_readable($this->getInstallPath($package));
22249 }
22250
22251
22252
22253
22254 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
22255 {
22256 $this->initializeVendorDir();
22257 $downloadPath = $this->getInstallPath($package);
22258
22259
22260  if (!is_readable($downloadPath) && $repo->hasPackage($package)) {
22261 $this->binaryInstaller->removeBinaries($package);
22262 }
22263
22264 $this->installCode($package);
22265 $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package));
22266 if (!$repo->hasPackage($package)) {
22267 $repo->addPackage(clone $package);
22268 }
22269 }
22270
22271
22272
22273
22274 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
22275 {
22276 if (!$repo->hasPackage($initial)) {
22277 throw new \InvalidArgumentException('Package is not installed: '.$initial);
22278 }
22279
22280 $this->initializeVendorDir();
22281
22282 $this->binaryInstaller->removeBinaries($initial);
22283 $this->updateCode($initial, $target);
22284 $this->binaryInstaller->installBinaries($target, $this->getInstallPath($target));
22285 $repo->removePackage($initial);
22286 if (!$repo->hasPackage($target)) {
22287 $repo->addPackage(clone $target);
22288 }
22289 }
22290
22291
22292
22293
22294 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
22295 {
22296 if (!$repo->hasPackage($package)) {
22297 throw new \InvalidArgumentException('Package is not installed: '.$package);
22298 }
22299
22300 $this->removeCode($package);
22301 $this->binaryInstaller->removeBinaries($package);
22302 $repo->removePackage($package);
22303
22304 $downloadPath = $this->getPackageBasePath($package);
22305 if (strpos($package->getName(), '/')) {
22306 $packageVendorDir = dirname($downloadPath);
22307 if (is_dir($packageVendorDir) && $this->filesystem->isDirEmpty($packageVendorDir)) {
22308 Silencer::call('rmdir', $packageVendorDir);
22309 }
22310 }
22311 }
22312
22313
22314
22315
22316 public function getInstallPath(PackageInterface $package)
22317 {
22318 $this->initializeVendorDir();
22319
22320 $basePath = ($this->vendorDir ? $this->vendorDir.'/' : '') . $package->getPrettyName();
22321 $targetDir = $package->getTargetDir();
22322
22323 return $basePath . ($targetDir ? '/'.$targetDir : '');
22324 }
22325
22326
22327
22328
22329
22330
22331 public function ensureBinariesPresence(PackageInterface $package)
22332 {
22333 $this->binaryInstaller->installBinaries($package, $this->getInstallPath($package), false);
22334 }
22335
22336
22337
22338
22339
22340
22341
22342
22343
22344
22345 protected function getPackageBasePath(PackageInterface $package)
22346 {
22347 $installPath = $this->getInstallPath($package);
22348 $targetDir = $package->getTargetDir();
22349
22350 if ($targetDir) {
22351 return preg_replace('{/*'.str_replace('/', '/+', preg_quote($targetDir)).'/?$}', '', $installPath);
22352 }
22353
22354 return $installPath;
22355 }
22356
22357 protected function installCode(PackageInterface $package)
22358 {
22359 $downloadPath = $this->getInstallPath($package);
22360 $this->downloadManager->download($package, $downloadPath);
22361 }
22362
22363 protected function updateCode(PackageInterface $initial, PackageInterface $target)
22364 {
22365 $initialDownloadPath = $this->getInstallPath($initial);
22366 $targetDownloadPath = $this->getInstallPath($target);
22367 if ($targetDownloadPath !== $initialDownloadPath) {
22368
22369  
22370  if (substr($initialDownloadPath, 0, strlen($targetDownloadPath)) === $targetDownloadPath
22371 || substr($targetDownloadPath, 0, strlen($initialDownloadPath)) === $initialDownloadPath
22372 ) {
22373 $this->removeCode($initial);
22374 $this->installCode($target);
22375
22376 return;
22377 }
22378
22379 $this->filesystem->rename($initialDownloadPath, $targetDownloadPath);
22380 }
22381 $this->downloadManager->update($initial, $target, $targetDownloadPath);
22382 }
22383
22384 protected function removeCode(PackageInterface $package)
22385 {
22386 $downloadPath = $this->getPackageBasePath($package);
22387 $this->downloadManager->remove($package, $downloadPath);
22388 }
22389
22390 protected function initializeVendorDir()
22391 {
22392 $this->filesystem->ensureDirectoryExists($this->vendorDir);
22393 $this->vendorDir = realpath($this->vendorDir);
22394 }
22395 }
22396 <?php
22397
22398
22399
22400
22401
22402
22403
22404
22405
22406
22407
22408 namespace Composer\Installer;
22409
22410 use Composer\Repository\InstalledRepositoryInterface;
22411 use Composer\Package\PackageInterface;
22412
22413
22414
22415
22416
22417
22418 class MetapackageInstaller implements InstallerInterface
22419 {
22420
22421
22422
22423 public function supports($packageType)
22424 {
22425 return $packageType === 'metapackage';
22426 }
22427
22428
22429
22430
22431 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
22432 {
22433 return $repo->hasPackage($package);
22434 }
22435
22436
22437
22438
22439 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
22440 {
22441 $repo->addPackage(clone $package);
22442 }
22443
22444
22445
22446
22447 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
22448 {
22449 if (!$repo->hasPackage($initial)) {
22450 throw new \InvalidArgumentException('Package is not installed: '.$initial);
22451 }
22452
22453 $repo->removePackage($initial);
22454 $repo->addPackage(clone $target);
22455 }
22456
22457
22458
22459
22460 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
22461 {
22462 if (!$repo->hasPackage($package)) {
22463 throw new \InvalidArgumentException('Package is not installed: '.$package);
22464 }
22465
22466 $repo->removePackage($package);
22467 }
22468
22469
22470
22471
22472 public function getInstallPath(PackageInterface $package)
22473 {
22474 return '';
22475 }
22476 }
22477 <?php
22478
22479
22480
22481
22482
22483
22484
22485
22486
22487
22488
22489 namespace Composer\Installer;
22490
22491 use Composer\Repository\InstalledRepositoryInterface;
22492 use Composer\Package\PackageInterface;
22493
22494
22495
22496
22497
22498
22499
22500
22501 class NoopInstaller implements InstallerInterface
22502 {
22503
22504
22505
22506 public function supports($packageType)
22507 {
22508 return true;
22509 }
22510
22511
22512
22513
22514 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
22515 {
22516 return $repo->hasPackage($package);
22517 }
22518
22519
22520
22521
22522 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
22523 {
22524 if (!$repo->hasPackage($package)) {
22525 $repo->addPackage(clone $package);
22526 }
22527 }
22528
22529
22530
22531
22532 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
22533 {
22534 if (!$repo->hasPackage($initial)) {
22535 throw new \InvalidArgumentException('Package is not installed: '.$initial);
22536 }
22537
22538 $repo->removePackage($initial);
22539 if (!$repo->hasPackage($target)) {
22540 $repo->addPackage(clone $target);
22541 }
22542 }
22543
22544
22545
22546
22547 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
22548 {
22549 if (!$repo->hasPackage($package)) {
22550 throw new \InvalidArgumentException('Package is not installed: '.$package);
22551 }
22552 $repo->removePackage($package);
22553 }
22554
22555
22556
22557
22558 public function getInstallPath(PackageInterface $package)
22559 {
22560 $targetDir = $package->getTargetDir();
22561
22562 return $package->getPrettyName() . ($targetDir ? '/'.$targetDir : '');
22563 }
22564 }
22565 <?php
22566
22567
22568
22569
22570
22571
22572
22573
22574
22575
22576
22577 namespace Composer\Installer;
22578
22579 use Composer\Composer;
22580 use Composer\IO\IOInterface;
22581 use Composer\DependencyResolver\Operation\OperationInterface;
22582 use Composer\DependencyResolver\PolicyInterface;
22583 use Composer\DependencyResolver\Pool;
22584 use Composer\DependencyResolver\Request;
22585 use Composer\Repository\CompositeRepository;
22586
22587
22588
22589
22590
22591
22592 class PackageEvent extends InstallerEvent
22593 {
22594
22595
22596
22597 private $operation;
22598
22599
22600
22601
22602
22603
22604
22605
22606
22607
22608
22609
22610
22611
22612
22613 public function __construct($eventName, Composer $composer, IOInterface $io, $devMode, PolicyInterface $policy, Pool $pool, CompositeRepository $installedRepo, Request $request, array $operations, OperationInterface $operation)
22614 {
22615 parent::__construct($eventName, $composer, $io, $devMode, $policy, $pool, $installedRepo, $request, $operations);
22616
22617 $this->operation = $operation;
22618 }
22619
22620
22621
22622
22623
22624
22625 public function getOperation()
22626 {
22627 return $this->operation;
22628 }
22629 }
22630 <?php
22631
22632
22633
22634
22635
22636
22637
22638
22639
22640
22641
22642 namespace Composer\Installer;
22643
22644
22645
22646
22647
22648
22649 class PackageEvents
22650 {
22651
22652
22653
22654
22655
22656
22657
22658 const PRE_PACKAGE_INSTALL = 'pre-package-install';
22659
22660
22661
22662
22663
22664
22665
22666
22667 const POST_PACKAGE_INSTALL = 'post-package-install';
22668
22669
22670
22671
22672
22673
22674
22675
22676 const PRE_PACKAGE_UPDATE = 'pre-package-update';
22677
22678
22679
22680
22681
22682
22683
22684
22685 const POST_PACKAGE_UPDATE = 'post-package-update';
22686
22687
22688
22689
22690
22691
22692
22693
22694 const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
22695
22696
22697
22698
22699
22700
22701
22702
22703 const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
22704 }
22705 <?php
22706
22707
22708
22709
22710
22711
22712
22713
22714
22715
22716
22717 namespace Composer\Installer;
22718
22719 use Composer\IO\IOInterface;
22720 use Composer\Package\PackageInterface;
22721 use Composer\Util\Filesystem;
22722 use Composer\Util\ProcessExecutor;
22723
22724
22725
22726
22727
22728
22729 class PearBinaryInstaller extends BinaryInstaller
22730 {
22731 private $installer;
22732 private $vendorDir;
22733
22734
22735
22736
22737
22738
22739
22740
22741
22742 public function __construct(IOInterface $io, $binDir, $vendorDir, $binCompat, Filesystem $filesystem, PearInstaller $installer)
22743 {
22744 parent::__construct($io, $binDir, $binCompat, $filesystem);
22745 $this->installer = $installer;
22746 $this->vendorDir = $vendorDir;
22747 }
22748
22749 protected function getBinaries(PackageInterface $package)
22750 {
22751 $binariesPath = $this->installer->getInstallPath($package) . '/bin/';
22752 $binaries = array();
22753 if (file_exists($binariesPath)) {
22754 foreach (new \FilesystemIterator($binariesPath, \FilesystemIterator::KEY_AS_FILENAME | \FilesystemIterator::CURRENT_AS_FILEINFO) as $fileName => $value) {
22755 if (!$value->isDir()) {
22756 $binaries[] = 'bin/'.$fileName;
22757 }
22758 }
22759 }
22760
22761 return $binaries;
22762 }
22763
22764 protected function initializeBinDir()
22765 {
22766 parent::initializeBinDir();
22767 file_put_contents($this->binDir.'/composer-php', $this->generateUnixyPhpProxyCode());
22768 @chmod($this->binDir.'/composer-php', 0777);
22769 file_put_contents($this->binDir.'/composer-php.bat', $this->generateWindowsPhpProxyCode());
22770 @chmod($this->binDir.'/composer-php.bat', 0777);
22771 }
22772
22773 protected function generateWindowsProxyCode($bin, $link)
22774 {
22775 $binPath = $this->filesystem->findShortestPath($link, $bin);
22776 if ('.bat' === substr($bin, -4)) {
22777 $caller = 'call';
22778 } else {
22779 $handle = fopen($bin, 'r');
22780 $line = fgets($handle);
22781 fclose($handle);
22782 if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) {
22783 $caller = trim($match[1]);
22784 } else {
22785 $caller = 'php';
22786 }
22787
22788 if ($caller === 'php') {
22789 return "@echo off\r\n".
22790 "pushd .\r\n".
22791 "cd %~dp0\r\n".
22792 "set PHP_PROXY=%CD%\\composer-php.bat\r\n".
22793 "cd ".ProcessExecutor::escape(dirname($binPath))."\r\n".
22794 "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n".
22795 "popd\r\n".
22796 "%PHP_PROXY% \"%BIN_TARGET%\" %*\r\n";
22797 }
22798 }
22799
22800 return "@echo off\r\n".
22801 "pushd .\r\n".
22802 "cd %~dp0\r\n".
22803 "cd ".ProcessExecutor::escape(dirname($binPath))."\r\n".
22804 "set BIN_TARGET=%CD%\\".basename($binPath)."\r\n".
22805 "popd\r\n".
22806 $caller." \"%BIN_TARGET%\" %*\r\n";
22807 }
22808
22809 private function generateWindowsPhpProxyCode()
22810 {
22811 $binToVendor = $this->filesystem->findShortestPath($this->binDir, $this->vendorDir, true);
22812
22813 return
22814 "@echo off\r\n" .
22815 "setlocal enabledelayedexpansion\r\n" .
22816 "set BIN_DIR=%~dp0\r\n" .
22817 "set VENDOR_DIR=%BIN_DIR%\\".$binToVendor."\r\n" .
22818 "set DIRS=.\r\n" .
22819 "FOR /D %%V IN (%VENDOR_DIR%\\*) DO (\r\n" .
22820 "    FOR /D %%P IN (%%V\\*) DO (\r\n" .
22821 "        set DIRS=!DIRS!;%%~fP\r\n" .
22822 "    )\r\n" .
22823 ")\r\n" .
22824 "php.exe -d include_path=!DIRS! %*\r\n";
22825 }
22826
22827 private function generateUnixyPhpProxyCode()
22828 {
22829 $binToVendor = $this->filesystem->findShortestPath($this->binDir, $this->vendorDir, true);
22830
22831 return
22832 "#!/usr/bin/env sh\n".
22833 "SRC_DIR=`pwd`\n".
22834 "BIN_DIR=`dirname $0`\n".
22835 "VENDOR_DIR=\$BIN_DIR/".escapeshellarg($binToVendor)."\n".
22836 "DIRS=\"\"\n".
22837 "for vendor in \$VENDOR_DIR/*; do\n".
22838 "    if [ -d \"\$vendor\" ]; then\n".
22839 "        for package in \$vendor/*; do\n".
22840 "            if [ -d \"\$package\" ]; then\n".
22841 "                DIRS=\"\${DIRS}:\${package}\"\n".
22842 "            fi\n".
22843 "        done\n".
22844 "    fi\n".
22845 "done\n".
22846 "php -d include_path=\".\$DIRS\" $@\n";
22847 }
22848 }
22849 <?php
22850
22851
22852
22853
22854
22855
22856
22857
22858
22859
22860
22861 namespace Composer\Installer;
22862
22863 use Composer\IO\IOInterface;
22864 use Composer\Composer;
22865 use Composer\Downloader\PearPackageExtractor;
22866 use Composer\Repository\InstalledRepositoryInterface;
22867 use Composer\Package\PackageInterface;
22868 use Composer\Util\Platform;
22869 use Composer\Util\Filesystem;
22870
22871
22872
22873
22874
22875
22876
22877 class PearInstaller extends LibraryInstaller
22878 {
22879
22880
22881
22882
22883
22884
22885
22886 public function __construct(IOInterface $io, Composer $composer, $type = 'pear-library')
22887 {
22888 $filesystem = new Filesystem();
22889 $binaryInstaller = new PearBinaryInstaller($io, rtrim($composer->getConfig()->get('bin-dir'), '/'), rtrim($composer->getConfig()->get('vendor-dir'), '/'), $composer->getConfig()->get('bin-compat'), $filesystem, $this);
22890
22891 parent::__construct($io, $composer, $type, $filesystem, $binaryInstaller);
22892 }
22893
22894
22895
22896
22897 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
22898 {
22899 $this->uninstall($repo, $initial);
22900 $this->install($repo, $target);
22901 }
22902
22903 protected function installCode(PackageInterface $package)
22904 {
22905 parent::installCode($package);
22906
22907 $isWindows = Platform::isWindows();
22908 $php_bin = $this->binDir . ($isWindows ? '/composer-php.bat' : '/composer-php');
22909
22910 if (!$isWindows) {
22911 $php_bin = '/usr/bin/env ' . $php_bin;
22912 }
22913
22914 $installPath = $this->getInstallPath($package);
22915 $vars = array(
22916 'os' => $isWindows ? 'windows' : 'linux',
22917 'php_bin' => $php_bin,
22918 'pear_php' => $installPath,
22919 'php_dir' => $installPath,
22920 'bin_dir' => $installPath . '/bin',
22921 'data_dir' => $installPath . '/data',
22922 'version' => $package->getPrettyVersion(),
22923 );
22924
22925 $packageArchive = $this->getInstallPath($package).'/'.pathinfo($package->getDistUrl(), PATHINFO_BASENAME);
22926 $pearExtractor = new PearPackageExtractor($packageArchive);
22927 $pearExtractor->extractTo($this->getInstallPath($package), array('php' => '/', 'script' => '/bin', 'data' => '/data'), $vars);
22928
22929 $this->io->writeError('    Cleaning up', true, IOInterface::VERBOSE);
22930 $this->filesystem->unlink($packageArchive);
22931 }
22932 }
22933 <?php
22934
22935
22936
22937
22938
22939
22940
22941
22942
22943
22944
22945 namespace Composer\Installer;
22946
22947 use Composer\Composer;
22948 use Composer\IO\IOInterface;
22949 use Composer\Repository\InstalledRepositoryInterface;
22950 use Composer\Package\PackageInterface;
22951
22952
22953
22954
22955
22956
22957
22958 class PluginInstaller extends LibraryInstaller
22959 {
22960 private $installationManager;
22961
22962
22963
22964
22965
22966
22967
22968
22969 public function __construct(IOInterface $io, Composer $composer, $type = 'library')
22970 {
22971 parent::__construct($io, $composer, 'composer-plugin');
22972 $this->installationManager = $composer->getInstallationManager();
22973 }
22974
22975
22976
22977
22978 public function supports($packageType)
22979 {
22980 return $packageType === 'composer-plugin' || $packageType === 'composer-installer';
22981 }
22982
22983
22984
22985
22986 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
22987 {
22988 $extra = $package->getExtra();
22989 if (empty($extra['class'])) {
22990 throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
22991 }
22992
22993 parent::install($repo, $package);
22994 try {
22995 $this->composer->getPluginManager()->registerPackage($package, true);
22996 } catch (\Exception $e) {
22997
22998  $this->io->writeError('Plugin installation failed, rolling back');
22999 parent::uninstall($repo, $package);
23000 throw $e;
23001 }
23002 }
23003
23004
23005
23006
23007 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23008 {
23009 $extra = $target->getExtra();
23010 if (empty($extra['class'])) {
23011 throw new \UnexpectedValueException('Error while installing '.$target->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
23012 }
23013
23014 parent::update($repo, $initial, $target);
23015 $this->composer->getPluginManager()->registerPackage($target, true);
23016 }
23017 }
23018 <?php
23019
23020
23021
23022
23023
23024
23025
23026
23027
23028
23029
23030 namespace Composer\Installer;
23031
23032 use Composer\Package\PackageInterface;
23033 use Composer\Downloader\DownloadManager;
23034 use Composer\Repository\InstalledRepositoryInterface;
23035 use Composer\Util\Filesystem;
23036
23037
23038
23039
23040
23041
23042
23043 class ProjectInstaller implements InstallerInterface
23044 {
23045 private $installPath;
23046 private $downloadManager;
23047 private $filesystem;
23048
23049 public function __construct($installPath, DownloadManager $dm)
23050 {
23051 $this->installPath = rtrim(strtr($installPath, '\\', '/'), '/').'/';
23052 $this->downloadManager = $dm;
23053 $this->filesystem = new Filesystem;
23054 }
23055
23056
23057
23058
23059
23060
23061
23062 public function supports($packageType)
23063 {
23064 return true;
23065 }
23066
23067
23068
23069
23070 public function isInstalled(InstalledRepositoryInterface $repo, PackageInterface $package)
23071 {
23072 return false;
23073 }
23074
23075
23076
23077
23078 public function install(InstalledRepositoryInterface $repo, PackageInterface $package)
23079 {
23080 $installPath = $this->installPath;
23081 if (file_exists($installPath) && !$this->filesystem->isDirEmpty($installPath)) {
23082 throw new \InvalidArgumentException("Project directory $installPath is not empty.");
23083 }
23084 if (!is_dir($installPath)) {
23085 mkdir($installPath, 0777, true);
23086 }
23087 $this->downloadManager->download($package, $installPath);
23088 }
23089
23090
23091
23092
23093 public function update(InstalledRepositoryInterface $repo, PackageInterface $initial, PackageInterface $target)
23094 {
23095 throw new \InvalidArgumentException("not supported");
23096 }
23097
23098
23099
23100
23101 public function uninstall(InstalledRepositoryInterface $repo, PackageInterface $package)
23102 {
23103 throw new \InvalidArgumentException("not supported");
23104 }
23105
23106
23107
23108
23109
23110
23111
23112 public function getInstallPath(PackageInterface $package)
23113 {
23114 return $this->installPath;
23115 }
23116 }
23117 <?php
23118
23119
23120
23121
23122
23123
23124
23125
23126
23127
23128
23129 namespace Composer\Installer;
23130
23131 use Composer\IO\IOInterface;
23132 use Composer\Package\PackageInterface;
23133 use Composer\Repository\RepositoryInterface;
23134 use Symfony\Component\Console\Formatter\OutputFormatter;
23135
23136
23137
23138
23139
23140
23141 class SuggestedPackagesReporter
23142 {
23143
23144
23145
23146 protected $suggestedPackages = array();
23147
23148
23149
23150
23151 private $io;
23152
23153 public function __construct(IOInterface $io)
23154 {
23155 $this->io = $io;
23156 }
23157
23158
23159
23160
23161 public function getPackages()
23162 {
23163 return $this->suggestedPackages;
23164 }
23165
23166
23167
23168
23169
23170
23171
23172
23173
23174
23175
23176
23177 public function addPackage($source, $target, $reason)
23178 {
23179 $this->suggestedPackages[] = array(
23180 'source' => $source,
23181 'target' => $target,
23182 'reason' => $reason,
23183 );
23184
23185 return $this;
23186 }
23187
23188
23189
23190
23191
23192
23193
23194 public function addSuggestionsFromPackage(PackageInterface $package)
23195 {
23196 $source = $package->getPrettyName();
23197 foreach ($package->getSuggests() as $target => $reason) {
23198 $this->addPackage(
23199 $source,
23200 $target,
23201 $reason
23202 );
23203 }
23204
23205 return $this;
23206 }
23207
23208
23209
23210
23211
23212
23213
23214
23215 public function output(RepositoryInterface $installedRepo = null)
23216 {
23217 $suggestedPackages = $this->getPackages();
23218 $installedPackages = array();
23219 if (null !== $installedRepo && ! empty($suggestedPackages)) {
23220 foreach ($installedRepo->getPackages() as $package) {
23221 $installedPackages = array_merge(
23222 $installedPackages,
23223 $package->getNames()
23224 );
23225 }
23226 }
23227
23228 foreach ($suggestedPackages as $suggestion) {
23229 if (in_array($suggestion['target'], $installedPackages)) {
23230 continue;
23231 }
23232
23233 $this->io->writeError(sprintf(
23234 '%s suggests installing %s (%s)',
23235 $suggestion['source'],
23236 $this->escapeOutput($suggestion['target']),
23237 $this->escapeOutput($suggestion['reason'])
23238 ));
23239 }
23240
23241 return $this;
23242 }
23243
23244
23245
23246
23247
23248 private function escapeOutput($string)
23249 {
23250 return OutputFormatter::escape(
23251 $this->removeControlCharacters($string)
23252 );
23253 }
23254
23255
23256
23257
23258
23259 private function removeControlCharacters($string)
23260 {
23261 return preg_replace(
23262 '/[[:cntrl:]]/',
23263 '',
23264 str_replace("\n", ' ', $string)
23265 );
23266 }
23267 }
23268 <?php
23269
23270
23271
23272
23273
23274
23275
23276
23277
23278
23279
23280 namespace Composer\Json;
23281
23282 use JsonSchema\Validator;
23283 use Seld\JsonLint\JsonParser;
23284 use Seld\JsonLint\ParsingException;
23285 use Composer\Util\RemoteFilesystem;
23286 use Composer\IO\IOInterface;
23287 use Composer\Downloader\TransportException;
23288
23289
23290
23291
23292
23293
23294
23295 class JsonFile
23296 {
23297 const LAX_SCHEMA = 1;
23298 const STRICT_SCHEMA = 2;
23299
23300 const JSON_UNESCAPED_SLASHES = 64;
23301 const JSON_PRETTY_PRINT = 128;
23302 const JSON_UNESCAPED_UNICODE = 256;
23303
23304 private $path;
23305 private $rfs;
23306 private $io;
23307
23308
23309
23310
23311
23312
23313
23314
23315
23316 public function __construct($path, RemoteFilesystem $rfs = null, IOInterface $io = null)
23317 {
23318 $this->path = $path;
23319
23320 if (null === $rfs && preg_match('{^https?://}i', $path)) {
23321 throw new \InvalidArgumentException('http urls require a RemoteFilesystem instance to be passed');
23322 }
23323 $this->rfs = $rfs;
23324 $this->io = $io;
23325 }
23326
23327
23328
23329
23330 public function getPath()
23331 {
23332 return $this->path;
23333 }
23334
23335
23336
23337
23338
23339
23340 public function exists()
23341 {
23342 return is_file($this->path);
23343 }
23344
23345
23346
23347
23348
23349
23350
23351 public function read()
23352 {
23353 try {
23354 if ($this->rfs) {
23355 $json = $this->rfs->getContents($this->path, $this->path, false);
23356 } else {
23357 if ($this->io && $this->io->isDebug()) {
23358 $this->io->writeError('Reading ' . $this->path);
23359 }
23360 $json = file_get_contents($this->path);
23361 }
23362 } catch (TransportException $e) {
23363 throw new \RuntimeException($e->getMessage(), 0, $e);
23364 } catch (\Exception $e) {
23365 throw new \RuntimeException('Could not read '.$this->path."\n\n".$e->getMessage());
23366 }
23367
23368 return static::parseJson($json, $this->path);
23369 }
23370
23371
23372
23373
23374
23375
23376
23377
23378 public function write(array $hash, $options = 448)
23379 {
23380 $dir = dirname($this->path);
23381 if (!is_dir($dir)) {
23382 if (file_exists($dir)) {
23383 throw new \UnexpectedValueException(
23384 $dir.' exists and is not a directory.'
23385 );
23386 }
23387 if (!@mkdir($dir, 0777, true)) {
23388 throw new \UnexpectedValueException(
23389 $dir.' does not exist and could not be created.'
23390 );
23391 }
23392 }
23393
23394 $retries = 3;
23395 while ($retries--) {
23396 try {
23397 file_put_contents($this->path, static::encode($hash, $options). ($options & self::JSON_PRETTY_PRINT ? "\n" : ''));
23398 break;
23399 } catch (\Exception $e) {
23400 if ($retries) {
23401 usleep(500000);
23402 continue;
23403 }
23404
23405 throw $e;
23406 }
23407 }
23408 }
23409
23410
23411
23412
23413
23414
23415
23416
23417 public function validateSchema($schema = self::STRICT_SCHEMA)
23418 {
23419 $content = file_get_contents($this->path);
23420 $data = json_decode($content);
23421
23422 if (null === $data && 'null' !== $content) {
23423 self::validateSyntax($content, $this->path);
23424 }
23425
23426 $schemaFile = __DIR__ . '/../../../res/composer-schema.json';
23427
23428
23429  if (false === strpos($schemaFile, '://')) {
23430 $schemaFile = 'file://' . $schemaFile;
23431 }
23432
23433 $schemaData = (object) array('$ref' => $schemaFile);
23434
23435 if ($schema === self::LAX_SCHEMA) {
23436 $schemaData->additionalProperties = true;
23437 $schemaData->required = array();
23438 }
23439
23440 $validator = new Validator();
23441 $validator->check($data, $schemaData);
23442
23443
23444
23445 if (!$validator->isValid()) {
23446 $errors = array();
23447 foreach ((array) $validator->getErrors() as $error) {
23448 $errors[] = ($error['property'] ? $error['property'].' : ' : '').$error['message'];
23449 }
23450 throw new JsonValidationException('"'.$this->path.'" does not match the expected JSON schema', $errors);
23451 }
23452
23453 return true;
23454 }
23455
23456
23457
23458
23459
23460
23461
23462
23463 public static function encode($data, $options = 448)
23464 {
23465 if (PHP_VERSION_ID >= 50400) {
23466 $json = json_encode($data, $options);
23467 if (false === $json) {
23468 self::throwEncodeError(json_last_error());
23469 }
23470
23471
23472  if (PHP_VERSION_ID < 50428 || (PHP_VERSION_ID >= 50500 && PHP_VERSION_ID < 50512) || (defined('JSON_C_VERSION') && version_compare(phpversion('json'), '1.3.6', '<'))) {
23473 $json = preg_replace('/\[\s+\]/', '[]', $json);
23474 $json = preg_replace('/\{\s+\}/', '{}', $json);
23475 }
23476
23477 return $json;
23478 }
23479
23480 $json = json_encode($data);
23481 if (false === $json) {
23482 self::throwEncodeError(json_last_error());
23483 }
23484
23485 $prettyPrint = (bool) ($options & self::JSON_PRETTY_PRINT);
23486 $unescapeUnicode = (bool) ($options & self::JSON_UNESCAPED_UNICODE);
23487 $unescapeSlashes = (bool) ($options & self::JSON_UNESCAPED_SLASHES);
23488
23489 if (!$prettyPrint && !$unescapeUnicode && !$unescapeSlashes) {
23490 return $json;
23491 }
23492
23493 $result = JsonFormatter::format($json, $unescapeUnicode, $unescapeSlashes);
23494
23495 return $result;
23496 }
23497
23498
23499
23500
23501
23502
23503
23504 private static function throwEncodeError($code)
23505 {
23506 switch ($code) {
23507 case JSON_ERROR_DEPTH:
23508 $msg = 'Maximum stack depth exceeded';
23509 break;
23510 case JSON_ERROR_STATE_MISMATCH:
23511 $msg = 'Underflow or the modes mismatch';
23512 break;
23513 case JSON_ERROR_CTRL_CHAR:
23514 $msg = 'Unexpected control character found';
23515 break;
23516 case JSON_ERROR_UTF8:
23517 $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
23518 break;
23519 default:
23520 $msg = 'Unknown error';
23521 }
23522
23523 throw new \RuntimeException('JSON encoding failed: '.$msg);
23524 }
23525
23526
23527
23528
23529
23530
23531
23532
23533
23534 public static function parseJson($json, $file = null)
23535 {
23536 if (null === $json) {
23537 return;
23538 }
23539 $data = json_decode($json, true);
23540 if (null === $data && JSON_ERROR_NONE !== json_last_error()) {
23541 self::validateSyntax($json, $file);
23542 }
23543
23544 return $data;
23545 }
23546
23547
23548
23549
23550
23551
23552
23553
23554
23555
23556
23557 protected static function validateSyntax($json, $file = null)
23558 {
23559 $parser = new JsonParser();
23560 $result = $parser->lint($json);
23561 if (null === $result) {
23562 if (defined('JSON_ERROR_UTF8') && JSON_ERROR_UTF8 === json_last_error()) {
23563 throw new \UnexpectedValueException('"'.$file.'" is not UTF-8, could not parse as JSON');
23564 }
23565
23566 return true;
23567 }
23568
23569 throw new ParsingException('"'.$file.'" does not contain valid JSON'."\n".$result->getMessage(), $result->getDetails());
23570 }
23571 }
23572 <?php
23573
23574
23575
23576
23577
23578
23579
23580
23581
23582
23583
23584 namespace Composer\Json;
23585
23586
23587
23588
23589
23590
23591
23592
23593
23594 class JsonFormatter
23595 {
23596
23597
23598
23599
23600
23601
23602
23603
23604
23605
23606
23607
23608 public static function format($json, $unescapeUnicode, $unescapeSlashes)
23609 {
23610 $result = '';
23611 $pos = 0;
23612 $strLen = strlen($json);
23613 $indentStr = '    ';
23614 $newLine = "\n";
23615 $outOfQuotes = true;
23616 $buffer = '';
23617 $noescape = true;
23618
23619 for ($i = 0; $i < $strLen; $i++) {
23620
23621  $char = substr($json, $i, 1);
23622
23623
23624  if ('"' === $char && $noescape) {
23625 $outOfQuotes = !$outOfQuotes;
23626 }
23627
23628 if (!$outOfQuotes) {
23629 $buffer .= $char;
23630 $noescape = '\\' === $char ? !$noescape : true;
23631 continue;
23632 } elseif ('' !== $buffer) {
23633 if ($unescapeSlashes) {
23634 $buffer = str_replace('\\/', '/', $buffer);
23635 }
23636
23637 if ($unescapeUnicode && function_exists('mb_convert_encoding')) {
23638
23639  $buffer = preg_replace_callback('/(\\\\+)u([0-9a-f]{4})/i', function ($match) {
23640 $l = strlen($match[1]);
23641
23642 if ($l % 2) {
23643 return str_repeat('\\', $l - 1) . mb_convert_encoding(
23644 pack('H*', $match[2]),
23645 'UTF-8',
23646 'UCS-2BE'
23647 );
23648 }
23649
23650 return $match[0];
23651 }, $buffer);
23652 }
23653
23654 $result .= $buffer.$char;
23655 $buffer = '';
23656 continue;
23657 }
23658
23659 if (':' === $char) {
23660
23661  $char .= ' ';
23662 } elseif (('}' === $char || ']' === $char)) {
23663 $pos--;
23664 $prevChar = substr($json, $i - 1, 1);
23665
23666 if ('{' !== $prevChar && '[' !== $prevChar) {
23667
23668  
23669  $result .= $newLine;
23670 for ($j = 0; $j < $pos; $j++) {
23671 $result .= $indentStr;
23672 }
23673 } else {
23674
23675  $result = rtrim($result);
23676 }
23677 }
23678
23679 $result .= $char;
23680
23681
23682  
23683  if (',' === $char || '{' === $char || '[' === $char) {
23684 $result .= $newLine;
23685
23686 if ('{' === $char || '[' === $char) {
23687 $pos++;
23688 }
23689
23690 for ($j = 0; $j < $pos; $j++) {
23691 $result .= $indentStr;
23692 }
23693 }
23694 }
23695
23696 return $result;
23697 }
23698 }
23699 <?php
23700
23701
23702
23703
23704
23705
23706
23707
23708
23709
23710
23711 namespace Composer\Json;
23712
23713 use Composer\Repository\PlatformRepository;
23714
23715
23716
23717
23718 class JsonManipulator
23719 {
23720 private static $DEFINES = '(?(DEFINE)
23721        (?<number>   -? (?= [1-9]|0(?!\d) ) \d+ (\.\d+)? ([eE] [+-]? \d+)? )
23722        (?<boolean>   true | false | null )
23723        (?<string>    " ([^"\\\\]* | \\\\ ["\\\\bfnrt\/] | \\\\ u [0-9a-f]{4} )* " )
23724        (?<array>     \[  (?:  (?&json) \s* (?: , (?&json) \s* )*  )?  \s* \] )
23725        (?<pair>      \s* (?&string) \s* : (?&json) \s* )
23726        (?<object>    \{  (?:  (?&pair)  (?: , (?&pair)  )*  )?  \s* \} )
23727        (?<json>   \s* (?: (?&number) | (?&boolean) | (?&string) | (?&array) | (?&object) ) )
23728     )';
23729
23730 private $contents;
23731 private $newline;
23732 private $indent;
23733
23734 public function __construct($contents)
23735 {
23736 $contents = trim($contents);
23737 if ($contents === '') {
23738 $contents = '{}';
23739 }
23740 if (!$this->pregMatch('#^\{(.*)\}$#s', $contents)) {
23741 throw new \InvalidArgumentException('The json file must be an object ({})');
23742 }
23743 $this->newline = false !== strpos($contents, "\r\n") ? "\r\n" : "\n";
23744 $this->contents = $contents === '{}' ? '{' . $this->newline . '}' : $contents;
23745 $this->detectIndenting();
23746 }
23747
23748 public function getContents()
23749 {
23750 return $this->contents . $this->newline;
23751 }
23752
23753 public function addLink($type, $package, $constraint, $sortPackages = false)
23754 {
23755 $decoded = JsonFile::parseJson($this->contents);
23756
23757
23758  if (!isset($decoded[$type])) {
23759 return $this->addMainKey($type, array($package => $constraint));
23760 }
23761
23762 $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
23763 '(?P<property>'.preg_quote(JsonFile::encode($type)).'\s*:\s*)(?P<value>(?&json))(?P<end>.*)}sx';
23764 if (!$this->pregMatch($regex, $this->contents, $matches)) {
23765 return false;
23766 }
23767
23768 $links = $matches['value'];
23769
23770
23771  $packageRegex = str_replace('/', '\\\\?/', preg_quote($package));
23772 $regex = '{'.self::$DEFINES.'"(?P<package>'.$packageRegex.')"(\s*:\s*)(?&string)}ix';
23773 if ($this->pregMatch($regex, $links, $packageMatches)) {
23774
23775  $existingPackage = $packageMatches['package'];
23776 $packageRegex = str_replace('/', '\\\\?/', preg_quote($existingPackage));
23777 $links = preg_replace_callback('{'.self::$DEFINES.'"'.$packageRegex.'"(?P<separator>\s*:\s*)(?&string)}ix', function ($m) use ($existingPackage, $constraint) {
23778 return JsonFile::encode(str_replace('\\/', '/', $existingPackage)) . $m['separator'] . '"' . $constraint . '"';
23779 }, $links);
23780 } else {
23781 if ($this->pregMatch('#^\s*\{\s*\S+.*?(\s*\}\s*)$#s', $links, $match)) {
23782
23783  $links = preg_replace(
23784 '{'.preg_quote($match[1]).'$}',
23785
23786  addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $match[1], '\\$'),
23787 $links
23788 );
23789 } else {
23790
23791  $links = '{' . $this->newline .
23792 $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $this->newline .
23793 $this->indent . '}';
23794 }
23795 }
23796
23797 if (true === $sortPackages) {
23798 $requirements = json_decode($links, true);
23799 $this->sortPackages($requirements);
23800 $links = $this->format($requirements);
23801 }
23802
23803 $this->contents = $matches['start'] . $matches['property'] . $links . $matches['end'];
23804
23805 return true;
23806 }
23807
23808
23809
23810
23811
23812
23813
23814
23815 private function sortPackages(array &$packages = array())
23816 {
23817 $prefix = function ($requirement) {
23818 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $requirement)) {
23819 return preg_replace(
23820 array(
23821 '/^php/',
23822 '/^hhvm/',
23823 '/^ext/',
23824 '/^lib/',
23825 '/^\D/',
23826 ),
23827 array(
23828 '0-$0',
23829 '1-$0',
23830 '2-$0',
23831 '3-$0',
23832 '4-$0',
23833 ),
23834 $requirement
23835 );
23836 }
23837
23838 return '5-'.$requirement;
23839 };
23840
23841 uksort($packages, function ($a, $b) use ($prefix) {
23842 return strnatcmp($prefix($a), $prefix($b));
23843 });
23844 }
23845
23846 public function addRepository($name, $config)
23847 {
23848 return $this->addSubNode('repositories', $name, $config);
23849 }
23850
23851 public function removeRepository($name)
23852 {
23853 return $this->removeSubNode('repositories', $name);
23854 }
23855
23856 public function addConfigSetting($name, $value)
23857 {
23858 return $this->addSubNode('config', $name, $value);
23859 }
23860
23861 public function removeConfigSetting($name)
23862 {
23863 return $this->removeSubNode('config', $name);
23864 }
23865
23866 public function addProperty($name, $value)
23867 {
23868 if (substr($name, 0, 6) === 'extra.') {
23869 return $this->addSubNode('extra', substr($name, 6), $value);
23870 }
23871
23872 return $this->addMainKey($name, $value);
23873 }
23874
23875 public function removeProperty($name)
23876 {
23877 if (substr($name, 0, 6) === 'extra.') {
23878 return $this->removeSubNode('extra', substr($name, 6));
23879 }
23880
23881 return $this->removeMainKey($name);
23882 }
23883
23884 public function addSubNode($mainNode, $name, $value)
23885 {
23886 $decoded = JsonFile::parseJson($this->contents);
23887
23888 $subName = null;
23889 if (in_array($mainNode, array('config', 'extra')) && false !== strpos($name, '.')) {
23890 list($name, $subName) = explode('.', $name, 2);
23891 }
23892
23893
23894  if (!isset($decoded[$mainNode])) {
23895 if ($subName !== null) {
23896 $this->addMainKey($mainNode, array($name => array($subName => $value)));
23897 } else {
23898 $this->addMainKey($mainNode, array($name => $value));
23899 }
23900
23901 return true;
23902 }
23903
23904
23905  $nodeRegex = '{'.self::$DEFINES.'^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
23906 preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
23907
23908 try {
23909 if (!$this->pregMatch($nodeRegex, $this->contents, $match)) {
23910 return false;
23911 }
23912 } catch (\RuntimeException $e) {
23913 if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
23914 return false;
23915 }
23916 throw $e;
23917 }
23918
23919 $children = $match['content'];
23920
23921  if (!@json_decode($children)) {
23922 return false;
23923 }
23924
23925 $that = $this;
23926
23927
23928  $childRegex = '{'.self::$DEFINES.'(?P<start>"'.preg_quote($name).'"\s*:\s*)(?P<content>(?&json))(?P<end>,?)}x';
23929 if ($this->pregMatch($childRegex, $children, $matches)) {
23930 $children = preg_replace_callback($childRegex, function ($matches) use ($name, $subName, $value, $that) {
23931 if ($subName !== null) {
23932 $curVal = json_decode($matches['content'], true);
23933 if (!is_array($curVal)) {
23934 $curVal = array();
23935 }
23936 $curVal[$subName] = $value;
23937 $value = $curVal;
23938 }
23939
23940 return $matches['start'] . $that->format($value, 1) . $matches['end'];
23941 }, $children);
23942 } else {
23943 $this->pregMatch('#^{ \s*? (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $children, $match);
23944
23945 $whitespace = '';
23946 if (!empty($match['trailingspace'])) {
23947 $whitespace = $match['trailingspace'];
23948 }
23949
23950 if (!empty($match['content'])) {
23951 if ($subName !== null) {
23952 $value = array($subName => $value);
23953 }
23954
23955
23956  $children = preg_replace(
23957 '#'.$whitespace.'}$#',
23958 addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $whitespace . '}', '\\$'),
23959 $children
23960 );
23961 } else {
23962 if ($subName !== null) {
23963 $value = array($subName => $value);
23964 }
23965
23966
23967  $children = '{' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $whitespace . '}';
23968 }
23969 }
23970
23971 $this->contents = preg_replace_callback($nodeRegex, function ($m) use ($children) {
23972 return $m['start'] . $children . $m['end'];
23973 }, $this->contents);
23974
23975 return true;
23976 }
23977
23978 public function removeSubNode($mainNode, $name)
23979 {
23980 $decoded = JsonFile::parseJson($this->contents);
23981
23982
23983  if (empty($decoded[$mainNode])) {
23984 return true;
23985 }
23986
23987
23988  $nodeRegex = '{'.self::$DEFINES.'^(?P<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
23989 preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}sx';
23990 try {
23991 if (!$this->pregMatch($nodeRegex, $this->contents, $match)) {
23992 return false;
23993 }
23994 } catch (\RuntimeException $e) {
23995 if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
23996 return false;
23997 }
23998 throw $e;
23999 }
24000
24001 $children = $match['content'];
24002
24003
24004  if (!@json_decode($children, true)) {
24005 return false;
24006 }
24007
24008 $subName = null;
24009 if (in_array($mainNode, array('config', 'extra')) && false !== strpos($name, '.')) {
24010 list($name, $subName) = explode('.', $name, 2);
24011 }
24012
24013
24014  if (!isset($decoded[$mainNode][$name]) || ($subName && !isset($decoded[$mainNode][$name][$subName]))) {
24015 return true;
24016 }
24017
24018
24019  if ($this->pregMatch('{"'.preg_quote($name).'"\s*:}i', $children)) {
24020
24021  if (preg_match_all('{'.self::$DEFINES.'"'.preg_quote($name).'"\s*:\s*(?:(?&json))}x', $children, $matches)) {
24022 $bestMatch = '';
24023 foreach ($matches[0] as $match) {
24024 if (strlen($bestMatch) < strlen($match)) {
24025 $bestMatch = $match;
24026 }
24027 }
24028 $childrenClean = preg_replace('{,\s*'.preg_quote($bestMatch).'}i', '', $children, -1, $count);
24029 if (1 !== $count) {
24030 $childrenClean = preg_replace('{'.preg_quote($bestMatch).'\s*,?\s*}i', '', $childrenClean, -1, $count);
24031 if (1 !== $count) {
24032 return false;
24033 }
24034 }
24035 }
24036 } else {
24037 $childrenClean = $children;
24038 }
24039
24040
24041  $this->pregMatch('#^{ \s*? (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $childrenClean, $match);
24042 if (empty($match['content'])) {
24043 $newline = $this->newline;
24044 $indent = $this->indent;
24045
24046 $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($indent, $newline) {
24047 return $matches['start'] . '{' . $newline . $indent . '}' . $matches['end'];
24048 }, $this->contents);
24049
24050
24051  if ($subName !== null) {
24052 $curVal = json_decode($children, true);
24053 unset($curVal[$name][$subName]);
24054 $this->addSubNode($mainNode, $name, $curVal[$name]);
24055 }
24056
24057 return true;
24058 }
24059
24060 $that = $this;
24061 $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($that, $name, $subName, $childrenClean) {
24062 if ($subName !== null) {
24063 $curVal = json_decode($matches['content'], true);
24064 unset($curVal[$name][$subName]);
24065 $childrenClean = $that->format($curVal, 0);
24066 }
24067
24068 return $matches['start'] . $childrenClean . $matches['end'];
24069 }, $this->contents);
24070
24071 return true;
24072 }
24073
24074 public function addMainKey($key, $content)
24075 {
24076 $decoded = JsonFile::parseJson($this->contents);
24077 $content = $this->format($content);
24078
24079
24080  $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
24081 '(?P<key>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))(?P<end>.*)}sx';
24082 if (isset($decoded[$key]) && $this->pregMatch($regex, $this->contents, $matches)) {
24083
24084  if (!@json_decode('{'.$matches['key'].'}')) {
24085 return false;
24086 }
24087
24088 $this->contents = $matches['start'] . JsonFile::encode($key).': '.$content . $matches['end'];
24089
24090 return true;
24091 }
24092
24093
24094  if ($this->pregMatch('#[^{\s](\s*)\}$#', $this->contents, $match)) {
24095 $this->contents = preg_replace(
24096 '#'.$match[1].'\}$#',
24097 addcslashes(',' . $this->newline . $this->indent . JsonFile::encode($key). ': '. $content . $this->newline . '}', '\\$'),
24098 $this->contents
24099 );
24100
24101 return true;
24102 }
24103
24104
24105  $this->contents = preg_replace(
24106 '#\}$#',
24107 addcslashes($this->indent . JsonFile::encode($key). ': '.$content . $this->newline . '}', '\\$'),
24108 $this->contents
24109 );
24110
24111 return true;
24112 }
24113
24114 public function removeMainKey($key)
24115 {
24116 $decoded = JsonFile::parseJson($this->contents);
24117
24118 if (!isset($decoded[$key])) {
24119 return true;
24120 }
24121
24122
24123  $regex = '{'.self::$DEFINES.'^(?P<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
24124 '(?P<removal>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))\s*,?\s*(?P<end>.*)}sx';
24125 if ($this->pregMatch($regex, $this->contents, $matches)) {
24126
24127  if (!@json_decode('{'.$matches['removal'].'}')) {
24128 return false;
24129 }
24130
24131
24132  if (preg_match('#,\s*$#', $matches['start']) && preg_match('#^\}$#', $matches['end'])) {
24133 $matches['start'] = rtrim(preg_replace('#,(\s*)$#', '$1', $matches['start']), $this->indent);
24134 }
24135
24136 $this->contents = $matches['start'] . $matches['end'];
24137 if (preg_match('#^\{\s*\}\s*$#', $this->contents)) {
24138 $this->contents = "{\n}";
24139 }
24140
24141 return true;
24142 }
24143
24144 return false;
24145 }
24146
24147 public function format($data, $depth = 0)
24148 {
24149 if (is_array($data)) {
24150 reset($data);
24151
24152 if (is_numeric(key($data))) {
24153 foreach ($data as $key => $val) {
24154 $data[$key] = $this->format($val, $depth + 1);
24155 }
24156
24157 return '['.implode(', ', $data).']';
24158 }
24159
24160 $out = '{' . $this->newline;
24161 $elems = array();
24162 foreach ($data as $key => $val) {
24163 $elems[] = str_repeat($this->indent, $depth + 2) . JsonFile::encode($key). ': '.$this->format($val, $depth + 1);
24164 }
24165
24166 return $out . implode(','.$this->newline, $elems) . $this->newline . str_repeat($this->indent, $depth + 1) . '}';
24167 }
24168
24169 return JsonFile::encode($data);
24170 }
24171
24172 protected function detectIndenting()
24173 {
24174 if ($this->pregMatch('{^([ \t]+)"}m', $this->contents, $match)) {
24175 $this->indent = $match[1];
24176 } else {
24177 $this->indent = '    ';
24178 }
24179 }
24180
24181 protected function pregMatch($re, $str, &$matches = array())
24182 {
24183 $count = preg_match($re, $str, $matches);
24184
24185 if ($count === false) {
24186 switch (preg_last_error()) {
24187 case PREG_NO_ERROR:
24188 throw new \RuntimeException('Failed to execute regex: PREG_NO_ERROR', PREG_NO_ERROR);
24189 case PREG_INTERNAL_ERROR:
24190 throw new \RuntimeException('Failed to execute regex: PREG_INTERNAL_ERROR', PREG_INTERNAL_ERROR);
24191 case PREG_BACKTRACK_LIMIT_ERROR:
24192 throw new \RuntimeException('Failed to execute regex: PREG_BACKTRACK_LIMIT_ERROR', PREG_BACKTRACK_LIMIT_ERROR);
24193 case PREG_RECURSION_LIMIT_ERROR:
24194 throw new \RuntimeException('Failed to execute regex: PREG_RECURSION_LIMIT_ERROR', PREG_RECURSION_LIMIT_ERROR);
24195 case PREG_BAD_UTF8_ERROR:
24196 throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_ERROR', PREG_BAD_UTF8_ERROR);
24197 case PREG_BAD_UTF8_OFFSET_ERROR:
24198 throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_OFFSET_ERROR', PREG_BAD_UTF8_OFFSET_ERROR);
24199 case 6: 
24200  if (PHP_VERSION_ID > 70000) {
24201 throw new \RuntimeException('Failed to execute regex: PREG_JIT_STACKLIMIT_ERROR', 6);
24202 }
24203
24204
24205 default:
24206 throw new \RuntimeException('Failed to execute regex: Unknown error');
24207 }
24208 }
24209
24210 return $count;
24211 }
24212 }
24213 <?php
24214
24215
24216
24217
24218
24219
24220
24221
24222
24223
24224
24225 namespace Composer\Json;
24226
24227 use Exception;
24228
24229
24230
24231
24232 class JsonValidationException extends Exception
24233 {
24234 protected $errors;
24235
24236 public function __construct($message, $errors = array(), Exception $previous = null)
24237 {
24238 $this->errors = $errors;
24239 parent::__construct($message, 0, $previous);
24240 }
24241
24242 public function getErrors()
24243 {
24244 return $this->errors;
24245 }
24246 }
24247 <?php
24248
24249
24250
24251
24252
24253
24254
24255
24256
24257
24258
24259 namespace Composer\Package;
24260
24261 use Composer\Semver\Constraint\Constraint;
24262 use Composer\Package\Version\VersionParser;
24263
24264
24265
24266
24267 class AliasPackage extends BasePackage implements CompletePackageInterface
24268 {
24269 protected $version;
24270 protected $prettyVersion;
24271 protected $dev;
24272 protected $rootPackageAlias = false;
24273 protected $stability;
24274
24275
24276 protected $aliasOf;
24277
24278 protected $requires;
24279
24280 protected $devRequires;
24281
24282 protected $conflicts;
24283
24284 protected $provides;
24285
24286 protected $replaces;
24287
24288
24289
24290
24291
24292
24293
24294
24295 public function __construct(PackageInterface $aliasOf, $version, $prettyVersion)
24296 {
24297 parent::__construct($aliasOf->getName());
24298
24299 $this->version = $version;
24300 $this->prettyVersion = $prettyVersion;
24301 $this->aliasOf = $aliasOf;
24302 $this->stability = VersionParser::parseStability($version);
24303 $this->dev = $this->stability === 'dev';
24304
24305 foreach (array('requires', 'devRequires', 'conflicts', 'provides', 'replaces') as $type) {
24306 $links = $aliasOf->{'get' . ucfirst($type)}();
24307 $this->$type = $this->replaceSelfVersionDependencies($links, $type);
24308 }
24309 }
24310
24311
24312
24313
24314 public function getAliasOf()
24315 {
24316 return $this->aliasOf;
24317 }
24318
24319
24320
24321
24322 public function getVersion()
24323 {
24324 return $this->version;
24325 }
24326
24327
24328
24329
24330 public function getStability()
24331 {
24332 return $this->stability;
24333 }
24334
24335
24336
24337
24338 public function getPrettyVersion()
24339 {
24340 return $this->prettyVersion;
24341 }
24342
24343
24344
24345
24346 public function isDev()
24347 {
24348 return $this->dev;
24349 }
24350
24351
24352
24353
24354 public function getRequires()
24355 {
24356 return $this->requires;
24357 }
24358
24359
24360
24361
24362 public function getConflicts()
24363 {
24364 return $this->conflicts;
24365 }
24366
24367
24368
24369
24370 public function getProvides()
24371 {
24372 return $this->provides;
24373 }
24374
24375
24376
24377
24378 public function getReplaces()
24379 {
24380 return $this->replaces;
24381 }
24382
24383
24384
24385
24386 public function getDevRequires()
24387 {
24388 return $this->devRequires;
24389 }
24390
24391
24392
24393
24394
24395
24396
24397
24398
24399
24400 public function setRootPackageAlias($value)
24401 {
24402 return $this->rootPackageAlias = $value;
24403 }
24404
24405
24406
24407
24408
24409 public function isRootPackageAlias()
24410 {
24411 return $this->rootPackageAlias;
24412 }
24413
24414
24415
24416
24417
24418
24419
24420 protected function replaceSelfVersionDependencies(array $links, $linkType)
24421 {
24422 if (in_array($linkType, array('conflicts', 'provides', 'replaces'), true)) {
24423 $newLinks = array();
24424 foreach ($links as $link) {
24425
24426  if ('self.version' === $link->getPrettyConstraint()) {
24427 $newLinks[] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
24428 }
24429 }
24430 $links = array_merge($links, $newLinks);
24431 } else {
24432 foreach ($links as $index => $link) {
24433 if ('self.version' === $link->getPrettyConstraint()) {
24434 $links[$index] = new Link($link->getSource(), $link->getTarget(), new Constraint('=', $this->version), $linkType, $this->prettyVersion);
24435 }
24436 }
24437 }
24438
24439 return $links;
24440 }
24441
24442
24443
24444
24445
24446 public function getType()
24447 {
24448 return $this->aliasOf->getType();
24449 }
24450
24451 public function getTargetDir()
24452 {
24453 return $this->aliasOf->getTargetDir();
24454 }
24455
24456 public function getExtra()
24457 {
24458 return $this->aliasOf->getExtra();
24459 }
24460
24461 public function setInstallationSource($type)
24462 {
24463 $this->aliasOf->setInstallationSource($type);
24464 }
24465
24466 public function getInstallationSource()
24467 {
24468 return $this->aliasOf->getInstallationSource();
24469 }
24470
24471 public function getSourceType()
24472 {
24473 return $this->aliasOf->getSourceType();
24474 }
24475
24476 public function getSourceUrl()
24477 {
24478 return $this->aliasOf->getSourceUrl();
24479 }
24480
24481 public function getSourceUrls()
24482 {
24483 return $this->aliasOf->getSourceUrls();
24484 }
24485
24486 public function getSourceReference()
24487 {
24488 return $this->aliasOf->getSourceReference();
24489 }
24490
24491 public function setSourceReference($reference)
24492 {
24493 return $this->aliasOf->setSourceReference($reference);
24494 }
24495
24496 public function setSourceMirrors($mirrors)
24497 {
24498 return $this->aliasOf->setSourceMirrors($mirrors);
24499 }
24500
24501 public function getSourceMirrors()
24502 {
24503 return $this->aliasOf->getSourceMirrors();
24504 }
24505
24506 public function getDistType()
24507 {
24508 return $this->aliasOf->getDistType();
24509 }
24510
24511 public function getDistUrl()
24512 {
24513 return $this->aliasOf->getDistUrl();
24514 }
24515
24516 public function getDistUrls()
24517 {
24518 return $this->aliasOf->getDistUrls();
24519 }
24520
24521 public function getDistReference()
24522 {
24523 return $this->aliasOf->getDistReference();
24524 }
24525
24526 public function setDistReference($reference)
24527 {
24528 return $this->aliasOf->setDistReference($reference);
24529 }
24530
24531 public function getDistSha1Checksum()
24532 {
24533 return $this->aliasOf->getDistSha1Checksum();
24534 }
24535
24536 public function setTransportOptions(array $options)
24537 {
24538 return $this->aliasOf->setTransportOptions($options);
24539 }
24540
24541 public function getTransportOptions()
24542 {
24543 return $this->aliasOf->getTransportOptions();
24544 }
24545
24546 public function setDistMirrors($mirrors)
24547 {
24548 return $this->aliasOf->setDistMirrors($mirrors);
24549 }
24550
24551 public function getDistMirrors()
24552 {
24553 return $this->aliasOf->getDistMirrors();
24554 }
24555
24556 public function getScripts()
24557 {
24558 return $this->aliasOf->getScripts();
24559 }
24560
24561 public function getLicense()
24562 {
24563 return $this->aliasOf->getLicense();
24564 }
24565
24566 public function getAutoload()
24567 {
24568 return $this->aliasOf->getAutoload();
24569 }
24570
24571 public function getDevAutoload()
24572 {
24573 return $this->aliasOf->getDevAutoload();
24574 }
24575
24576 public function getIncludePaths()
24577 {
24578 return $this->aliasOf->getIncludePaths();
24579 }
24580
24581 public function getRepositories()
24582 {
24583 return $this->aliasOf->getRepositories();
24584 }
24585
24586 public function getReleaseDate()
24587 {
24588 return $this->aliasOf->getReleaseDate();
24589 }
24590
24591 public function getBinaries()
24592 {
24593 return $this->aliasOf->getBinaries();
24594 }
24595
24596 public function getKeywords()
24597 {
24598 return $this->aliasOf->getKeywords();
24599 }
24600
24601 public function getDescription()
24602 {
24603 return $this->aliasOf->getDescription();
24604 }
24605
24606 public function getHomepage()
24607 {
24608 return $this->aliasOf->getHomepage();
24609 }
24610
24611 public function getSuggests()
24612 {
24613 return $this->aliasOf->getSuggests();
24614 }
24615
24616 public function getAuthors()
24617 {
24618 return $this->aliasOf->getAuthors();
24619 }
24620
24621 public function getSupport()
24622 {
24623 return $this->aliasOf->getSupport();
24624 }
24625
24626 public function getNotificationUrl()
24627 {
24628 return $this->aliasOf->getNotificationUrl();
24629 }
24630
24631 public function getArchiveExcludes()
24632 {
24633 return $this->aliasOf->getArchiveExcludes();
24634 }
24635
24636 public function isAbandoned()
24637 {
24638 return $this->aliasOf->isAbandoned();
24639 }
24640
24641 public function getReplacementPackage()
24642 {
24643 return $this->aliasOf->getReplacementPackage();
24644 }
24645
24646 public function __toString()
24647 {
24648 return parent::__toString().' (alias of '.$this->aliasOf->getVersion().')';
24649 }
24650 }
24651 <?php
24652
24653
24654
24655
24656
24657
24658
24659
24660
24661
24662
24663 namespace Composer\Package\Archiver;
24664
24665 use FilterIterator;
24666 use PharData;
24667
24668 class ArchivableFilesFilter extends FilterIterator
24669 {
24670 private $dirs = array();
24671
24672
24673
24674
24675 public function accept()
24676 {
24677 $file = $this->getInnerIterator()->current();
24678 if ($file->isDir()) {
24679 $this->dirs[] = (string) $file;
24680
24681 return false;
24682 }
24683
24684 return true;
24685 }
24686
24687 public function addEmptyDir(PharData $phar, $sources)
24688 {
24689 foreach ($this->dirs as $filepath) {
24690 $localname = str_replace($sources . "/", '', $filepath);
24691 $phar->addEmptyDir($localname);
24692 }
24693 }
24694 }
24695 <?php
24696
24697
24698
24699
24700
24701
24702
24703
24704
24705
24706
24707 namespace Composer\Package\Archiver;
24708
24709 use Composer\Util\Filesystem;
24710 use FilesystemIterator;
24711 use Symfony\Component\Finder\Finder;
24712 use Symfony\Component\Finder\SplFileInfo;
24713
24714
24715
24716
24717
24718
24719
24720
24721
24722 class ArchivableFilesFinder extends \FilterIterator
24723 {
24724
24725
24726
24727 protected $finder;
24728
24729
24730
24731
24732
24733
24734
24735
24736 public function __construct($sources, array $excludes, $ignoreFilters = false)
24737 {
24738 $fs = new Filesystem();
24739
24740 $sources = $fs->normalizePath($sources);
24741
24742 if ($ignoreFilters) {
24743 $filters = array();
24744 } else {
24745 $filters = array(
24746 new HgExcludeFilter($sources),
24747 new GitExcludeFilter($sources),
24748 new ComposerExcludeFilter($sources, $excludes),
24749 );
24750 }
24751
24752 $this->finder = new Finder();
24753
24754 $filter = function (\SplFileInfo $file) use ($sources, $filters, $fs) {
24755 if ($file->isLink() && strpos($file->getLinkTarget(), $sources) !== 0) {
24756 return false;
24757 }
24758
24759 $relativePath = preg_replace(
24760 '#^'.preg_quote($sources, '#').'#',
24761 '',
24762 $fs->normalizePath($file->getRealPath())
24763 );
24764
24765 $exclude = false;
24766 foreach ($filters as $filter) {
24767 $exclude = $filter->filter($relativePath, $exclude);
24768 }
24769
24770 return !$exclude;
24771 };
24772
24773 if (method_exists($filter, 'bindTo')) {
24774 $filter = $filter->bindTo(null);
24775 }
24776
24777 $this->finder
24778 ->in($sources)
24779 ->filter($filter)
24780 ->ignoreVCS(true)
24781 ->ignoreDotFiles(false);
24782
24783 parent::__construct($this->finder->getIterator());
24784 }
24785
24786 public function accept()
24787 {
24788
24789 $current = $this->getInnerIterator()->current();
24790
24791 if (!$current->isDir()) {
24792 return true;
24793 }
24794
24795 $iterator = new FilesystemIterator($current, FilesystemIterator::SKIP_DOTS);
24796
24797 return !$iterator->valid();
24798 }
24799 }
24800 <?php
24801
24802
24803
24804
24805
24806
24807
24808
24809
24810
24811
24812 namespace Composer\Package\Archiver;
24813
24814 use Composer\Downloader\DownloadManager;
24815 use Composer\Package\PackageInterface;
24816 use Composer\Package\RootPackageInterface;
24817 use Composer\Util\Filesystem;
24818 use Composer\Json\JsonFile;
24819
24820
24821
24822
24823
24824 class ArchiveManager
24825 {
24826 protected $downloadManager;
24827
24828 protected $archivers = array();
24829
24830
24831
24832
24833 protected $overwriteFiles = true;
24834
24835
24836
24837
24838 public function __construct(DownloadManager $downloadManager)
24839 {
24840 $this->downloadManager = $downloadManager;
24841 }
24842
24843
24844
24845
24846 public function addArchiver(ArchiverInterface $archiver)
24847 {
24848 $this->archivers[] = $archiver;
24849 }
24850
24851
24852
24853
24854
24855
24856
24857
24858 public function setOverwriteFiles($overwriteFiles)
24859 {
24860 $this->overwriteFiles = $overwriteFiles;
24861
24862 return $this;
24863 }
24864
24865
24866
24867
24868
24869
24870
24871
24872 public function getPackageFilename(PackageInterface $package)
24873 {
24874 $nameParts = array(preg_replace('#[^a-z0-9-_]#i', '-', $package->getName()));
24875
24876 if (preg_match('{^[a-f0-9]{40}$}', $package->getDistReference())) {
24877 $nameParts = array_merge($nameParts, array($package->getDistReference(), $package->getDistType()));
24878 } else {
24879 $nameParts = array_merge($nameParts, array($package->getPrettyVersion(), $package->getDistReference()));
24880 }
24881
24882 if ($package->getSourceReference()) {
24883 $nameParts[] = substr(sha1($package->getSourceReference()), 0, 6);
24884 }
24885
24886 $name = implode('-', array_filter($nameParts, function ($p) {
24887 return !empty($p);
24888 }));
24889
24890 return str_replace('/', '-', $name);
24891 }
24892
24893
24894
24895
24896
24897
24898
24899
24900
24901
24902
24903
24904
24905
24906 public function archive(PackageInterface $package, $format, $targetDir, $fileName = null, $ignoreFilters = false)
24907 {
24908 if (empty($format)) {
24909 throw new \InvalidArgumentException('Format must be specified');
24910 }
24911
24912
24913  $usableArchiver = null;
24914 foreach ($this->archivers as $archiver) {
24915 if ($archiver->supports($format, $package->getSourceType())) {
24916 $usableArchiver = $archiver;
24917 break;
24918 }
24919 }
24920
24921
24922  if (null === $usableArchiver) {
24923 throw new \RuntimeException(sprintf('No archiver found to support %s format', $format));
24924 }
24925
24926 $filesystem = new Filesystem();
24927 if (null === $fileName) {
24928 $packageName = $this->getPackageFilename($package);
24929 } else {
24930 $packageName = $fileName;
24931 }
24932
24933
24934  $filesystem->ensureDirectoryExists($targetDir);
24935 $target = realpath($targetDir).'/'.$packageName.'.'.$format;
24936 $filesystem->ensureDirectoryExists(dirname($target));
24937
24938 if (!$this->overwriteFiles && file_exists($target)) {
24939 return $target;
24940 }
24941
24942 if ($package instanceof RootPackageInterface) {
24943 $sourcePath = realpath('.');
24944 } else {
24945
24946  $sourcePath = sys_get_temp_dir().'/composer_archive'.uniqid();
24947 $filesystem->ensureDirectoryExists($sourcePath);
24948
24949
24950  $this->downloadManager->download($package, $sourcePath);
24951
24952
24953  if (file_exists($composerJsonPath = $sourcePath.'/composer.json')) {
24954 $jsonFile = new JsonFile($composerJsonPath);
24955 $jsonData = $jsonFile->read();
24956 if (!empty($jsonData['archive']['exclude'])) {
24957 $package->setArchiveExcludes($jsonData['archive']['exclude']);
24958 }
24959 }
24960 }
24961
24962
24963  $tempTarget = sys_get_temp_dir().'/composer_archive'.uniqid().'.'.$format;
24964 $filesystem->ensureDirectoryExists(dirname($tempTarget));
24965
24966 $archivePath = $usableArchiver->archive($sourcePath, $tempTarget, $format, $package->getArchiveExcludes(), $ignoreFilters);
24967 $filesystem->rename($archivePath, $target);
24968
24969
24970  if (!$package instanceof RootPackageInterface) {
24971 $filesystem->removeDirectory($sourcePath);
24972 }
24973 $filesystem->remove($tempTarget);
24974
24975 return $target;
24976 }
24977 }
24978 <?php
24979
24980
24981
24982
24983
24984
24985
24986
24987
24988
24989
24990 namespace Composer\Package\Archiver;
24991
24992
24993
24994
24995
24996
24997 interface ArchiverInterface
24998 {
24999
25000
25001
25002
25003
25004
25005
25006
25007
25008
25009 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false);
25010
25011
25012
25013
25014
25015
25016
25017
25018
25019 public function supports($format, $sourceType);
25020 }
25021 <?php
25022
25023
25024
25025
25026
25027
25028
25029
25030
25031
25032
25033 namespace Composer\Package\Archiver;
25034
25035 use Symfony\Component\Finder;
25036
25037
25038
25039
25040 abstract class BaseExcludeFilter
25041 {
25042
25043
25044
25045 protected $sourcePath;
25046
25047
25048
25049
25050 protected $excludePatterns;
25051
25052
25053
25054
25055 public function __construct($sourcePath)
25056 {
25057 $this->sourcePath = $sourcePath;
25058 $this->excludePatterns = array();
25059 }
25060
25061
25062
25063
25064
25065
25066
25067
25068
25069
25070
25071 public function filter($relativePath, $exclude)
25072 {
25073 foreach ($this->excludePatterns as $patternData) {
25074 list($pattern, $negate, $stripLeadingSlash) = $patternData;
25075
25076 if ($stripLeadingSlash) {
25077 $path = substr($relativePath, 1);
25078 } else {
25079 $path = $relativePath;
25080 }
25081
25082 if (preg_match($pattern, $path)) {
25083 $exclude = !$negate;
25084 }
25085 }
25086
25087 return $exclude;
25088 }
25089
25090
25091
25092
25093
25094
25095
25096
25097
25098 protected function parseLines(array $lines, $lineParser)
25099 {
25100 return array_filter(
25101 array_map(
25102 function ($line) use ($lineParser) {
25103 $line = trim($line);
25104
25105 if (!$line || 0 === strpos($line, '#')) {
25106 return null;
25107 }
25108
25109 return call_user_func($lineParser, $line);
25110 },
25111 $lines
25112 ),
25113 function ($pattern) {
25114 return $pattern !== null;
25115 }
25116 );
25117 }
25118
25119
25120
25121
25122
25123
25124
25125
25126 protected function generatePatterns($rules)
25127 {
25128 $patterns = array();
25129 foreach ($rules as $rule) {
25130 $patterns[] = $this->generatePattern($rule);
25131 }
25132
25133 return $patterns;
25134 }
25135
25136
25137
25138
25139
25140
25141
25142
25143 protected function generatePattern($rule)
25144 {
25145 $negate = false;
25146 $pattern = '{';
25147
25148 if (strlen($rule) && $rule[0] === '!') {
25149 $negate = true;
25150 $rule = substr($rule, 1);
25151 }
25152
25153 if (strlen($rule) && $rule[0] === '/') {
25154 $pattern .= '^/';
25155 $rule = substr($rule, 1);
25156 } elseif (strlen($rule) - 1 === strpos($rule, '/')) {
25157 $pattern .= '/';
25158 $rule = substr($rule, 0, -1);
25159 } elseif (false === strpos($rule, '/')) {
25160 $pattern .= '/';
25161 }
25162
25163
25164  $pattern .= substr(Finder\Glob::toRegex($rule), 2, -2) . '(?=$|/)';
25165
25166 return array($pattern . '}', $negate, false);
25167 }
25168 }
25169 <?php
25170
25171
25172
25173
25174
25175
25176
25177
25178
25179
25180
25181 namespace Composer\Package\Archiver;
25182
25183
25184
25185
25186
25187
25188 class ComposerExcludeFilter extends BaseExcludeFilter
25189 {
25190
25191
25192
25193
25194 public function __construct($sourcePath, array $excludeRules)
25195 {
25196 parent::__construct($sourcePath);
25197 $this->excludePatterns = $this->generatePatterns($excludeRules);
25198 }
25199 }
25200 <?php
25201
25202
25203
25204
25205
25206
25207
25208
25209
25210
25211
25212 namespace Composer\Package\Archiver;
25213
25214
25215
25216
25217
25218
25219
25220
25221 class GitExcludeFilter extends BaseExcludeFilter
25222 {
25223
25224
25225
25226
25227
25228 public function __construct($sourcePath)
25229 {
25230 parent::__construct($sourcePath);
25231
25232 if (file_exists($sourcePath.'/.gitignore')) {
25233 $this->excludePatterns = $this->parseLines(
25234 file($sourcePath.'/.gitignore'),
25235 array($this, 'parseGitIgnoreLine')
25236 );
25237 }
25238 if (file_exists($sourcePath.'/.gitattributes')) {
25239 $this->excludePatterns = array_merge(
25240 $this->excludePatterns,
25241 $this->parseLines(
25242 file($sourcePath.'/.gitattributes'),
25243 array($this, 'parseGitAttributesLine')
25244 ));
25245 }
25246 }
25247
25248
25249
25250
25251
25252
25253
25254
25255 public function parseGitIgnoreLine($line)
25256 {
25257 return $this->generatePattern($line);
25258 }
25259
25260
25261
25262
25263
25264
25265
25266
25267 public function parseGitAttributesLine($line)
25268 {
25269 $parts = preg_split('#\s+#', $line);
25270
25271 if (count($parts) == 2 && $parts[1] === 'export-ignore') {
25272 return $this->generatePattern($parts[0]);
25273 }
25274
25275 return null;
25276 }
25277 }
25278 <?php
25279
25280
25281
25282
25283
25284
25285
25286
25287
25288
25289
25290 namespace Composer\Package\Archiver;
25291
25292 use Symfony\Component\Finder;
25293
25294
25295
25296
25297
25298
25299 class HgExcludeFilter extends BaseExcludeFilter
25300 {
25301 const HG_IGNORE_REGEX = 1;
25302 const HG_IGNORE_GLOB = 2;
25303
25304
25305
25306
25307
25308 protected $patternMode;
25309
25310
25311
25312
25313
25314
25315 public function __construct($sourcePath)
25316 {
25317 parent::__construct($sourcePath);
25318
25319 $this->patternMode = self::HG_IGNORE_REGEX;
25320
25321 if (file_exists($sourcePath.'/.hgignore')) {
25322 $this->excludePatterns = $this->parseLines(
25323 file($sourcePath.'/.hgignore'),
25324 array($this, 'parseHgIgnoreLine')
25325 );
25326 }
25327 }
25328
25329
25330
25331
25332
25333
25334
25335
25336 public function parseHgIgnoreLine($line)
25337 {
25338 if (preg_match('#^syntax\s*:\s*(glob|regexp)$#', $line, $matches)) {
25339 if ($matches[1] === 'glob') {
25340 $this->patternMode = self::HG_IGNORE_GLOB;
25341 } else {
25342 $this->patternMode = self::HG_IGNORE_REGEX;
25343 }
25344
25345 return null;
25346 }
25347
25348 if ($this->patternMode == self::HG_IGNORE_GLOB) {
25349 return $this->patternFromGlob($line);
25350 } else {
25351 return $this->patternFromRegex($line);
25352 }
25353 }
25354
25355
25356
25357
25358
25359
25360
25361
25362 protected function patternFromGlob($line)
25363 {
25364 $pattern = '#'.substr(Finder\Glob::toRegex($line), 2, -1).'#';
25365 $pattern = str_replace('[^/]*', '.*', $pattern);
25366
25367 return array($pattern, false, true);
25368 }
25369
25370
25371
25372
25373
25374
25375
25376
25377 public function patternFromRegex($line)
25378 {
25379
25380  $pattern = '#'.preg_replace('/((?:\\\\\\\\)*)(\\\\?)#/', '\1\2\2\\#', $line).'#';
25381
25382 return array($pattern, false, true);
25383 }
25384 }
25385 <?php
25386
25387
25388
25389
25390
25391
25392
25393
25394
25395
25396
25397 namespace Composer\Package\Archiver;
25398
25399
25400
25401
25402
25403
25404 class PharArchiver implements ArchiverInterface
25405 {
25406 protected static $formats = array(
25407 'zip' => \Phar::ZIP,
25408 'tar' => \Phar::TAR,
25409 'tar.gz' => \Phar::TAR,
25410 'tar.bz2' => \Phar::TAR,
25411 );
25412
25413 protected static $compressFormats = array(
25414 'tar.gz' => \Phar::GZ,
25415 'tar.bz2' => \Phar::BZ2,
25416 );
25417
25418
25419
25420
25421 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false)
25422 {
25423 $sources = realpath($sources);
25424
25425
25426  if (file_exists($target)) {
25427 unlink($target);
25428 }
25429
25430 try {
25431 $filename = substr($target, 0, strrpos($target, $format) - 1);
25432
25433
25434  if (isset(static::$compressFormats[$format])) {
25435
25436  $target = $filename . '.tar';
25437 }
25438
25439 $phar = new \PharData($target, null, null, static::$formats[$format]);
25440 $files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
25441 $filesOnly = new ArchivableFilesFilter($files);
25442 $phar->buildFromIterator($filesOnly, $sources);
25443 $filesOnly->addEmptyDir($phar, $sources);
25444
25445 if (isset(static::$compressFormats[$format])) {
25446
25447  if (!$phar->canCompress(static::$compressFormats[$format])) {
25448 throw new \RuntimeException(sprintf('Can not compress to %s format', $format));
25449 }
25450
25451
25452  unlink($target);
25453
25454
25455  $phar->compress(static::$compressFormats[$format]);
25456
25457
25458  $target = $filename . '.' . $format;
25459 }
25460
25461 return $target;
25462 } catch (\UnexpectedValueException $e) {
25463 $message = sprintf("Could not create archive '%s' from '%s': %s",
25464 $target,
25465 $sources,
25466 $e->getMessage()
25467 );
25468
25469 throw new \RuntimeException($message, $e->getCode(), $e);
25470 }
25471 }
25472
25473
25474
25475
25476 public function supports($format, $sourceType)
25477 {
25478 return isset(static::$formats[$format]);
25479 }
25480 }
25481 <?php
25482
25483
25484
25485
25486
25487
25488
25489
25490
25491
25492
25493 namespace Composer\Package\Archiver;
25494
25495 use ZipArchive;
25496 use Composer\Util\Filesystem;
25497
25498
25499
25500
25501 class ZipArchiver implements ArchiverInterface
25502 {
25503 protected static $formats = array(
25504 'zip' => 1,
25505 );
25506
25507
25508
25509
25510 public function archive($sources, $target, $format, array $excludes = array(), $ignoreFilters = false)
25511 {
25512 $fs = new Filesystem();
25513 $sources = $fs->normalizePath($sources);
25514
25515 $zip = new ZipArchive();
25516 $res = $zip->open($target, ZipArchive::CREATE);
25517 if ($res === true) {
25518 $files = new ArchivableFilesFinder($sources, $excludes, $ignoreFilters);
25519 foreach ($files as $file) {
25520
25521 $filepath = strtr($file->getPath()."/".$file->getFilename(), '\\', '/');
25522 $localname = str_replace($sources.'/', '', $filepath);
25523 if ($file->isDir()) {
25524 $zip->addEmptyDir($localname);
25525 } else {
25526 $zip->addFile($filepath, $localname);
25527 }
25528 }
25529 if ($zip->close()) {
25530 return $target;
25531 }
25532 }
25533 $message = sprintf("Could not create archive '%s' from '%s': %s",
25534 $target,
25535 $sources,
25536 $zip->getStatusString()
25537 );
25538 throw new \RuntimeException($message);
25539 }
25540
25541
25542
25543
25544 public function supports($format, $sourceType)
25545 {
25546 return isset(static::$formats[$format]) && $this->compressionAvailable();
25547 }
25548
25549 private function compressionAvailable()
25550 {
25551 return class_exists('ZipArchive');
25552 }
25553 }
25554 <?php
25555
25556
25557
25558
25559
25560
25561
25562
25563
25564
25565
25566 namespace Composer\Package;
25567
25568 use Composer\Repository\RepositoryInterface;
25569 use Composer\Repository\PlatformRepository;
25570
25571
25572
25573
25574
25575
25576 abstract class BasePackage implements PackageInterface
25577 {
25578 public static $supportedLinkTypes = array(
25579 'require' => array('description' => 'requires', 'method' => 'requires'),
25580 'conflict' => array('description' => 'conflicts', 'method' => 'conflicts'),
25581 'provide' => array('description' => 'provides', 'method' => 'provides'),
25582 'replace' => array('description' => 'replaces', 'method' => 'replaces'),
25583 'require-dev' => array('description' => 'requires (for development)', 'method' => 'devRequires'),
25584 );
25585
25586 const STABILITY_STABLE = 0;
25587 const STABILITY_RC = 5;
25588 const STABILITY_BETA = 10;
25589 const STABILITY_ALPHA = 15;
25590 const STABILITY_DEV = 20;
25591
25592 public static $stabilities = array(
25593 'stable' => self::STABILITY_STABLE,
25594 'RC' => self::STABILITY_RC,
25595 'beta' => self::STABILITY_BETA,
25596 'alpha' => self::STABILITY_ALPHA,
25597 'dev' => self::STABILITY_DEV,
25598 );
25599
25600
25601
25602
25603
25604 public $id;
25605
25606 protected $name;
25607
25608 protected $prettyName;
25609
25610 protected $repository;
25611
25612 protected $transportOptions = array();
25613
25614
25615
25616
25617
25618
25619 public function __construct($name)
25620 {
25621 $this->prettyName = $name;
25622 $this->name = strtolower($name);
25623 $this->id = -1;
25624 }
25625
25626
25627
25628
25629 public function getName()
25630 {
25631 return $this->name;
25632 }
25633
25634
25635
25636
25637 public function getPrettyName()
25638 {
25639 return $this->prettyName;
25640 }
25641
25642
25643
25644
25645 public function getNames()
25646 {
25647 $names = array(
25648 $this->getName() => true,
25649 );
25650
25651 foreach ($this->getProvides() as $link) {
25652 $names[$link->getTarget()] = true;
25653 }
25654
25655 foreach ($this->getReplaces() as $link) {
25656 $names[$link->getTarget()] = true;
25657 }
25658
25659 return array_keys($names);
25660 }
25661
25662
25663
25664
25665 public function setId($id)
25666 {
25667 $this->id = $id;
25668 }
25669
25670
25671
25672
25673 public function getId()
25674 {
25675 return $this->id;
25676 }
25677
25678
25679
25680
25681 public function setRepository(RepositoryInterface $repository)
25682 {
25683 if ($this->repository && $repository !== $this->repository) {
25684 throw new \LogicException('A package can only be added to one repository');
25685 }
25686 $this->repository = $repository;
25687 }
25688
25689
25690
25691
25692 public function getRepository()
25693 {
25694 return $this->repository;
25695 }
25696
25697
25698
25699
25700 public function getTransportOptions()
25701 {
25702 return $this->transportOptions;
25703 }
25704
25705
25706
25707
25708
25709
25710 public function setTransportOptions(array $options)
25711 {
25712 $this->transportOptions = $options;
25713 }
25714
25715
25716
25717
25718
25719
25720 public function isPlatform()
25721 {
25722 return $this->getRepository() instanceof PlatformRepository;
25723 }
25724
25725
25726
25727
25728
25729
25730 public function getUniqueName()
25731 {
25732 return $this->getName().'-'.$this->getVersion();
25733 }
25734
25735 public function equals(PackageInterface $package)
25736 {
25737 $self = $this;
25738 if ($this instanceof AliasPackage) {
25739 $self = $this->getAliasOf();
25740 }
25741 if ($package instanceof AliasPackage) {
25742 $package = $package->getAliasOf();
25743 }
25744
25745 return $package === $self;
25746 }
25747
25748
25749
25750
25751
25752
25753 public function __toString()
25754 {
25755 return $this->getUniqueName();
25756 }
25757
25758 public function getPrettyString()
25759 {
25760 return $this->getPrettyName().' '.$this->getPrettyVersion();
25761 }
25762
25763
25764
25765
25766 public function getFullPrettyVersion($truncate = true)
25767 {
25768 if (!$this->isDev() || !in_array($this->getSourceType(), array('hg', 'git'))) {
25769 return $this->getPrettyVersion();
25770 }
25771
25772
25773  if ($truncate && strlen($this->getSourceReference()) === 40) {
25774 return $this->getPrettyVersion() . ' ' . substr($this->getSourceReference(), 0, 7);
25775 }
25776
25777 return $this->getPrettyVersion() . ' ' . $this->getSourceReference();
25778 }
25779
25780 public function getStabilityPriority()
25781 {
25782 return self::$stabilities[$this->getStability()];
25783 }
25784
25785 public function __clone()
25786 {
25787 $this->repository = null;
25788 $this->id = -1;
25789 }
25790 }
25791 <?php
25792
25793
25794
25795
25796
25797
25798
25799
25800
25801
25802
25803 namespace Composer\Package;
25804
25805
25806
25807
25808
25809
25810 class CompletePackage extends Package implements CompletePackageInterface
25811 {
25812 protected $repositories;
25813 protected $license = array();
25814 protected $keywords;
25815 protected $authors;
25816 protected $description;
25817 protected $homepage;
25818 protected $scripts = array();
25819 protected $support = array();
25820 protected $abandoned = false;
25821
25822
25823
25824
25825 public function setScripts(array $scripts)
25826 {
25827 $this->scripts = $scripts;
25828 }
25829
25830
25831
25832
25833 public function getScripts()
25834 {
25835 return $this->scripts;
25836 }
25837
25838
25839
25840
25841
25842
25843 public function setRepositories($repositories)
25844 {
25845 $this->repositories = $repositories;
25846 }
25847
25848
25849
25850
25851 public function getRepositories()
25852 {
25853 return $this->repositories;
25854 }
25855
25856
25857
25858
25859
25860
25861 public function setLicense(array $license)
25862 {
25863 $this->license = $license;
25864 }
25865
25866
25867
25868
25869 public function getLicense()
25870 {
25871 return $this->license;
25872 }
25873
25874
25875
25876
25877
25878
25879 public function setKeywords(array $keywords)
25880 {
25881 $this->keywords = $keywords;
25882 }
25883
25884
25885
25886
25887 public function getKeywords()
25888 {
25889 return $this->keywords;
25890 }
25891
25892
25893
25894
25895
25896
25897 public function setAuthors(array $authors)
25898 {
25899 $this->authors = $authors;
25900 }
25901
25902
25903
25904
25905 public function getAuthors()
25906 {
25907 return $this->authors;
25908 }
25909
25910
25911
25912
25913
25914
25915 public function setDescription($description)
25916 {
25917 $this->description = $description;
25918 }
25919
25920
25921
25922
25923 public function getDescription()
25924 {
25925 return $this->description;
25926 }
25927
25928
25929
25930
25931
25932
25933 public function setHomepage($homepage)
25934 {
25935 $this->homepage = $homepage;
25936 }
25937
25938
25939
25940
25941 public function getHomepage()
25942 {
25943 return $this->homepage;
25944 }
25945
25946
25947
25948
25949
25950
25951 public function setSupport(array $support)
25952 {
25953 $this->support = $support;
25954 }
25955
25956
25957
25958
25959 public function getSupport()
25960 {
25961 return $this->support;
25962 }
25963
25964
25965
25966
25967 public function isAbandoned()
25968 {
25969 return (bool) $this->abandoned;
25970 }
25971
25972
25973
25974
25975 public function setAbandoned($abandoned)
25976 {
25977 $this->abandoned = $abandoned;
25978 }
25979
25980
25981
25982
25983
25984
25985 public function getReplacementPackage()
25986 {
25987 return is_string($this->abandoned) ? $this->abandoned : null;
25988 }
25989 }
25990 <?php
25991
25992
25993
25994
25995
25996
25997
25998
25999
26000
26001
26002 namespace Composer\Package;
26003
26004
26005
26006
26007
26008
26009 interface CompletePackageInterface extends PackageInterface
26010 {
26011
26012
26013
26014
26015
26016 public function getScripts();
26017
26018
26019
26020
26021
26022
26023
26024
26025 public function getRepositories();
26026
26027
26028
26029
26030
26031
26032 public function getLicense();
26033
26034
26035
26036
26037
26038
26039 public function getKeywords();
26040
26041
26042
26043
26044
26045
26046 public function getDescription();
26047
26048
26049
26050
26051
26052
26053 public function getHomepage();
26054
26055
26056
26057
26058
26059
26060
26061
26062 public function getAuthors();
26063
26064
26065
26066
26067
26068
26069 public function getSupport();
26070
26071
26072
26073
26074
26075
26076 public function isAbandoned();
26077
26078
26079
26080
26081
26082
26083 public function getReplacementPackage();
26084 }
26085 <?php
26086
26087
26088
26089
26090
26091
26092
26093
26094
26095
26096
26097 namespace Composer\Package\Dumper;
26098
26099 use Composer\Package\BasePackage;
26100 use Composer\Package\PackageInterface;
26101 use Composer\Package\CompletePackageInterface;
26102 use Composer\Package\RootPackageInterface;
26103
26104
26105
26106
26107
26108 class ArrayDumper
26109 {
26110 public function dump(PackageInterface $package)
26111 {
26112 $keys = array(
26113 'binaries' => 'bin',
26114 'type',
26115 'extra',
26116 'installationSource' => 'installation-source',
26117 'autoload',
26118 'devAutoload' => 'autoload-dev',
26119 'notificationUrl' => 'notification-url',
26120 'includePaths' => 'include-path',
26121 );
26122
26123 $data = array();
26124 $data['name'] = $package->getPrettyName();
26125 $data['version'] = $package->getPrettyVersion();
26126 $data['version_normalized'] = $package->getVersion();
26127
26128 if ($package->getTargetDir()) {
26129 $data['target-dir'] = $package->getTargetDir();
26130 }
26131
26132 if ($package->getSourceType()) {
26133 $data['source']['type'] = $package->getSourceType();
26134 $data['source']['url'] = $package->getSourceUrl();
26135 $data['source']['reference'] = $package->getSourceReference();
26136 if ($mirrors = $package->getSourceMirrors()) {
26137 $data['source']['mirrors'] = $mirrors;
26138 }
26139 }
26140
26141 if ($package->getDistType()) {
26142 $data['dist']['type'] = $package->getDistType();
26143 $data['dist']['url'] = $package->getDistUrl();
26144 $data['dist']['reference'] = $package->getDistReference();
26145 $data['dist']['shasum'] = $package->getDistSha1Checksum();
26146 if ($mirrors = $package->getDistMirrors()) {
26147 $data['dist']['mirrors'] = $mirrors;
26148 }
26149 }
26150
26151 if ($package->getArchiveExcludes()) {
26152 $data['archive']['exclude'] = $package->getArchiveExcludes();
26153 }
26154
26155 foreach (BasePackage::$supportedLinkTypes as $type => $opts) {
26156 if ($links = $package->{'get'.ucfirst($opts['method'])}()) {
26157 foreach ($links as $link) {
26158 $data[$type][$link->getTarget()] = $link->getPrettyConstraint();
26159 }
26160 ksort($data[$type]);
26161 }
26162 }
26163
26164 if ($packages = $package->getSuggests()) {
26165 ksort($packages);
26166 $data['suggest'] = $packages;
26167 }
26168
26169 if ($package->getReleaseDate()) {
26170 $data['time'] = $package->getReleaseDate()->format(DATE_RFC3339);
26171 }
26172
26173 $data = $this->dumpValues($package, $keys, $data);
26174
26175 if ($package instanceof CompletePackageInterface) {
26176 $keys = array(
26177 'scripts',
26178 'license',
26179 'authors',
26180 'description',
26181 'homepage',
26182 'keywords',
26183 'repositories',
26184 'support',
26185 );
26186
26187 $data = $this->dumpValues($package, $keys, $data);
26188
26189 if (isset($data['keywords']) && is_array($data['keywords'])) {
26190 sort($data['keywords']);
26191 }
26192
26193 if ($package->isAbandoned()) {
26194 $data['abandoned'] = $package->getReplacementPackage() ?: true;
26195 }
26196 }
26197
26198 if ($package instanceof RootPackageInterface) {
26199 $minimumStability = $package->getMinimumStability();
26200 if ($minimumStability) {
26201 $data['minimum-stability'] = $minimumStability;
26202 }
26203 }
26204
26205 if (count($package->getTransportOptions()) > 0) {
26206 $data['transport-options'] = $package->getTransportOptions();
26207 }
26208
26209 return $data;
26210 }
26211
26212 private function dumpValues(PackageInterface $package, array $keys, array $data)
26213 {
26214 foreach ($keys as $method => $key) {
26215 if (is_numeric($method)) {
26216 $method = $key;
26217 }
26218
26219 $getter = 'get'.ucfirst($method);
26220 $value = $package->$getter();
26221
26222 if (null !== $value && !(is_array($value) && 0 === count($value))) {
26223 $data[$key] = $value;
26224 }
26225 }
26226
26227 return $data;
26228 }
26229 }
26230 <?php
26231
26232
26233
26234
26235
26236
26237
26238
26239
26240
26241
26242 namespace Composer\Package;
26243
26244 use Composer\Semver\Constraint\ConstraintInterface;
26245
26246
26247
26248
26249
26250
26251 class Link
26252 {
26253
26254
26255
26256 protected $source;
26257
26258
26259
26260
26261 protected $target;
26262
26263
26264
26265
26266 protected $constraint;
26267
26268
26269
26270
26271 protected $description;
26272
26273
26274
26275
26276 protected $prettyConstraint;
26277
26278
26279
26280
26281
26282
26283
26284
26285
26286
26287 public function __construct($source, $target, ConstraintInterface $constraint = null, $description = 'relates to', $prettyConstraint = null)
26288 {
26289 $this->source = strtolower($source);
26290 $this->target = strtolower($target);
26291 $this->constraint = $constraint;
26292 $this->description = $description;
26293 $this->prettyConstraint = $prettyConstraint;
26294 }
26295
26296
26297
26298
26299 public function getDescription()
26300 {
26301 return $this->description;
26302 }
26303
26304
26305
26306
26307 public function getSource()
26308 {
26309 return $this->source;
26310 }
26311
26312
26313
26314
26315 public function getTarget()
26316 {
26317 return $this->target;
26318 }
26319
26320
26321
26322
26323 public function getConstraint()
26324 {
26325 return $this->constraint;
26326 }
26327
26328
26329
26330
26331
26332 public function getPrettyConstraint()
26333 {
26334 if (null === $this->prettyConstraint) {
26335 throw new \UnexpectedValueException(sprintf('Link %s has been misconfigured and had no prettyConstraint given.', $this));
26336 }
26337
26338 return $this->prettyConstraint;
26339 }
26340
26341
26342
26343
26344 public function __toString()
26345 {
26346 return $this->source.' '.$this->description.' '.$this->target.' ('.$this->constraint.')';
26347 }
26348
26349
26350
26351
26352
26353 public function getPrettyString(PackageInterface $sourcePackage)
26354 {
26355 return $sourcePackage->getPrettyString().' '.$this->description.' '.$this->target.' '.$this->constraint->getPrettyString().'';
26356 }
26357 }
26358 <?php
26359
26360
26361
26362
26363
26364
26365
26366
26367
26368
26369
26370 namespace Composer\Package\LinkConstraint;
26371
26372 use Composer\Semver\Constraint\EmptyConstraint as SemverEmptyConstraint;
26373
26374 trigger_error('The ' . __NAMESPACE__ . '\EmptyConstraint class is deprecated, use Composer\Semver\Constraint\EmptyConstraint instead.', E_USER_DEPRECATED);
26375
26376
26377
26378
26379 class EmptyConstraint extends SemverEmptyConstraint implements LinkConstraintInterface
26380 {
26381 }
26382 <?php
26383
26384
26385
26386
26387
26388
26389
26390
26391
26392
26393
26394 namespace Composer\Package\LinkConstraint;
26395
26396 use Composer\Semver\Constraint\ConstraintInterface;
26397
26398 trigger_error('The ' . __NAMESPACE__ . '\LinkConstraintInterface interface is deprecated, use Composer\Semver\Constraint\ConstraintInterface instead.', E_USER_DEPRECATED);
26399
26400
26401
26402
26403 interface LinkConstraintInterface extends ConstraintInterface
26404 {
26405 }
26406 <?php
26407
26408
26409
26410
26411
26412
26413
26414
26415
26416
26417
26418 namespace Composer\Package\LinkConstraint;
26419
26420 use Composer\Semver\Constraint\MultiConstraint as SemverMultiConstraint;
26421
26422 trigger_error('The ' . __NAMESPACE__ . '\MultiConstraint class is deprecated, use Composer\Semver\Constraint\MultiConstraint instead.', E_USER_DEPRECATED);
26423
26424
26425
26426
26427 class MultiConstraint extends SemverMultiConstraint implements LinkConstraintInterface
26428 {
26429 }
26430 <?php
26431
26432
26433
26434
26435
26436
26437
26438
26439
26440
26441
26442 namespace Composer\Package\LinkConstraint;
26443
26444 use Composer\Semver\Constraint\AbstractConstraint;
26445
26446 trigger_error('The ' . __NAMESPACE__ . '\SpecificConstraint abstract class is deprecated, there is no replacement for it.', E_USER_DEPRECATED);
26447
26448
26449
26450
26451 abstract class SpecificConstraint extends AbstractConstraint implements LinkConstraintInterface
26452 {
26453 }
26454 <?php
26455
26456
26457
26458
26459
26460
26461
26462
26463
26464
26465
26466 namespace Composer\Package\LinkConstraint;
26467
26468 use Composer\Semver\Constraint\Constraint;
26469
26470 trigger_error('The ' . __NAMESPACE__ . '\VersionConstraint class is deprecated, use Composer\Semver\Constraint\Constraint instead.', E_USER_DEPRECATED);
26471
26472
26473
26474
26475 class VersionConstraint extends Constraint implements LinkConstraintInterface
26476 {
26477 }
26478 <?php
26479
26480
26481
26482
26483
26484
26485
26486
26487
26488
26489
26490 namespace Composer\Package\Loader;
26491
26492 use Composer\Package;
26493 use Composer\Package\AliasPackage;
26494 use Composer\Package\Link;
26495 use Composer\Package\RootAliasPackage;
26496 use Composer\Package\RootPackageInterface;
26497 use Composer\Package\Version\VersionParser;
26498 use Composer\Semver\VersionParser as SemverVersionParser;
26499
26500
26501
26502
26503
26504 class ArrayLoader implements LoaderInterface
26505 {
26506 protected $versionParser;
26507 protected $loadOptions;
26508
26509 public function __construct(SemverVersionParser $parser = null, $loadOptions = false)
26510 {
26511 if (!$parser) {
26512 $parser = new VersionParser;
26513 }
26514 $this->versionParser = $parser;
26515 $this->loadOptions = $loadOptions;
26516 }
26517
26518 public function load(array $config, $class = 'Composer\Package\CompletePackage')
26519 {
26520 if (!isset($config['name'])) {
26521 throw new \UnexpectedValueException('Unknown package has no name defined ('.json_encode($config).').');
26522 }
26523 if (!isset($config['version'])) {
26524 throw new \UnexpectedValueException('Package '.$config['name'].' has no version defined.');
26525 }
26526
26527
26528  if (isset($config['version_normalized'])) {
26529 $version = $config['version_normalized'];
26530 } else {
26531 $version = $this->versionParser->normalize($config['version']);
26532 }
26533 $package = new $class($config['name'], $version, $config['version']);
26534 $package->setType(isset($config['type']) ? strtolower($config['type']) : 'library');
26535
26536 if (isset($config['target-dir'])) {
26537 $package->setTargetDir($config['target-dir']);
26538 }
26539
26540 if (isset($config['extra']) && is_array($config['extra'])) {
26541 $package->setExtra($config['extra']);
26542 }
26543
26544 if (isset($config['bin'])) {
26545 if (!is_array($config['bin'])) {
26546 throw new \UnexpectedValueException('Package '.$config['name'].'\'s bin key should be an array, '.gettype($config['bin']).' given.');
26547 }
26548 foreach ($config['bin'] as $key => $bin) {
26549 $config['bin'][$key] = ltrim($bin, '/');
26550 }
26551 $package->setBinaries($config['bin']);
26552 }
26553
26554 if (isset($config['installation-source'])) {
26555 $package->setInstallationSource($config['installation-source']);
26556 }
26557
26558 if (isset($config['source'])) {
26559 if (!isset($config['source']['type']) || !isset($config['source']['url']) || !isset($config['source']['reference'])) {
26560 throw new \UnexpectedValueException(sprintf(
26561 "Package %s's source key should be specified as {\"type\": ..., \"url\": ..., \"reference\": ...},\n%s given.",
26562 $config['name'],
26563 json_encode($config['source'])
26564 ));
26565 }
26566 $package->setSourceType($config['source']['type']);
26567 $package->setSourceUrl($config['source']['url']);
26568 $package->setSourceReference($config['source']['reference']);
26569 if (isset($config['source']['mirrors'])) {
26570 $package->setSourceMirrors($config['source']['mirrors']);
26571 }
26572 }
26573
26574 if (isset($config['dist'])) {
26575 if (!isset($config['dist']['type'])
26576 || !isset($config['dist']['url'])) {
26577 throw new \UnexpectedValueException(sprintf(
26578 "Package %s's dist key should be specified as ".
26579 "{\"type\": ..., \"url\": ..., \"reference\": ..., \"shasum\": ...},\n%s given.",
26580 $config['name'],
26581 json_encode($config['dist'])
26582 ));
26583 }
26584 $package->setDistType($config['dist']['type']);
26585 $package->setDistUrl($config['dist']['url']);
26586 $package->setDistReference(isset($config['dist']['reference']) ? $config['dist']['reference'] : null);
26587 $package->setDistSha1Checksum(isset($config['dist']['shasum']) ? $config['dist']['shasum'] : null);
26588 if (isset($config['dist']['mirrors'])) {
26589 $package->setDistMirrors($config['dist']['mirrors']);
26590 }
26591 }
26592
26593 foreach (Package\BasePackage::$supportedLinkTypes as $type => $opts) {
26594 if (isset($config[$type])) {
26595 $method = 'set'.ucfirst($opts['method']);
26596 $package->{$method}(
26597 $this->parseLinks(
26598 $package->getName(),
26599 $package->getPrettyVersion(),
26600 $opts['description'],
26601 $config[$type]
26602 )
26603 );
26604 }
26605 }
26606
26607 if (isset($config['suggest']) && is_array($config['suggest'])) {
26608 foreach ($config['suggest'] as $target => $reason) {
26609 if ('self.version' === trim($reason)) {
26610 $config['suggest'][$target] = $package->getPrettyVersion();
26611 }
26612 }
26613 $package->setSuggests($config['suggest']);
26614 }
26615
26616 if (isset($config['autoload'])) {
26617 $package->setAutoload($config['autoload']);
26618 }
26619
26620 if (isset($config['autoload-dev'])) {
26621 $package->setDevAutoload($config['autoload-dev']);
26622 }
26623
26624 if (isset($config['include-path'])) {
26625 $package->setIncludePaths($config['include-path']);
26626 }
26627
26628 if (!empty($config['time'])) {
26629 $time = preg_match('/^\d++$/D', $config['time']) ? '@'.$config['time'] : $config['time'];
26630
26631 try {
26632 $date = new \DateTime($time, new \DateTimeZone('UTC'));
26633 $package->setReleaseDate($date);
26634 } catch (\Exception $e) {
26635 }
26636 }
26637
26638 if (!empty($config['notification-url'])) {
26639 $package->setNotificationUrl($config['notification-url']);
26640 }
26641
26642 if (!empty($config['archive']['exclude'])) {
26643 $package->setArchiveExcludes($config['archive']['exclude']);
26644 }
26645
26646 if ($package instanceof Package\CompletePackageInterface) {
26647 if (isset($config['scripts']) && is_array($config['scripts'])) {
26648 foreach ($config['scripts'] as $event => $listeners) {
26649 $config['scripts'][$event] = (array) $listeners;
26650 }
26651 if (isset($config['scripts']['composer'])) {
26652 trigger_error('The `composer` script name is reserved for internal use, please avoid defining it', E_USER_DEPRECATED);
26653 }
26654 $package->setScripts($config['scripts']);
26655 }
26656
26657 if (!empty($config['description']) && is_string($config['description'])) {
26658 $package->setDescription($config['description']);
26659 }
26660
26661 if (!empty($config['homepage']) && is_string($config['homepage'])) {
26662 $package->setHomepage($config['homepage']);
26663 }
26664
26665 if (!empty($config['keywords']) && is_array($config['keywords'])) {
26666 $package->setKeywords($config['keywords']);
26667 }
26668
26669 if (!empty($config['license'])) {
26670 $package->setLicense(is_array($config['license']) ? $config['license'] : array($config['license']));
26671 }
26672
26673 if (!empty($config['authors']) && is_array($config['authors'])) {
26674 $package->setAuthors($config['authors']);
26675 }
26676
26677 if (isset($config['support'])) {
26678 $package->setSupport($config['support']);
26679 }
26680
26681 if (isset($config['abandoned'])) {
26682 $package->setAbandoned($config['abandoned']);
26683 }
26684 }
26685
26686 if ($aliasNormalized = $this->getBranchAlias($config)) {
26687 if ($package instanceof RootPackageInterface) {
26688 $package = new RootAliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
26689 } else {
26690 $package = new AliasPackage($package, $aliasNormalized, preg_replace('{(\.9{7})+}', '.x', $aliasNormalized));
26691 }
26692 }
26693
26694 if ($this->loadOptions && isset($config['transport-options'])) {
26695 $package->setTransportOptions($config['transport-options']);
26696 }
26697
26698 return $package;
26699 }
26700
26701
26702
26703
26704
26705
26706
26707
26708 public function parseLinks($source, $sourceVersion, $description, $links)
26709 {
26710 $res = array();
26711 foreach ($links as $target => $constraint) {
26712 if (!is_string($constraint)) {
26713 throw new \UnexpectedValueException('Link constraint in '.$source.' '.$description.' > '.$target.' should be a string, got '.gettype($constraint) . ' (' . var_export($constraint, true) . ')');
26714 }
26715 if ('self.version' === $constraint) {
26716 $parsedConstraint = $this->versionParser->parseConstraints($sourceVersion);
26717 } else {
26718 $parsedConstraint = $this->versionParser->parseConstraints($constraint);
26719 }
26720
26721 $res[strtolower($target)] = new Link($source, $target, $parsedConstraint, $description, $constraint);
26722 }
26723
26724 return $res;
26725 }
26726
26727
26728
26729
26730
26731
26732
26733 public function getBranchAlias(array $config)
26734 {
26735 if (('dev-' !== substr($config['version'], 0, 4) && '-dev' !== substr($config['version'], -4))
26736 || !isset($config['extra']['branch-alias'])
26737 || !is_array($config['extra']['branch-alias'])
26738 ) {
26739 return;
26740 }
26741
26742 foreach ($config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
26743
26744  if ('-dev' !== substr($targetBranch, -4)) {
26745 continue;
26746 }
26747
26748
26749  $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
26750 if ('-dev' !== substr($validatedTargetBranch, -4)) {
26751 continue;
26752 }
26753
26754
26755  if (strtolower($config['version']) !== strtolower($sourceBranch)) {
26756 continue;
26757 }
26758
26759
26760  if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
26761 && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
26762 && (stripos($targetPrefix, $sourcePrefix) !== 0)
26763 ) {
26764 continue;
26765 }
26766
26767 return $validatedTargetBranch;
26768 }
26769 }
26770 }
26771 <?php
26772
26773
26774
26775
26776
26777
26778
26779
26780
26781
26782
26783 namespace Composer\Package\Loader;
26784
26785
26786
26787
26788 class InvalidPackageException extends \Exception
26789 {
26790 private $errors;
26791 private $warnings;
26792 private $data;
26793
26794 public function __construct(array $errors, array $warnings, array $data)
26795 {
26796 $this->errors = $errors;
26797 $this->warnings = $warnings;
26798 $this->data = $data;
26799 parent::__construct("Invalid package information: \n".implode("\n", array_merge($errors, $warnings)));
26800 }
26801
26802 public function getData()
26803 {
26804 return $this->data;
26805 }
26806
26807 public function getErrors()
26808 {
26809 return $this->errors;
26810 }
26811
26812 public function getWarnings()
26813 {
26814 return $this->warnings;
26815 }
26816 }
26817 <?php
26818
26819
26820
26821
26822
26823
26824
26825
26826
26827
26828
26829 namespace Composer\Package\Loader;
26830
26831 use Composer\Json\JsonFile;
26832
26833
26834
26835
26836 class JsonLoader
26837 {
26838 private $loader;
26839
26840 public function __construct(LoaderInterface $loader)
26841 {
26842 $this->loader = $loader;
26843 }
26844
26845
26846
26847
26848
26849 public function load($json)
26850 {
26851 if ($json instanceof JsonFile) {
26852 $config = $json->read();
26853 } elseif (file_exists($json)) {
26854 $config = JsonFile::parseJson(file_get_contents($json), $json);
26855 } elseif (is_string($json)) {
26856 $config = JsonFile::parseJson($json);
26857 }
26858
26859 return $this->loader->load($config);
26860 }
26861 }
26862 <?php
26863
26864
26865
26866
26867
26868
26869
26870
26871
26872
26873
26874 namespace Composer\Package\Loader;
26875
26876
26877
26878
26879
26880
26881 interface LoaderInterface
26882 {
26883
26884
26885
26886
26887
26888
26889
26890 public function load(array $package, $class = 'Composer\Package\CompletePackage');
26891 }
26892 <?php
26893
26894
26895
26896
26897
26898
26899
26900
26901
26902
26903
26904 namespace Composer\Package\Loader;
26905
26906 use Composer\Package\BasePackage;
26907 use Composer\Package\AliasPackage;
26908 use Composer\Config;
26909 use Composer\Package\RootPackageInterface;
26910 use Composer\Repository\RepositoryFactory;
26911 use Composer\Package\Version\VersionGuesser;
26912 use Composer\Package\Version\VersionParser;
26913 use Composer\Repository\RepositoryManager;
26914 use Composer\Util\ProcessExecutor;
26915
26916
26917
26918
26919
26920
26921
26922
26923 class RootPackageLoader extends ArrayLoader
26924 {
26925
26926
26927
26928 private $manager;
26929
26930
26931
26932
26933 private $config;
26934
26935
26936
26937
26938 private $versionGuesser;
26939
26940 public function __construct(RepositoryManager $manager, Config $config, VersionParser $parser = null, VersionGuesser $versionGuesser = null)
26941 {
26942 parent::__construct($parser);
26943
26944 $this->manager = $manager;
26945 $this->config = $config;
26946 $this->versionGuesser = $versionGuesser ?: new VersionGuesser($config, new ProcessExecutor(), $this->versionParser);
26947 }
26948
26949
26950
26951
26952
26953
26954
26955 public function load(array $config, $class = 'Composer\Package\RootPackage', $cwd = null)
26956 {
26957 if (!isset($config['name'])) {
26958 $config['name'] = '__root__';
26959 }
26960 $autoVersioned = false;
26961 if (!isset($config['version'])) {
26962
26963  if (getenv('COMPOSER_ROOT_VERSION')) {
26964 $version = getenv('COMPOSER_ROOT_VERSION');
26965 $commit = null;
26966 } else {
26967 $versionData = $this->versionGuesser->guessVersion($config, $cwd ?: getcwd());
26968 $version = $versionData['version'];
26969 $commit = $versionData['commit'];
26970 }
26971
26972 if (!$version) {
26973 $version = '1.0.0';
26974 $autoVersioned = true;
26975 }
26976
26977 $config['version'] = $version;
26978 if ($commit) {
26979 $config['source'] = array(
26980 'type' => '',
26981 'url' => '',
26982 'reference' => $commit,
26983 );
26984 $config['dist'] = array(
26985 'type' => '',
26986 'url' => '',
26987 'reference' => $commit,
26988 );
26989 }
26990 }
26991
26992 $realPackage = $package = parent::load($config, $class);
26993 if ($realPackage instanceof AliasPackage) {
26994 $realPackage = $package->getAliasOf();
26995 }
26996
26997 if ($autoVersioned) {
26998 $realPackage->replaceVersion($realPackage->getVersion(), 'No version set (parsed as 1.0.0)');
26999 }
27000
27001 if (isset($config['minimum-stability'])) {
27002 $realPackage->setMinimumStability(VersionParser::normalizeStability($config['minimum-stability']));
27003 }
27004
27005 $aliases = array();
27006 $stabilityFlags = array();
27007 $references = array();
27008 foreach (array('require', 'require-dev') as $linkType) {
27009 if (isset($config[$linkType])) {
27010 $linkInfo = BasePackage::$supportedLinkTypes[$linkType];
27011 $method = 'get'.ucfirst($linkInfo['method']);
27012 $links = array();
27013 foreach ($realPackage->$method() as $link) {
27014 $links[$link->getTarget()] = $link->getConstraint()->getPrettyString();
27015 }
27016 $aliases = $this->extractAliases($links, $aliases);
27017 $stabilityFlags = $this->extractStabilityFlags($links, $stabilityFlags, $realPackage->getMinimumStability());
27018 $references = $this->extractReferences($links, $references);
27019 }
27020 }
27021
27022 if (isset($links[$config['name']])) {
27023 throw new \InvalidArgumentException(sprintf('Root package \'%s\' cannot require itself in its composer.json' . PHP_EOL .
27024 'Did you accidentally name your root package after an external package?', $config['name']));
27025 }
27026
27027 $realPackage->setAliases($aliases);
27028 $realPackage->setStabilityFlags($stabilityFlags);
27029 $realPackage->setReferences($references);
27030
27031 if (isset($config['prefer-stable'])) {
27032 $realPackage->setPreferStable((bool) $config['prefer-stable']);
27033 }
27034
27035 if (isset($config['config'])) {
27036 $realPackage->setConfig($config['config']);
27037 }
27038
27039 $repos = RepositoryFactory::defaultRepos(null, $this->config, $this->manager);
27040 foreach ($repos as $repo) {
27041 $this->manager->addRepository($repo);
27042 }
27043 $realPackage->setRepositories($this->config->getRepositories());
27044
27045 return $package;
27046 }
27047
27048 private function extractAliases(array $requires, array $aliases)
27049 {
27050 foreach ($requires as $reqName => $reqVersion) {
27051 if (preg_match('{^([^,\s#]+)(?:#[^ ]+)? +as +([^,\s]+)$}', $reqVersion, $match)) {
27052 $aliases[] = array(
27053 'package' => strtolower($reqName),
27054 'version' => $this->versionParser->normalize($match[1], $reqVersion),
27055 'alias' => $match[2],
27056 'alias_normalized' => $this->versionParser->normalize($match[2], $reqVersion),
27057 );
27058 }
27059 }
27060
27061 return $aliases;
27062 }
27063
27064 private function extractStabilityFlags(array $requires, array $stabilityFlags, $minimumStability)
27065 {
27066 $stabilities = BasePackage::$stabilities;
27067 $minimumStability = $stabilities[$minimumStability];
27068 foreach ($requires as $reqName => $reqVersion) {
27069 $constraints = array();
27070
27071
27072  $orSplit = preg_split('{\s*\|\|?\s*}', trim($reqVersion));
27073 foreach ($orSplit as $orConstraint) {
27074 $andSplit = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $orConstraint);
27075 foreach ($andSplit as $andConstraint) {
27076 $constraints[] = $andConstraint;
27077 }
27078 }
27079
27080
27081  $match = false;
27082 foreach ($constraints as $constraint) {
27083 if (preg_match('{^[^@]*?@('.implode('|', array_keys($stabilities)).')$}i', $constraint, $match)) {
27084 $name = strtolower($reqName);
27085 $stability = $stabilities[VersionParser::normalizeStability($match[1])];
27086
27087 if (isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) {
27088 continue;
27089 }
27090 $stabilityFlags[$name] = $stability;
27091 $match = true;
27092 }
27093 }
27094
27095 if ($match) {
27096 continue;
27097 }
27098
27099 foreach ($constraints as $constraint) {
27100
27101  
27102  $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $constraint);
27103 if (preg_match('{^[^,\s@]+$}', $reqVersion) && 'stable' !== ($stabilityName = VersionParser::parseStability($reqVersion))) {
27104 $name = strtolower($reqName);
27105 $stability = $stabilities[$stabilityName];
27106 if ((isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $stability) || ($minimumStability > $stability)) {
27107 continue;
27108 }
27109 $stabilityFlags[$name] = $stability;
27110 }
27111 }
27112 }
27113
27114 return $stabilityFlags;
27115 }
27116
27117 private function extractReferences(array $requires, array $references)
27118 {
27119 foreach ($requires as $reqName => $reqVersion) {
27120 $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $reqVersion);
27121 if (preg_match('{^[^,\s@]+?#([a-f0-9]+)$}', $reqVersion, $match) && 'dev' === ($stabilityName = VersionParser::parseStability($reqVersion))) {
27122 $name = strtolower($reqName);
27123 $references[$name] = $match[1];
27124 }
27125 }
27126
27127 return $references;
27128 }
27129 }
27130 <?php
27131
27132
27133
27134
27135
27136
27137
27138
27139
27140
27141
27142 namespace Composer\Package\Loader;
27143
27144 use Composer\Package;
27145 use Composer\Package\BasePackage;
27146 use Composer\Semver\Constraint\Constraint;
27147 use Composer\Package\Version\VersionParser;
27148 use Composer\Repository\PlatformRepository;
27149
27150
27151
27152
27153 class ValidatingArrayLoader implements LoaderInterface
27154 {
27155 const CHECK_ALL = 3;
27156 const CHECK_UNBOUND_CONSTRAINTS = 1;
27157 const CHECK_STRICT_CONSTRAINTS = 2;
27158
27159 private $loader;
27160 private $versionParser;
27161 private $errors;
27162 private $warnings;
27163 private $config;
27164 private $strictName;
27165 private $flags;
27166
27167 public function __construct(LoaderInterface $loader, $strictName = true, VersionParser $parser = null, $flags = 0)
27168 {
27169 $this->loader = $loader;
27170 $this->versionParser = $parser ?: new VersionParser();
27171 $this->strictName = $strictName;
27172 $this->flags = $flags;
27173 }
27174
27175 public function load(array $config, $class = 'Composer\Package\CompletePackage')
27176 {
27177 $this->errors = array();
27178 $this->warnings = array();
27179 $this->config = $config;
27180
27181 if ($this->strictName) {
27182 $this->validateRegex('name', '[A-Za-z0-9][A-Za-z0-9_.-]*/[A-Za-z0-9][A-Za-z0-9_.-]*', true);
27183 } else {
27184 $this->validateString('name', true);
27185 }
27186
27187 if (!empty($this->config['version'])) {
27188 try {
27189 $this->versionParser->normalize($this->config['version']);
27190 } catch (\Exception $e) {
27191 $this->errors[] = 'version : invalid value ('.$this->config['version'].'): '.$e->getMessage();
27192 unset($this->config['version']);
27193 }
27194 }
27195
27196 if (!empty($this->config['config']['platform'])) {
27197 foreach ((array) $this->config['config']['platform'] as $key => $platform) {
27198 try {
27199 $this->versionParser->normalize($platform);
27200 } catch (\Exception $e) {
27201 $this->errors[] = 'config.platform.' . $key . ' : invalid value ('.$platform.'): '.$e->getMessage();
27202 }
27203 }
27204 }
27205
27206 $this->validateRegex('type', '[A-Za-z0-9-]+');
27207 $this->validateString('target-dir');
27208 $this->validateArray('extra');
27209 $this->validateFlatArray('bin');
27210 $this->validateArray('scripts'); 
27211  $this->validateString('description');
27212 $this->validateUrl('homepage');
27213 $this->validateFlatArray('keywords', '[\p{N}\p{L} ._-]+');
27214
27215 if (isset($this->config['license'])) {
27216 if (is_string($this->config['license'])) {
27217 $this->validateRegex('license', '[A-Za-z0-9+. ()-]+');
27218 } else {
27219 $this->validateFlatArray('license', '[A-Za-z0-9+. ()-]+');
27220 }
27221 }
27222
27223 $this->validateString('time');
27224 if (!empty($this->config['time'])) {
27225 try {
27226 $date = new \DateTime($this->config['time'], new \DateTimeZone('UTC'));
27227 } catch (\Exception $e) {
27228 $this->errors[] = 'time : invalid value ('.$this->config['time'].'): '.$e->getMessage();
27229 unset($this->config['time']);
27230 }
27231 }
27232
27233 if ($this->validateArray('authors') && !empty($this->config['authors'])) {
27234 foreach ($this->config['authors'] as $key => $author) {
27235 if (!is_array($author)) {
27236 $this->errors[] = 'authors.'.$key.' : should be an array, '.gettype($author).' given';
27237 unset($this->config['authors'][$key]);
27238 continue;
27239 }
27240 foreach (array('homepage', 'email', 'name', 'role') as $authorData) {
27241 if (isset($author[$authorData]) && !is_string($author[$authorData])) {
27242 $this->errors[] = 'authors.'.$key.'.'.$authorData.' : invalid value, must be a string';
27243 unset($this->config['authors'][$key][$authorData]);
27244 }
27245 }
27246 if (isset($author['homepage']) && !$this->filterUrl($author['homepage'])) {
27247 $this->warnings[] = 'authors.'.$key.'.homepage : invalid value ('.$author['homepage'].'), must be an http/https URL';
27248 unset($this->config['authors'][$key]['homepage']);
27249 }
27250 if (isset($author['email']) && !filter_var($author['email'], FILTER_VALIDATE_EMAIL)) {
27251 $this->warnings[] = 'authors.'.$key.'.email : invalid value ('.$author['email'].'), must be a valid email address';
27252 unset($this->config['authors'][$key]['email']);
27253 }
27254 if (empty($this->config['authors'][$key])) {
27255 unset($this->config['authors'][$key]);
27256 }
27257 }
27258 if (empty($this->config['authors'])) {
27259 unset($this->config['authors']);
27260 }
27261 }
27262
27263 if ($this->validateArray('support') && !empty($this->config['support'])) {
27264 foreach (array('issues', 'forum', 'wiki', 'source', 'email', 'irc', 'docs', 'rss') as $key) {
27265 if (isset($this->config['support'][$key]) && !is_string($this->config['support'][$key])) {
27266 $this->errors[] = 'support.'.$key.' : invalid value, must be a string';
27267 unset($this->config['support'][$key]);
27268 }
27269 }
27270
27271 if (isset($this->config['support']['email']) && !filter_var($this->config['support']['email'], FILTER_VALIDATE_EMAIL)) {
27272 $this->warnings[] = 'support.email : invalid value ('.$this->config['support']['email'].'), must be a valid email address';
27273 unset($this->config['support']['email']);
27274 }
27275
27276 if (isset($this->config['support']['irc']) && !$this->filterUrl($this->config['support']['irc'], array('irc'))) {
27277 $this->warnings[] = 'support.irc : invalid value ('.$this->config['support']['irc'].'), must be a irc://<server>/<channel> URL';
27278 unset($this->config['support']['irc']);
27279 }
27280
27281 foreach (array('issues', 'forum', 'wiki', 'source', 'docs') as $key) {
27282 if (isset($this->config['support'][$key]) && !$this->filterUrl($this->config['support'][$key])) {
27283 $this->warnings[] = 'support.'.$key.' : invalid value ('.$this->config['support'][$key].'), must be an http/https URL';
27284 unset($this->config['support'][$key]);
27285 }
27286 }
27287 if (empty($this->config['support'])) {
27288 unset($this->config['support']);
27289 }
27290 }
27291
27292 $unboundConstraint = new Constraint('=', $this->versionParser->normalize('dev-master'));
27293 $stableConstraint = new Constraint('=', '1.0.0');
27294
27295 foreach (array_keys(BasePackage::$supportedLinkTypes) as $linkType) {
27296 if ($this->validateArray($linkType) && isset($this->config[$linkType])) {
27297 foreach ($this->config[$linkType] as $package => $constraint) {
27298 if (!preg_match('{^[A-Za-z0-9_./-]+$}', $package)) {
27299 $this->warnings[] = $linkType.'.'.$package.' : invalid key, package names must be strings containing only [A-Za-z0-9_./-]';
27300 }
27301 if (!is_string($constraint)) {
27302 $this->errors[] = $linkType.'.'.$package.' : invalid value, must be a string containing a version constraint';
27303 unset($this->config[$linkType][$package]);
27304 } elseif ('self.version' !== $constraint) {
27305 try {
27306 $linkConstraint = $this->versionParser->parseConstraints($constraint);
27307 } catch (\Exception $e) {
27308 $this->errors[] = $linkType.'.'.$package.' : invalid version constraint ('.$e->getMessage().')';
27309 unset($this->config[$linkType][$package]);
27310 continue;
27311 }
27312
27313
27314  if (
27315 ($this->flags & self::CHECK_UNBOUND_CONSTRAINTS)
27316 && 'require' === $linkType
27317 && $linkConstraint->matches($unboundConstraint)
27318 && !preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $package)
27319 ) {
27320 $this->warnings[] = $linkType.'.'.$package.' : unbound version constraints ('.$constraint.') should be avoided';
27321 } elseif (
27322
27323  ($this->flags & self::CHECK_STRICT_CONSTRAINTS)
27324 && 'require' === $linkType
27325 && substr($linkConstraint, 0, 1) === '='
27326 && $stableConstraint->versionCompare($stableConstraint, $linkConstraint, '<=')
27327 ) {
27328 $this->warnings[] = $linkType.'.'.$package.' : exact version constraints ('.$constraint.') should be avoided if the package follows semantic versioning';
27329 }
27330 }
27331 }
27332 }
27333 }
27334
27335 if ($this->validateArray('suggest') && !empty($this->config['suggest'])) {
27336 foreach ($this->config['suggest'] as $package => $description) {
27337 if (!is_string($description)) {
27338 $this->errors[] = 'suggest.'.$package.' : invalid value, must be a string describing why the package is suggested';
27339 unset($this->config['suggest'][$package]);
27340 }
27341 }
27342 }
27343
27344 if ($this->validateString('minimum-stability') && !empty($this->config['minimum-stability'])) {
27345 if (!isset(BasePackage::$stabilities[$this->config['minimum-stability']])) {
27346 $this->errors[] = 'minimum-stability : invalid value ('.$this->config['minimum-stability'].'), must be one of '.implode(', ', array_keys(BasePackage::$stabilities));
27347 unset($this->config['minimum-stability']);
27348 }
27349 }
27350
27351 if ($this->validateArray('autoload') && !empty($this->config['autoload'])) {
27352 $types = array('psr-0', 'psr-4', 'classmap', 'files', 'exclude-from-classmap');
27353 foreach ($this->config['autoload'] as $type => $typeConfig) {
27354 if (!in_array($type, $types)) {
27355 $this->errors[] = 'autoload : invalid value ('.$type.'), must be one of '.implode(', ', $types);
27356 unset($this->config['autoload'][$type]);
27357 }
27358 if ($type === 'psr-4') {
27359 foreach ($typeConfig as $namespace => $dirs) {
27360 if ($namespace !== '' && '\\' !== substr($namespace, -1)) {
27361 $this->errors[] = 'autoload.psr-4 : invalid value ('.$namespace.'), namespaces must end with a namespace separator, should be '.$namespace.'\\\\';
27362 }
27363 }
27364 }
27365 }
27366 }
27367
27368 if (!empty($this->config['autoload']['psr-4']) && !empty($this->config['target-dir'])) {
27369 $this->errors[] = 'target-dir : this can not be used together with the autoload.psr-4 setting, remove target-dir to upgrade to psr-4';
27370
27371  
27372  unset($this->config['autoload']['psr-4']);
27373 }
27374
27375
27376  
27377
27378
27379  
27380
27381 $this->validateFlatArray('include-path');
27382 $this->validateArray('transport-options');
27383
27384
27385  if (isset($this->config['extra']['branch-alias'])) {
27386 if (!is_array($this->config['extra']['branch-alias'])) {
27387 $this->errors[] = 'extra.branch-alias : must be an array of versions => aliases';
27388 } else {
27389 foreach ($this->config['extra']['branch-alias'] as $sourceBranch => $targetBranch) {
27390
27391  if ('-dev' !== substr($targetBranch, -4)) {
27392 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must end in -dev';
27393 unset($this->config['extra']['branch-alias'][$sourceBranch]);
27394
27395 continue;
27396 }
27397
27398
27399  $validatedTargetBranch = $this->versionParser->normalizeBranch(substr($targetBranch, 0, -4));
27400 if ('-dev' !== substr($validatedTargetBranch, -4)) {
27401 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') must be a parseable number like 2.0-dev';
27402 unset($this->config['extra']['branch-alias'][$sourceBranch]);
27403
27404 continue;
27405 }
27406
27407
27408  if (($sourcePrefix = $this->versionParser->parseNumericAliasPrefix($sourceBranch))
27409 && ($targetPrefix = $this->versionParser->parseNumericAliasPrefix($targetBranch))
27410 && (stripos($targetPrefix, $sourcePrefix) !== 0)
27411 ) {
27412 $this->warnings[] = 'extra.branch-alias.'.$sourceBranch.' : the target branch ('.$targetBranch.') is not a valid numeric alias for this version';
27413 unset($this->config['extra']['branch-alias'][$sourceBranch]);
27414 }
27415 }
27416 }
27417 }
27418
27419 if ($this->errors) {
27420 throw new InvalidPackageException($this->errors, $this->warnings, $config);
27421 }
27422
27423 $package = $this->loader->load($this->config, $class);
27424 $this->config = null;
27425
27426 return $package;
27427 }
27428
27429 public function getWarnings()
27430 {
27431 return $this->warnings;
27432 }
27433
27434 public function getErrors()
27435 {
27436 return $this->errors;
27437 }
27438
27439 private function validateRegex($property, $regex, $mandatory = false)
27440 {
27441 if (!$this->validateString($property, $mandatory)) {
27442 return false;
27443 }
27444
27445 if (!preg_match('{^'.$regex.'$}u', $this->config[$property])) {
27446 $message = $property.' : invalid value ('.$this->config[$property].'), must match '.$regex;
27447 if ($mandatory) {
27448 $this->errors[] = $message;
27449 } else {
27450 $this->warnings[] = $message;
27451 }
27452 unset($this->config[$property]);
27453
27454 return false;
27455 }
27456
27457 return true;
27458 }
27459
27460 private function validateString($property, $mandatory = false)
27461 {
27462 if (isset($this->config[$property]) && !is_string($this->config[$property])) {
27463 $this->errors[] = $property.' : should be a string, '.gettype($this->config[$property]).' given';
27464 unset($this->config[$property]);
27465
27466 return false;
27467 }
27468
27469 if (!isset($this->config[$property]) || trim($this->config[$property]) === '') {
27470 if ($mandatory) {
27471 $this->errors[] = $property.' : must be present';
27472 }
27473 unset($this->config[$property]);
27474
27475 return false;
27476 }
27477
27478 return true;
27479 }
27480
27481 private function validateArray($property, $mandatory = false)
27482 {
27483 if (isset($this->config[$property]) && !is_array($this->config[$property])) {
27484 $this->errors[] = $property.' : should be an array, '.gettype($this->config[$property]).' given';
27485 unset($this->config[$property]);
27486
27487 return false;
27488 }
27489
27490 if (!isset($this->config[$property]) || !count($this->config[$property])) {
27491 if ($mandatory) {
27492 $this->errors[] = $property.' : must be present and contain at least one element';
27493 }
27494 unset($this->config[$property]);
27495
27496 return false;
27497 }
27498
27499 return true;
27500 }
27501
27502 private function validateFlatArray($property, $regex = null, $mandatory = false)
27503 {
27504 if (!$this->validateArray($property, $mandatory)) {
27505 return false;
27506 }
27507
27508 $pass = true;
27509 foreach ($this->config[$property] as $key => $value) {
27510 if (!is_string($value) && !is_numeric($value)) {
27511 $this->errors[] = $property.'.'.$key.' : must be a string or int, '.gettype($value).' given';
27512 unset($this->config[$property][$key]);
27513 $pass = false;
27514
27515 continue;
27516 }
27517
27518 if ($regex && !preg_match('{^'.$regex.'$}u', $value)) {
27519 $this->warnings[] = $property.'.'.$key.' : invalid value ('.$value.'), must match '.$regex;
27520 unset($this->config[$property][$key]);
27521 $pass = false;
27522 }
27523 }
27524
27525 return $pass;
27526 }
27527
27528 private function validateUrl($property, $mandatory = false)
27529 {
27530 if (!$this->validateString($property, $mandatory)) {
27531 return false;
27532 }
27533
27534 if (!$this->filterUrl($this->config[$property])) {
27535 $this->warnings[] = $property.' : invalid value ('.$this->config[$property].'), must be an http/https URL';
27536 unset($this->config[$property]);
27537
27538 return false;
27539 }
27540
27541 return true;
27542 }
27543
27544 private function filterUrl($value, array $schemes = array('http', 'https'))
27545 {
27546 if ($value === '') {
27547 return true;
27548 }
27549
27550 $bits = parse_url($value);
27551 if (empty($bits['scheme']) || empty($bits['host'])) {
27552 return false;
27553 }
27554
27555 if (!in_array($bits['scheme'], $schemes, true)) {
27556 return false;
27557 }
27558
27559 return true;
27560 }
27561 }
27562 <?php
27563
27564
27565
27566
27567
27568
27569
27570
27571
27572
27573
27574 namespace Composer\Package;
27575
27576 use Composer\Json\JsonFile;
27577 use Composer\Installer\InstallationManager;
27578 use Composer\Repository\RepositoryManager;
27579 use Composer\Util\ProcessExecutor;
27580 use Composer\Repository\ArrayRepository;
27581 use Composer\Package\Dumper\ArrayDumper;
27582 use Composer\Package\Loader\ArrayLoader;
27583 use Composer\Util\Git as GitUtil;
27584 use Composer\IO\IOInterface;
27585 use Seld\JsonLint\ParsingException;
27586
27587
27588
27589
27590
27591
27592
27593 class Locker
27594 {
27595 private $lockFile;
27596 private $repositoryManager;
27597 private $installationManager;
27598 private $hash;
27599 private $contentHash;
27600 private $loader;
27601 private $dumper;
27602 private $process;
27603 private $lockDataCache;
27604
27605
27606
27607
27608
27609
27610
27611
27612
27613
27614 public function __construct(IOInterface $io, JsonFile $lockFile, RepositoryManager $repositoryManager, InstallationManager $installationManager, $composerFileContents)
27615 {
27616 $this->lockFile = $lockFile;
27617 $this->repositoryManager = $repositoryManager;
27618 $this->installationManager = $installationManager;
27619 $this->hash = md5($composerFileContents);
27620 $this->contentHash = self::getContentHash($composerFileContents);
27621 $this->loader = new ArrayLoader(null, true);
27622 $this->dumper = new ArrayDumper();
27623 $this->process = new ProcessExecutor($io);
27624 }
27625
27626
27627
27628
27629
27630
27631
27632
27633 public static function getContentHash($composerFileContents)
27634 {
27635 $content = json_decode($composerFileContents, true);
27636
27637 $relevantKeys = array(
27638 'name',
27639 'version',
27640 'require',
27641 'require-dev',
27642 'conflict',
27643 'replace',
27644 'provide',
27645 'minimum-stability',
27646 'prefer-stable',
27647 'repositories',
27648 'extra',
27649 );
27650
27651 $relevantContent = array();
27652
27653 foreach (array_intersect($relevantKeys, array_keys($content)) as $key) {
27654 $relevantContent[$key] = $content[$key];
27655 }
27656 if (isset($content['config']['platform'])) {
27657 $relevantContent['config']['platform'] = $content['config']['platform'];
27658 }
27659
27660 ksort($relevantContent);
27661
27662 return md5(json_encode($relevantContent));
27663 }
27664
27665
27666
27667
27668
27669
27670 public function isLocked()
27671 {
27672 if (!$this->lockFile->exists()) {
27673 return false;
27674 }
27675
27676 $data = $this->getLockData();
27677
27678 return isset($data['packages']);
27679 }
27680
27681
27682
27683
27684
27685
27686 public function isFresh()
27687 {
27688 $lock = $this->lockFile->read();
27689
27690 if (!empty($lock['content-hash'])) {
27691
27692  return $this->contentHash === $lock['content-hash'];
27693 }
27694
27695
27696  if (!empty($lock['hash'])) {
27697 return $this->hash === $lock['hash'];
27698 }
27699
27700
27701  return false;
27702 }
27703
27704
27705
27706
27707
27708
27709
27710
27711 public function getLockedRepository($withDevReqs = false)
27712 {
27713 $lockData = $this->getLockData();
27714 $packages = new ArrayRepository();
27715
27716 $lockedPackages = $lockData['packages'];
27717 if ($withDevReqs) {
27718 if (isset($lockData['packages-dev'])) {
27719 $lockedPackages = array_merge($lockedPackages, $lockData['packages-dev']);
27720 } else {
27721 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.');
27722 }
27723 }
27724
27725 if (empty($lockedPackages)) {
27726 return $packages;
27727 }
27728
27729 if (isset($lockedPackages[0]['name'])) {
27730 foreach ($lockedPackages as $info) {
27731 $packages->addPackage($this->loader->load($info));
27732 }
27733
27734 return $packages;
27735 }
27736
27737 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.');
27738 }
27739
27740
27741
27742
27743
27744
27745
27746 public function getPlatformRequirements($withDevReqs = false)
27747 {
27748 $lockData = $this->getLockData();
27749 $requirements = array();
27750
27751 if (!empty($lockData['platform'])) {
27752 $requirements = $this->loader->parseLinks(
27753 '__ROOT__',
27754 '1.0.0',
27755 'requires',
27756 isset($lockData['platform']) ? $lockData['platform'] : array()
27757 );
27758 }
27759
27760 if ($withDevReqs && !empty($lockData['platform-dev'])) {
27761 $devRequirements = $this->loader->parseLinks(
27762 '__ROOT__',
27763 '1.0.0',
27764 'requires',
27765 isset($lockData['platform-dev']) ? $lockData['platform-dev'] : array()
27766 );
27767
27768 $requirements = array_merge($requirements, $devRequirements);
27769 }
27770
27771 return $requirements;
27772 }
27773
27774 public function getMinimumStability()
27775 {
27776 $lockData = $this->getLockData();
27777
27778 return isset($lockData['minimum-stability']) ? $lockData['minimum-stability'] : 'stable';
27779 }
27780
27781 public function getStabilityFlags()
27782 {
27783 $lockData = $this->getLockData();
27784
27785 return isset($lockData['stability-flags']) ? $lockData['stability-flags'] : array();
27786 }
27787
27788 public function getPreferStable()
27789 {
27790 $lockData = $this->getLockData();
27791
27792
27793  
27794  return isset($lockData['prefer-stable']) ? $lockData['prefer-stable'] : null;
27795 }
27796
27797 public function getPreferLowest()
27798 {
27799 $lockData = $this->getLockData();
27800
27801
27802  
27803  return isset($lockData['prefer-lowest']) ? $lockData['prefer-lowest'] : null;
27804 }
27805
27806 public function getPlatformOverrides()
27807 {
27808 $lockData = $this->getLockData();
27809
27810 return isset($lockData['platform-overrides']) ? $lockData['platform-overrides'] : array();
27811 }
27812
27813 public function getAliases()
27814 {
27815 $lockData = $this->getLockData();
27816
27817 return isset($lockData['aliases']) ? $lockData['aliases'] : array();
27818 }
27819
27820 public function getLockData()
27821 {
27822 if (null !== $this->lockDataCache) {
27823 return $this->lockDataCache;
27824 }
27825
27826 if (!$this->lockFile->exists()) {
27827 throw new \LogicException('No lockfile found. Unable to read locked packages');
27828 }
27829
27830 return $this->lockDataCache = $this->lockFile->read();
27831 }
27832
27833
27834
27835
27836
27837
27838
27839
27840
27841
27842
27843
27844
27845
27846
27847
27848
27849 public function setLockData(array $packages, $devPackages, array $platformReqs, $platformDevReqs, array $aliases, $minimumStability, array $stabilityFlags, $preferStable, $preferLowest, array $platformOverrides)
27850 {
27851 $lock = array(
27852 '_readme' => array('This file locks the dependencies of your project to a known state',
27853 'Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file',
27854 'This file is @gener'.'ated automatically', ),
27855 'content-hash' => $this->contentHash,
27856 'packages' => null,
27857 'packages-dev' => null,
27858 'aliases' => array(),
27859 'minimum-stability' => $minimumStability,
27860 'stability-flags' => $stabilityFlags,
27861 'prefer-stable' => $preferStable,
27862 'prefer-lowest' => $preferLowest,
27863 );
27864
27865 foreach ($aliases as $package => $versions) {
27866 foreach ($versions as $version => $alias) {
27867 $lock['aliases'][] = array(
27868 'alias' => $alias['alias'],
27869 'alias_normalized' => $alias['alias_normalized'],
27870 'version' => $version,
27871 'package' => $package,
27872 );
27873 }
27874 }
27875
27876 $lock['packages'] = $this->lockPackages($packages);
27877 if (null !== $devPackages) {
27878 $lock['packages-dev'] = $this->lockPackages($devPackages);
27879 }
27880
27881 $lock['platform'] = $platformReqs;
27882 $lock['platform-dev'] = $platformDevReqs;
27883 if ($platformOverrides) {
27884 $lock['platform-overrides'] = $platformOverrides;
27885 }
27886
27887 if (empty($lock['packages']) && empty($lock['packages-dev']) && empty($lock['platform']) && empty($lock['platform-dev'])) {
27888 if ($this->lockFile->exists()) {
27889 unlink($this->lockFile->getPath());
27890 }
27891
27892 return false;
27893 }
27894
27895 try {
27896 $isLocked = $this->isLocked();
27897 } catch (ParsingException $e) {
27898 $isLocked = false;
27899 }
27900 if (!$isLocked || $lock !== $this->getLockData()) {
27901 $this->lockFile->write($lock);
27902 $this->lockDataCache = null;
27903
27904 return true;
27905 }
27906
27907 return false;
27908 }
27909
27910 private function lockPackages(array $packages)
27911 {
27912 $locked = array();
27913
27914 foreach ($packages as $package) {
27915 if ($package instanceof AliasPackage) {
27916 continue;
27917 }
27918
27919 $name = $package->getPrettyName();
27920 $version = $package->getPrettyVersion();
27921
27922 if (!$name || !$version) {
27923 throw new \LogicException(sprintf(
27924 'Package "%s" has no version or name and can not be locked', $package
27925 ));
27926 }
27927
27928 $spec = $this->dumper->dump($package);
27929 unset($spec['version_normalized']);
27930
27931
27932  $time = isset($spec['time']) ? $spec['time'] : null;
27933 unset($spec['time']);
27934 if ($package->isDev() && $package->getInstallationSource() === 'source') {
27935
27936  $time = $this->getPackageTime($package) ?: $time;
27937 }
27938 if (null !== $time) {
27939 $spec['time'] = $time;
27940 }
27941
27942 unset($spec['installation-source']);
27943
27944 $locked[] = $spec;
27945 }
27946
27947 usort($locked, function ($a, $b) {
27948 $comparison = strcmp($a['name'], $b['name']);
27949
27950 if (0 !== $comparison) {
27951 return $comparison;
27952 }
27953
27954
27955  return strcmp($a['version'], $b['version']);
27956 });
27957
27958 return $locked;
27959 }
27960
27961
27962
27963
27964
27965
27966
27967 private function getPackageTime(PackageInterface $package)
27968 {
27969 if (!function_exists('proc_open')) {
27970 return null;
27971 }
27972
27973 $path = realpath($this->installationManager->getInstallPath($package));
27974 $sourceType = $package->getSourceType();
27975 $datetime = null;
27976
27977 if ($path && in_array($sourceType, array('git', 'hg'))) {
27978 $sourceRef = $package->getSourceReference() ?: $package->getDistReference();
27979 switch ($sourceType) {
27980 case 'git':
27981 GitUtil::cleanEnv();
27982
27983 if (0 === $this->process->execute('git log -n1 --pretty=%ct '.ProcessExecutor::escape($sourceRef), $output, $path) && preg_match('{^\s*\d+\s*$}', $output)) {
27984 $datetime = new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
27985 }
27986 break;
27987
27988 case 'hg':
27989 if (0 === $this->process->execute('hg log --template "{date|hgdate}" -r '.ProcessExecutor::escape($sourceRef), $output, $path) && preg_match('{^\s*(\d+)\s*}', $output, $match)) {
27990 $datetime = new \DateTime('@'.$match[1], new \DateTimeZone('UTC'));
27991 }
27992 break;
27993 }
27994 }
27995
27996 return $datetime ? $datetime->format(DATE_RFC3339) : null;
27997 }
27998 }
27999 <?php
28000
28001
28002
28003
28004
28005
28006
28007
28008
28009
28010
28011 namespace Composer\Package;
28012
28013 use Composer\Package\Version\VersionParser;
28014 use Composer\Util\ComposerMirror;
28015
28016
28017
28018
28019
28020
28021 class Package extends BasePackage
28022 {
28023 protected $type;
28024 protected $targetDir;
28025 protected $installationSource;
28026 protected $sourceType;
28027 protected $sourceUrl;
28028 protected $sourceReference;
28029 protected $sourceMirrors;
28030 protected $distType;
28031 protected $distUrl;
28032 protected $distReference;
28033 protected $distSha1Checksum;
28034 protected $distMirrors;
28035 protected $version;
28036 protected $prettyVersion;
28037 protected $releaseDate;
28038 protected $extra = array();
28039 protected $binaries = array();
28040 protected $dev;
28041 protected $stability;
28042 protected $notificationUrl;
28043
28044
28045 protected $requires = array();
28046
28047 protected $conflicts = array();
28048
28049 protected $provides = array();
28050
28051 protected $replaces = array();
28052
28053 protected $devRequires = array();
28054 protected $suggests = array();
28055 protected $autoload = array();
28056 protected $devAutoload = array();
28057 protected $includePaths = array();
28058 protected $archiveExcludes = array();
28059
28060
28061
28062
28063
28064
28065
28066
28067 public function __construct($name, $version, $prettyVersion)
28068 {
28069 parent::__construct($name);
28070
28071 $this->version = $version;
28072 $this->prettyVersion = $prettyVersion;
28073
28074 $this->stability = VersionParser::parseStability($version);
28075 $this->dev = $this->stability === 'dev';
28076 }
28077
28078
28079
28080
28081 public function isDev()
28082 {
28083 return $this->dev;
28084 }
28085
28086
28087
28088
28089 public function setType($type)
28090 {
28091 $this->type = $type;
28092 }
28093
28094
28095
28096
28097 public function getType()
28098 {
28099 return $this->type ?: 'library';
28100 }
28101
28102
28103
28104
28105 public function getStability()
28106 {
28107 return $this->stability;
28108 }
28109
28110
28111
28112
28113 public function setTargetDir($targetDir)
28114 {
28115 $this->targetDir = $targetDir;
28116 }
28117
28118
28119
28120
28121 public function getTargetDir()
28122 {
28123 if (null === $this->targetDir) {
28124 return;
28125 }
28126
28127 return ltrim(preg_replace('{ (?:^|[\\\\/]+) \.\.? (?:[\\\\/]+|$) (?:\.\.? (?:[\\\\/]+|$) )*}x', '/', $this->targetDir), '/');
28128 }
28129
28130
28131
28132
28133 public function setExtra(array $extra)
28134 {
28135 $this->extra = $extra;
28136 }
28137
28138
28139
28140
28141 public function getExtra()
28142 {
28143 return $this->extra;
28144 }
28145
28146
28147
28148
28149 public function setBinaries(array $binaries)
28150 {
28151 $this->binaries = $binaries;
28152 }
28153
28154
28155
28156
28157 public function getBinaries()
28158 {
28159 return $this->binaries;
28160 }
28161
28162
28163
28164
28165 public function setInstallationSource($type)
28166 {
28167 $this->installationSource = $type;
28168 }
28169
28170
28171
28172
28173 public function getInstallationSource()
28174 {
28175 return $this->installationSource;
28176 }
28177
28178
28179
28180
28181 public function setSourceType($type)
28182 {
28183 $this->sourceType = $type;
28184 }
28185
28186
28187
28188
28189 public function getSourceType()
28190 {
28191 return $this->sourceType;
28192 }
28193
28194
28195
28196
28197 public function setSourceUrl($url)
28198 {
28199 $this->sourceUrl = $url;
28200 }
28201
28202
28203
28204
28205 public function getSourceUrl()
28206 {
28207 return $this->sourceUrl;
28208 }
28209
28210
28211
28212
28213 public function setSourceReference($reference)
28214 {
28215 $this->sourceReference = $reference;
28216 }
28217
28218
28219
28220
28221 public function getSourceReference()
28222 {
28223 return $this->sourceReference;
28224 }
28225
28226
28227
28228
28229 public function setSourceMirrors($mirrors)
28230 {
28231 $this->sourceMirrors = $mirrors;
28232 }
28233
28234
28235
28236
28237 public function getSourceMirrors()
28238 {
28239 return $this->sourceMirrors;
28240 }
28241
28242
28243
28244
28245 public function getSourceUrls()
28246 {
28247 return $this->getUrls($this->sourceUrl, $this->sourceMirrors, $this->sourceReference, $this->sourceType, 'source');
28248 }
28249
28250
28251
28252
28253 public function setDistType($type)
28254 {
28255 $this->distType = $type;
28256 }
28257
28258
28259
28260
28261 public function getDistType()
28262 {
28263 return $this->distType;
28264 }
28265
28266
28267
28268
28269 public function setDistUrl($url)
28270 {
28271 $this->distUrl = $url;
28272 }
28273
28274
28275
28276
28277 public function getDistUrl()
28278 {
28279 return $this->distUrl;
28280 }
28281
28282
28283
28284
28285 public function setDistReference($reference)
28286 {
28287 $this->distReference = $reference;
28288 }
28289
28290
28291
28292
28293 public function getDistReference()
28294 {
28295 return $this->distReference;
28296 }
28297
28298
28299
28300
28301 public function setDistSha1Checksum($sha1checksum)
28302 {
28303 $this->distSha1Checksum = $sha1checksum;
28304 }
28305
28306
28307
28308
28309 public function getDistSha1Checksum()
28310 {
28311 return $this->distSha1Checksum;
28312 }
28313
28314
28315
28316
28317 public function setDistMirrors($mirrors)
28318 {
28319 $this->distMirrors = $mirrors;
28320 }
28321
28322
28323
28324
28325 public function getDistMirrors()
28326 {
28327 return $this->distMirrors;
28328 }
28329
28330
28331
28332
28333 public function getDistUrls()
28334 {
28335 return $this->getUrls($this->distUrl, $this->distMirrors, $this->distReference, $this->distType, 'dist');
28336 }
28337
28338
28339
28340
28341 public function getVersion()
28342 {
28343 return $this->version;
28344 }
28345
28346
28347
28348
28349 public function getPrettyVersion()
28350 {
28351 return $this->prettyVersion;
28352 }
28353
28354
28355
28356
28357
28358
28359 public function setReleaseDate(\DateTime $releaseDate)
28360 {
28361 $this->releaseDate = $releaseDate;
28362 }
28363
28364
28365
28366
28367 public function getReleaseDate()
28368 {
28369 return $this->releaseDate;
28370 }
28371
28372
28373
28374
28375
28376
28377 public function setRequires(array $requires)
28378 {
28379 $this->requires = $requires;
28380 }
28381
28382
28383
28384
28385 public function getRequires()
28386 {
28387 return $this->requires;
28388 }
28389
28390
28391
28392
28393
28394
28395 public function setConflicts(array $conflicts)
28396 {
28397 $this->conflicts = $conflicts;
28398 }
28399
28400
28401
28402
28403 public function getConflicts()
28404 {
28405 return $this->conflicts;
28406 }
28407
28408
28409
28410
28411
28412
28413 public function setProvides(array $provides)
28414 {
28415 $this->provides = $provides;
28416 }
28417
28418
28419
28420
28421 public function getProvides()
28422 {
28423 return $this->provides;
28424 }
28425
28426
28427
28428
28429
28430
28431 public function setReplaces(array $replaces)
28432 {
28433 $this->replaces = $replaces;
28434 }
28435
28436
28437
28438
28439 public function getReplaces()
28440 {
28441 return $this->replaces;
28442 }
28443
28444
28445
28446
28447
28448
28449 public function setDevRequires(array $devRequires)
28450 {
28451 $this->devRequires = $devRequires;
28452 }
28453
28454
28455
28456
28457 public function getDevRequires()
28458 {
28459 return $this->devRequires;
28460 }
28461
28462
28463
28464
28465
28466
28467 public function setSuggests(array $suggests)
28468 {
28469 $this->suggests = $suggests;
28470 }
28471
28472
28473
28474
28475 public function getSuggests()
28476 {
28477 return $this->suggests;
28478 }
28479
28480
28481
28482
28483
28484
28485 public function setAutoload(array $autoload)
28486 {
28487 $this->autoload = $autoload;
28488 }
28489
28490
28491
28492
28493 public function getAutoload()
28494 {
28495 return $this->autoload;
28496 }
28497
28498
28499
28500
28501
28502
28503 public function setDevAutoload(array $devAutoload)
28504 {
28505 $this->devAutoload = $devAutoload;
28506 }
28507
28508
28509
28510
28511 public function getDevAutoload()
28512 {
28513 return $this->devAutoload;
28514 }
28515
28516
28517
28518
28519
28520
28521 public function setIncludePaths(array $includePaths)
28522 {
28523 $this->includePaths = $includePaths;
28524 }
28525
28526
28527
28528
28529 public function getIncludePaths()
28530 {
28531 return $this->includePaths;
28532 }
28533
28534
28535
28536
28537
28538
28539 public function setNotificationUrl($notificationUrl)
28540 {
28541 $this->notificationUrl = $notificationUrl;
28542 }
28543
28544
28545
28546
28547 public function getNotificationUrl()
28548 {
28549 return $this->notificationUrl;
28550 }
28551
28552
28553
28554
28555
28556
28557 public function setArchiveExcludes(array $excludes)
28558 {
28559 $this->archiveExcludes = $excludes;
28560 }
28561
28562
28563
28564
28565 public function getArchiveExcludes()
28566 {
28567 return $this->archiveExcludes;
28568 }
28569
28570
28571
28572
28573
28574
28575
28576
28577 public function replaceVersion($version, $prettyVersion)
28578 {
28579 $this->version = $version;
28580 $this->prettyVersion = $prettyVersion;
28581
28582 $this->stability = VersionParser::parseStability($version);
28583 $this->dev = $this->stability === 'dev';
28584 }
28585
28586 protected function getUrls($url, $mirrors, $ref, $type, $urlType)
28587 {
28588 if (!$url) {
28589 return array();
28590 }
28591 $urls = array($url);
28592 if ($mirrors) {
28593 foreach ($mirrors as $mirror) {
28594 if ($urlType === 'dist') {
28595 $mirrorUrl = ComposerMirror::processUrl($mirror['url'], $this->name, $this->version, $ref, $type);
28596 } elseif ($urlType === 'source' && $type === 'git') {
28597 $mirrorUrl = ComposerMirror::processGitUrl($mirror['url'], $this->name, $url, $type);
28598 } elseif ($urlType === 'source' && $type === 'hg') {
28599 $mirrorUrl = ComposerMirror::processHgUrl($mirror['url'], $this->name, $url, $type);
28600 }
28601 if (!in_array($mirrorUrl, $urls)) {
28602 $func = $mirror['preferred'] ? 'array_unshift' : 'array_push';
28603 $func($urls, $mirrorUrl);
28604 }
28605 }
28606 }
28607
28608 return $urls;
28609 }
28610 }
28611 <?php
28612
28613
28614
28615
28616
28617
28618
28619
28620
28621
28622
28623 namespace Composer\Package;
28624
28625 use Composer\Repository\RepositoryInterface;
28626
28627
28628
28629
28630
28631
28632 interface PackageInterface
28633 {
28634
28635
28636
28637
28638
28639 public function getName();
28640
28641
28642
28643
28644
28645
28646 public function getPrettyName();
28647
28648
28649
28650
28651
28652
28653
28654
28655
28656 public function getNames();
28657
28658
28659
28660
28661
28662
28663 public function setId($id);
28664
28665
28666
28667
28668
28669
28670 public function getId();
28671
28672
28673
28674
28675
28676
28677 public function isDev();
28678
28679
28680
28681
28682
28683
28684 public function getType();
28685
28686
28687
28688
28689
28690
28691 public function getTargetDir();
28692
28693
28694
28695
28696
28697
28698 public function getExtra();
28699
28700
28701
28702
28703
28704
28705 public function setInstallationSource($type);
28706
28707
28708
28709
28710
28711
28712 public function getInstallationSource();
28713
28714
28715
28716
28717
28718
28719 public function getSourceType();
28720
28721
28722
28723
28724
28725
28726 public function getSourceUrl();
28727
28728
28729
28730
28731
28732
28733 public function getSourceUrls();
28734
28735
28736
28737
28738
28739
28740 public function getSourceReference();
28741
28742
28743
28744
28745
28746
28747 public function getSourceMirrors();
28748
28749
28750
28751
28752
28753
28754 public function getDistType();
28755
28756
28757
28758
28759
28760
28761 public function getDistUrl();
28762
28763
28764
28765
28766
28767
28768 public function getDistUrls();
28769
28770
28771
28772
28773
28774
28775 public function getDistReference();
28776
28777
28778
28779
28780
28781
28782 public function getDistSha1Checksum();
28783
28784
28785
28786
28787
28788
28789 public function getDistMirrors();
28790
28791
28792
28793
28794
28795
28796 public function getVersion();
28797
28798
28799
28800
28801
28802
28803 public function getPrettyVersion();
28804
28805
28806
28807
28808
28809
28810
28811
28812
28813 public function getFullPrettyVersion($truncate = true);
28814
28815
28816
28817
28818
28819
28820 public function getReleaseDate();
28821
28822
28823
28824
28825
28826
28827 public function getStability();
28828
28829
28830
28831
28832
28833
28834
28835 public function getRequires();
28836
28837
28838
28839
28840
28841
28842
28843 public function getConflicts();
28844
28845
28846
28847
28848
28849
28850
28851 public function getProvides();
28852
28853
28854
28855
28856
28857
28858
28859 public function getReplaces();
28860
28861
28862
28863
28864
28865
28866
28867 public function getDevRequires();
28868
28869
28870
28871
28872
28873
28874
28875 public function getSuggests();
28876
28877
28878
28879
28880
28881
28882
28883
28884
28885
28886
28887 public function getAutoload();
28888
28889
28890
28891
28892
28893
28894
28895
28896
28897
28898
28899 public function getDevAutoload();
28900
28901
28902
28903
28904
28905
28906
28907 public function getIncludePaths();
28908
28909
28910
28911
28912
28913
28914 public function setRepository(RepositoryInterface $repository);
28915
28916
28917
28918
28919
28920
28921 public function getRepository();
28922
28923
28924
28925
28926
28927
28928 public function getBinaries();
28929
28930
28931
28932
28933
28934
28935 public function getUniqueName();
28936
28937
28938
28939
28940
28941
28942 public function getNotificationUrl();
28943
28944
28945
28946
28947
28948
28949 public function __toString();
28950
28951
28952
28953
28954
28955
28956 public function getPrettyString();
28957
28958
28959
28960
28961
28962
28963 public function getArchiveExcludes();
28964
28965
28966
28967
28968
28969
28970 public function getTransportOptions();
28971 }
28972 <?php
28973
28974
28975
28976
28977
28978
28979
28980
28981
28982
28983
28984 namespace Composer\Package;
28985
28986
28987
28988
28989 class RootAliasPackage extends AliasPackage implements RootPackageInterface
28990 {
28991 public function __construct(RootPackageInterface $aliasOf, $version, $prettyVersion)
28992 {
28993 parent::__construct($aliasOf, $version, $prettyVersion);
28994 }
28995
28996
28997
28998
28999 public function getAliases()
29000 {
29001 return $this->aliasOf->getAliases();
29002 }
29003
29004
29005
29006
29007 public function getMinimumStability()
29008 {
29009 return $this->aliasOf->getMinimumStability();
29010 }
29011
29012
29013
29014
29015 public function getStabilityFlags()
29016 {
29017 return $this->aliasOf->getStabilityFlags();
29018 }
29019
29020
29021
29022
29023 public function getReferences()
29024 {
29025 return $this->aliasOf->getReferences();
29026 }
29027
29028
29029
29030
29031 public function getPreferStable()
29032 {
29033 return $this->aliasOf->getPreferStable();
29034 }
29035
29036
29037
29038
29039 public function getConfig()
29040 {
29041 return $this->aliasOf->getConfig();
29042 }
29043
29044
29045
29046
29047 public function setRequires(array $require)
29048 {
29049 $this->requires = $this->replaceSelfVersionDependencies($require, 'requires');
29050
29051 $this->aliasOf->setRequires($require);
29052 }
29053
29054
29055
29056
29057 public function setDevRequires(array $devRequire)
29058 {
29059 $this->devRequires = $this->replaceSelfVersionDependencies($devRequire, 'devRequires');
29060
29061 $this->aliasOf->setDevRequires($devRequire);
29062 }
29063
29064
29065
29066
29067 public function setConflicts(array $conflicts)
29068 {
29069 $this->conflicts = $this->replaceSelfVersionDependencies($conflicts, 'conflicts');
29070 $this->aliasOf->setConflicts($conflicts);
29071 }
29072
29073
29074
29075
29076 public function setProvides(array $provides)
29077 {
29078 $this->provides = $this->replaceSelfVersionDependencies($provides, 'provides');
29079 $this->aliasOf->setProvides($provides);
29080 }
29081
29082
29083
29084
29085 public function setReplaces(array $replaces)
29086 {
29087 $this->replaces = $this->replaceSelfVersionDependencies($replaces, 'replaces');
29088 $this->aliasOf->setReplaces($replaces);
29089 }
29090
29091
29092
29093
29094 public function setRepositories($repositories)
29095 {
29096 $this->aliasOf->setRepositories($repositories);
29097 }
29098
29099
29100
29101
29102 public function setAutoload(array $autoload)
29103 {
29104 $this->aliasOf->setAutoload($autoload);
29105 }
29106
29107
29108
29109
29110 public function setDevAutoload(array $devAutoload)
29111 {
29112 $this->aliasOf->setDevAutoload($devAutoload);
29113 }
29114
29115
29116
29117
29118 public function setStabilityFlags(array $stabilityFlags)
29119 {
29120 $this->aliasOf->setStabilityFlags($stabilityFlags);
29121 }
29122
29123
29124
29125
29126 public function setSuggests(array $suggests)
29127 {
29128 $this->aliasOf->setSuggests($suggests);
29129 }
29130
29131
29132
29133
29134 public function setExtra(array $extra)
29135 {
29136 $this->aliasOf->setExtra($extra);
29137 }
29138
29139 public function __clone()
29140 {
29141 parent::__clone();
29142 $this->aliasOf = clone $this->aliasOf;
29143 }
29144 }
29145 <?php
29146
29147
29148
29149
29150
29151
29152
29153
29154
29155
29156
29157 namespace Composer\Package;
29158
29159
29160
29161
29162
29163
29164 class RootPackage extends CompletePackage implements RootPackageInterface
29165 {
29166 protected $minimumStability = 'stable';
29167 protected $preferStable = false;
29168 protected $stabilityFlags = array();
29169 protected $config = array();
29170 protected $references = array();
29171 protected $aliases = array();
29172
29173
29174
29175
29176
29177
29178 public function setMinimumStability($minimumStability)
29179 {
29180 $this->minimumStability = $minimumStability;
29181 }
29182
29183
29184
29185
29186 public function getMinimumStability()
29187 {
29188 return $this->minimumStability;
29189 }
29190
29191
29192
29193
29194
29195
29196 public function setStabilityFlags(array $stabilityFlags)
29197 {
29198 $this->stabilityFlags = $stabilityFlags;
29199 }
29200
29201
29202
29203
29204 public function getStabilityFlags()
29205 {
29206 return $this->stabilityFlags;
29207 }
29208
29209
29210
29211
29212
29213
29214 public function setPreferStable($preferStable)
29215 {
29216 $this->preferStable = $preferStable;
29217 }
29218
29219
29220
29221
29222 public function getPreferStable()
29223 {
29224 return $this->preferStable;
29225 }
29226
29227
29228
29229
29230
29231
29232 public function setConfig(array $config)
29233 {
29234 $this->config = $config;
29235 }
29236
29237
29238
29239
29240 public function getConfig()
29241 {
29242 return $this->config;
29243 }
29244
29245
29246
29247
29248
29249
29250 public function setReferences(array $references)
29251 {
29252 $this->references = $references;
29253 }
29254
29255
29256
29257
29258 public function getReferences()
29259 {
29260 return $this->references;
29261 }
29262
29263
29264
29265
29266
29267
29268 public function setAliases(array $aliases)
29269 {
29270 $this->aliases = $aliases;
29271 }
29272
29273
29274
29275
29276 public function getAliases()
29277 {
29278 return $this->aliases;
29279 }
29280 }
29281 <?php
29282
29283
29284
29285
29286
29287
29288
29289
29290
29291
29292
29293 namespace Composer\Package;
29294
29295
29296
29297
29298
29299
29300 interface RootPackageInterface extends CompletePackageInterface
29301 {
29302
29303
29304
29305
29306
29307 public function getAliases();
29308
29309
29310
29311
29312
29313
29314 public function getMinimumStability();
29315
29316
29317
29318
29319
29320
29321
29322
29323 public function getStabilityFlags();
29324
29325
29326
29327
29328
29329
29330
29331
29332 public function getReferences();
29333
29334
29335
29336
29337
29338
29339 public function getPreferStable();
29340
29341
29342
29343
29344
29345
29346 public function getConfig();
29347
29348
29349
29350
29351
29352
29353 public function setRequires(array $requires);
29354
29355
29356
29357
29358
29359
29360 public function setDevRequires(array $devRequires);
29361
29362
29363
29364
29365
29366
29367 public function setConflicts(array $conflicts);
29368
29369
29370
29371
29372
29373
29374 public function setProvides(array $provides);
29375
29376
29377
29378
29379
29380
29381 public function setReplaces(array $replaces);
29382
29383
29384
29385
29386
29387
29388 public function setRepositories($repositories);
29389
29390
29391
29392
29393
29394
29395 public function setAutoload(array $autoload);
29396
29397
29398
29399
29400
29401
29402 public function setDevAutoload(array $devAutoload);
29403
29404
29405
29406
29407
29408
29409 public function setStabilityFlags(array $stabilityFlags);
29410
29411
29412
29413
29414
29415
29416 public function setSuggests(array $suggests);
29417
29418
29419
29420
29421 public function setExtra(array $extra);
29422 }
29423 <?php
29424
29425
29426
29427
29428
29429
29430
29431
29432
29433
29434
29435 namespace Composer\Package\Version;
29436
29437 use Composer\Config;
29438 use Composer\Repository\Vcs\HgDriver;
29439 use Composer\IO\NullIO;
29440 use Composer\Semver\VersionParser as SemverVersionParser;
29441 use Composer\Util\Git as GitUtil;
29442 use Composer\Util\ProcessExecutor;
29443 use Composer\Util\Svn as SvnUtil;
29444
29445
29446
29447
29448
29449
29450
29451 class VersionGuesser
29452 {
29453
29454
29455
29456 private $config;
29457
29458
29459
29460
29461 private $process;
29462
29463
29464
29465
29466 private $versionParser;
29467
29468
29469
29470
29471
29472
29473 public function __construct(Config $config, ProcessExecutor $process, SemverVersionParser $versionParser)
29474 {
29475 $this->config = $config;
29476 $this->process = $process;
29477 $this->versionParser = $versionParser;
29478 }
29479
29480
29481
29482
29483
29484
29485
29486 public function guessVersion(array $packageConfig, $path)
29487 {
29488 if (function_exists('proc_open')) {
29489 $versionData = $this->guessGitVersion($packageConfig, $path);
29490 if (null !== $versionData && null !== $versionData['version']) {
29491 return $versionData;
29492 }
29493
29494 $versionData = $this->guessHgVersion($packageConfig, $path);
29495 if (null !== $versionData && null !== $versionData['version']) {
29496 return $versionData;
29497 }
29498
29499 $versionData = $this->guessFossilVersion($packageConfig, $path);
29500 if (null !== $versionData && null !== $versionData['version']) {
29501 return $versionData;
29502 }
29503
29504 return $this->guessSvnVersion($packageConfig, $path);
29505 }
29506 }
29507
29508 private function guessGitVersion(array $packageConfig, $path)
29509 {
29510 GitUtil::cleanEnv();
29511 $commit = null;
29512 $version = null;
29513 $prettyVersion = null;
29514 $isDetached = false;
29515
29516
29517  if (0 === $this->process->execute('git branch --no-color --no-abbrev -v', $output, $path)) {
29518 $branches = array();
29519 $isFeatureBranch = false;
29520
29521
29522  foreach ($this->process->splitLines($output) as $branch) {
29523 if ($branch && preg_match('{^(?:\* ) *(\(no branch\)|\(detached from \S+\)|\(HEAD detached at \S+\)|\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
29524 if ($match[1] === '(no branch)' || substr($match[1], 0, 10) === '(detached ' || substr($match[1], 0, 17) === '(HEAD detached at') {
29525 $version = 'dev-' . $match[2];
29526 $prettyVersion = $version;
29527 $isFeatureBranch = true;
29528 $isDetached = true;
29529 } else {
29530 $version = $this->versionParser->normalizeBranch($match[1]);
29531 $prettyVersion = 'dev-' . $match[1];
29532 $isFeatureBranch = 0 === strpos($version, 'dev-');
29533 if ('9999999-dev' === $version) {
29534 $version = $prettyVersion;
29535 }
29536 }
29537
29538 if ($match[2]) {
29539 $commit = $match[2];
29540 }
29541 }
29542
29543 if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
29544 if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+) .*$}', $branch, $match)) {
29545 $branches[] = $match[1];
29546 }
29547 }
29548 }
29549
29550 if ($isFeatureBranch) {
29551
29552  $result = $this->guessFeatureVersion($packageConfig, $version, $branches, 'git rev-list %candidate%..%branch%', $path);
29553 $version = $result['version'];
29554 $prettyVersion = $result['pretty_version'];
29555 }
29556 }
29557
29558 if (!$version || $isDetached) {
29559 $result = $this->versionFromGitTags($path);
29560 if ($result) {
29561 $version = $result['version'];
29562 $prettyVersion = $result['pretty_version'];
29563 }
29564 }
29565
29566 if (!$commit) {
29567 $command = 'git log --pretty="%H" -n1 HEAD';
29568 if (0 === $this->process->execute($command, $output, $path)) {
29569 $commit = trim($output) ?: null;
29570 }
29571 }
29572
29573 return array('version' => $version, 'commit' => $commit, 'pretty_version' => $prettyVersion);
29574 }
29575
29576 private function versionFromGitTags($path)
29577 {
29578
29579  if (0 === $this->process->execute('git describe --exact-match --tags', $output, $path)) {
29580 try {
29581 $version = $this->versionParser->normalize(trim($output));
29582
29583 return array('version' => $version, 'pretty_version' => trim($output));
29584 } catch (\Exception $e) {
29585 }
29586 }
29587
29588 return null;
29589 }
29590
29591 private function guessHgVersion(array $packageConfig, $path)
29592 {
29593
29594  if (0 === $this->process->execute('hg branch', $output, $path)) {
29595 $branch = trim($output);
29596 $version = $this->versionParser->normalizeBranch($branch);
29597 $isFeatureBranch = 0 === strpos($version, 'dev-');
29598
29599 if ('9999999-dev' === $version) {
29600 $version = 'dev-' . $branch;
29601 }
29602
29603 if (!$isFeatureBranch) {
29604 return array('version' => $version, 'commit' => null, 'pretty_version' => $version);
29605 }
29606
29607
29608  $driver = new HgDriver(array('url' => $path), new NullIO(), $this->config, $this->process);
29609 $branches = array_keys($driver->getBranches());
29610
29611
29612  $result = $this->guessFeatureVersion($packageConfig, $version, $branches, 'hg log -r "not ancestors(\'%candidate%\') and ancestors(\'%branch%\')" --template "{node}\\n"', $path);
29613 $result['commit'] = '';
29614
29615 return $result;
29616 }
29617 }
29618
29619 private function guessFeatureVersion(array $packageConfig, $version, array $branches, $scmCmdline, $path)
29620 {
29621 $prettyVersion = $version;
29622
29623
29624  
29625  if ((isset($packageConfig['extra']['branch-alias']) && !isset($packageConfig['extra']['branch-alias'][$version]))
29626 || strpos(json_encode($packageConfig), '"self.version"')
29627 ) {
29628 $branch = preg_replace('{^dev-}', '', $version);
29629 $length = PHP_INT_MAX;
29630
29631 $nonFeatureBranches = '';
29632 if (!empty($packageConfig['non-feature-branches'])) {
29633 $nonFeatureBranches = implode('|', $packageConfig['non-feature-branches']);
29634 }
29635
29636 foreach ($branches as $candidate) {
29637
29638  if ($candidate === $branch && preg_match('{^(' . $nonFeatureBranches . ')$}', $candidate)) {
29639 break;
29640 }
29641
29642
29643  if ($candidate === $branch || !preg_match('{^(' . $nonFeatureBranches . '|master|trunk|default|develop|\d+\..+)$}', $candidate, $match)) {
29644 continue;
29645 }
29646
29647 $cmdLine = str_replace(array('%candidate%', '%branch%'), array($candidate, $branch), $scmCmdline);
29648 if (0 !== $this->process->execute($cmdLine, $output, $path)) {
29649 continue;
29650 }
29651
29652 if (strlen($output) < $length) {
29653 $length = strlen($output);
29654 $version = $this->versionParser->normalizeBranch($candidate);
29655 $prettyVersion = 'dev-' . $match[1];
29656 if ('9999999-dev' === $version) {
29657 $version = $prettyVersion;
29658 }
29659 }
29660 }
29661 }
29662
29663 return array('version' => $version, 'pretty_version' => $prettyVersion);
29664 }
29665
29666 private function guessFossilVersion(array $packageConfig, $path)
29667 {
29668 $version = null;
29669 $prettyVersion = null;
29670
29671
29672  if (0 === $this->process->execute('fossil branch list', $output, $path)) {
29673 $branch = trim($output);
29674 $version = $this->versionParser->normalizeBranch($branch);
29675 $prettyVersion = 'dev-' . $branch;
29676
29677 if ('9999999-dev' === $version) {
29678 $version = $prettyVersion;
29679 }
29680 }
29681
29682
29683  if (0 === $this->process->execute('fossil tag list', $output, $path)) {
29684 try {
29685 $version = $this->versionParser->normalize(trim($output));
29686 $prettyVersion = trim($output);
29687 } catch (\Exception $e) {
29688 }
29689 }
29690
29691 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
29692 }
29693
29694 private function guessSvnVersion(array $packageConfig, $path)
29695 {
29696 SvnUtil::cleanEnv();
29697
29698
29699  if (0 === $this->process->execute('svn info --xml', $output, $path)) {
29700 $trunkPath = isset($packageConfig['trunk-path']) ? preg_quote($packageConfig['trunk-path'], '#') : 'trunk';
29701 $branchesPath = isset($packageConfig['branches-path']) ? preg_quote($packageConfig['branches-path'], '#') : 'branches';
29702 $tagsPath = isset($packageConfig['tags-path']) ? preg_quote($packageConfig['tags-path'], '#') : 'tags';
29703
29704 $urlPattern = '#<url>.*/(' . $trunkPath . '|(' . $branchesPath . '|' . $tagsPath . ')/(.*))</url>#';
29705
29706 if (preg_match($urlPattern, $output, $matches)) {
29707 if (isset($matches[2]) && ($branchesPath === $matches[2] || $tagsPath === $matches[2])) {
29708
29709  $version = $this->versionParser->normalizeBranch($matches[3]);
29710 $prettyVersion = 'dev-' . $matches[3];
29711 if ('9999999-dev' === $version) {
29712 $version = $prettyVersion;
29713 }
29714
29715 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
29716 }
29717
29718 $prettyVersion = trim($matches[1]);
29719 $version = $this->versionParser->normalize($prettyVersion);
29720
29721 return array('version' => $version, 'commit' => '', 'pretty_version' => $prettyVersion);
29722 }
29723 }
29724 }
29725 }
29726 <?php
29727
29728
29729
29730
29731
29732
29733
29734
29735
29736
29737
29738 namespace Composer\Package\Version;
29739
29740 use Composer\Semver\VersionParser as SemverVersionParser;
29741
29742 class VersionParser extends SemverVersionParser
29743 {
29744 private static $constraints = array();
29745
29746
29747
29748
29749 public function parseConstraints($constraints)
29750 {
29751 if (!isset(self::$constraints[$constraints])) {
29752 self::$constraints[$constraints] = parent::parseConstraints($constraints);
29753 }
29754
29755 return self::$constraints[$constraints];
29756 }
29757
29758
29759
29760
29761
29762
29763
29764
29765
29766
29767
29768 public function parseNameVersionPairs(array $pairs)
29769 {
29770 $pairs = array_values($pairs);
29771 $result = array();
29772
29773 for ($i = 0, $count = count($pairs); $i < $count; $i++) {
29774 $pair = preg_replace('{^([^=: ]+)[=: ](.*)$}', '$1 $2', trim($pairs[$i]));
29775 if (false === strpos($pair, ' ') && isset($pairs[$i + 1]) && false === strpos($pairs[$i + 1], '/')) {
29776 $pair .= ' '.$pairs[$i + 1];
29777 $i++;
29778 }
29779
29780 if (strpos($pair, ' ')) {
29781 list($name, $version) = explode(" ", $pair, 2);
29782 $result[] = array('name' => $name, 'version' => $version);
29783 } else {
29784 $result[] = array('name' => $pair);
29785 }
29786 }
29787
29788 return $result;
29789 }
29790 }
29791 <?php
29792
29793
29794
29795
29796
29797
29798
29799
29800
29801
29802
29803 namespace Composer\Package\Version;
29804
29805 use Composer\DependencyResolver\Pool;
29806 use Composer\Package\BasePackage;
29807 use Composer\Package\PackageInterface;
29808 use Composer\Package\Loader\ArrayLoader;
29809 use Composer\Package\Dumper\ArrayDumper;
29810 use Composer\Semver\Constraint\Constraint;
29811
29812
29813
29814
29815
29816
29817
29818 class VersionSelector
29819 {
29820 private $pool;
29821
29822 private $parser;
29823
29824 public function __construct(Pool $pool)
29825 {
29826 $this->pool = $pool;
29827 }
29828
29829
29830
29831
29832
29833
29834
29835
29836
29837
29838
29839 public function findBestCandidate($packageName, $targetPackageVersion = null, $targetPhpVersion = null, $preferredStability = 'stable')
29840 {
29841 $constraint = $targetPackageVersion ? $this->getParser()->parseConstraints($targetPackageVersion) : null;
29842 $candidates = $this->pool->whatProvides(strtolower($packageName), $constraint, true);
29843
29844 if ($targetPhpVersion) {
29845 $phpConstraint = new Constraint('==', $this->getParser()->normalize($targetPhpVersion));
29846 $candidates = array_filter($candidates, function ($pkg) use ($phpConstraint) {
29847 $reqs = $pkg->getRequires();
29848
29849 return !isset($reqs['php']) || $reqs['php']->getConstraint()->matches($phpConstraint);
29850 });
29851 }
29852
29853 if (!$candidates) {
29854 return false;
29855 }
29856
29857
29858  $package = reset($candidates);
29859 $minPriority = BasePackage::$stabilities[$preferredStability];
29860 foreach ($candidates as $candidate) {
29861 $candidatePriority = $candidate->getStabilityPriority();
29862 $currentPriority = $package->getStabilityPriority();
29863
29864
29865  
29866  if ($minPriority < $candidatePriority && $currentPriority < $candidatePriority) {
29867 continue;
29868 }
29869
29870
29871  
29872  if ($minPriority < $candidatePriority && $candidatePriority < $currentPriority) {
29873 $package = $candidate;
29874 continue;
29875 }
29876
29877
29878  
29879  if ($minPriority >= $candidatePriority && $minPriority < $currentPriority) {
29880 $package = $candidate;
29881 continue;
29882 }
29883
29884
29885  if (version_compare($package->getVersion(), $candidate->getVersion(), '<')) {
29886 $package = $candidate;
29887 }
29888 }
29889
29890 return $package;
29891 }
29892
29893
29894
29895
29896
29897
29898
29899
29900
29901
29902
29903
29904
29905
29906
29907
29908 public function findRecommendedRequireVersion(PackageInterface $package)
29909 {
29910 $version = $package->getVersion();
29911 if (!$package->isDev()) {
29912 return $this->transformVersion($version, $package->getPrettyVersion(), $package->getStability());
29913 }
29914
29915 $loader = new ArrayLoader($this->getParser());
29916 $dumper = new ArrayDumper();
29917 $extra = $loader->getBranchAlias($dumper->dump($package));
29918 if ($extra) {
29919 $extra = preg_replace('{^(\d+\.\d+\.\d+)(\.9999999)-dev$}', '$1.0', $extra, -1, $count);
29920 if ($count) {
29921 $extra = str_replace('.9999999', '.0', $extra);
29922
29923 return $this->transformVersion($extra, $extra, 'dev');
29924 }
29925 }
29926
29927 return $package->getPrettyVersion();
29928 }
29929
29930 private function transformVersion($version, $prettyVersion, $stability)
29931 {
29932
29933  
29934  $semanticVersionParts = explode('.', $version);
29935
29936
29937  if (count($semanticVersionParts) == 4 && preg_match('{^0\D?}', $semanticVersionParts[3])) {
29938
29939  if ($semanticVersionParts[0] === '0') {
29940 unset($semanticVersionParts[3]);
29941 } else {
29942 unset($semanticVersionParts[2], $semanticVersionParts[3]);
29943 }
29944 $version = implode('.', $semanticVersionParts);
29945 } else {
29946 return $prettyVersion;
29947 }
29948
29949
29950  if ($stability != 'stable') {
29951 $version .= '@'.$stability;
29952 }
29953
29954
29955  return '^' . $version;
29956 }
29957
29958 private function getParser()
29959 {
29960 if ($this->parser === null) {
29961 $this->parser = new VersionParser();
29962 }
29963
29964 return $this->parser;
29965 }
29966 }
29967 <?php
29968
29969
29970
29971
29972
29973
29974
29975
29976
29977
29978
29979 namespace Composer\Plugin\Capability;
29980
29981
29982
29983
29984
29985
29986
29987 interface Capability
29988 {
29989 }
29990 <?php
29991
29992
29993
29994
29995
29996
29997
29998
29999
30000
30001
30002 namespace Composer\Plugin\Capability;
30003
30004
30005
30006
30007
30008
30009
30010
30011
30012
30013
30014 interface CommandProvider extends Capability
30015 {
30016
30017
30018
30019
30020
30021 public function getCommands();
30022 }
30023 <?php
30024
30025
30026
30027
30028
30029
30030
30031
30032
30033
30034
30035 namespace Composer\Plugin;
30036
30037
30038
30039
30040
30041
30042
30043
30044 interface Capable
30045 {
30046
30047
30048
30049
30050
30051
30052
30053
30054
30055
30056
30057
30058
30059
30060
30061
30062
30063
30064 public function getCapabilities();
30065 }
30066 <?php
30067
30068
30069
30070
30071
30072
30073
30074
30075
30076
30077
30078 namespace Composer\Plugin;
30079
30080 use Composer\EventDispatcher\Event;
30081 use Symfony\Component\Console\Input\InputInterface;
30082 use Symfony\Component\Console\Output\OutputInterface;
30083
30084
30085
30086
30087
30088
30089 class CommandEvent extends Event
30090 {
30091
30092
30093
30094 private $commandName;
30095
30096
30097
30098
30099 private $input;
30100
30101
30102
30103
30104 private $output;
30105
30106
30107
30108
30109
30110
30111
30112
30113
30114
30115
30116 public function __construct($name, $commandName, $input, $output, array $args = array(), array $flags = array())
30117 {
30118 parent::__construct($name, $args, $flags);
30119 $this->commandName = $commandName;
30120 $this->input = $input;
30121 $this->output = $output;
30122 }
30123
30124
30125
30126
30127
30128
30129 public function getInput()
30130 {
30131 return $this->input;
30132 }
30133
30134
30135
30136
30137
30138
30139 public function getOutput()
30140 {
30141 return $this->output;
30142 }
30143
30144
30145
30146
30147
30148
30149 public function getCommandName()
30150 {
30151 return $this->commandName;
30152 }
30153 }
30154 <?php
30155
30156
30157
30158
30159
30160
30161
30162
30163
30164
30165
30166 namespace Composer\Plugin;
30167
30168
30169
30170
30171
30172
30173 class PluginEvents
30174 {
30175
30176
30177
30178
30179
30180
30181
30182
30183 const INIT = 'init';
30184
30185
30186
30187
30188
30189
30190
30191
30192
30193 const COMMAND = 'command';
30194
30195
30196
30197
30198
30199
30200
30201
30202
30203 const PRE_FILE_DOWNLOAD = 'pre-file-download';
30204 }
30205 <?php
30206
30207
30208
30209
30210
30211
30212
30213
30214
30215
30216
30217 namespace Composer\Plugin;
30218
30219 use Composer\Composer;
30220 use Composer\IO\IOInterface;
30221
30222
30223
30224
30225
30226
30227 interface PluginInterface
30228 {
30229
30230
30231
30232
30233
30234 const PLUGIN_API_VERSION = '1.1.0';
30235
30236
30237
30238
30239
30240
30241
30242 public function activate(Composer $composer, IOInterface $io);
30243 }
30244 <?php
30245
30246
30247
30248
30249
30250
30251
30252
30253
30254
30255
30256 namespace Composer\Plugin;
30257
30258 use Composer\Composer;
30259 use Composer\EventDispatcher\EventSubscriberInterface;
30260 use Composer\IO\IOInterface;
30261 use Composer\Package\Package;
30262 use Composer\Package\Version\VersionParser;
30263 use Composer\Repository\RepositoryInterface;
30264 use Composer\Package\AliasPackage;
30265 use Composer\Package\PackageInterface;
30266 use Composer\Package\Link;
30267 use Composer\Semver\Constraint\Constraint;
30268 use Composer\DependencyResolver\Pool;
30269 use Composer\Plugin\Capability\Capability;
30270
30271
30272
30273
30274
30275
30276
30277 class PluginManager
30278 {
30279 protected $composer;
30280 protected $io;
30281 protected $globalComposer;
30282 protected $versionParser;
30283 protected $disablePlugins = false;
30284
30285 protected $plugins = array();
30286 protected $registeredPlugins = array();
30287
30288 private static $classCounter = 0;
30289
30290
30291
30292
30293
30294
30295
30296
30297
30298 public function __construct(IOInterface $io, Composer $composer, Composer $globalComposer = null, $disablePlugins = false)
30299 {
30300 $this->io = $io;
30301 $this->composer = $composer;
30302 $this->globalComposer = $globalComposer;
30303 $this->versionParser = new VersionParser();
30304 $this->disablePlugins = $disablePlugins;
30305 }
30306
30307
30308
30309
30310 public function loadInstalledPlugins()
30311 {
30312 if ($this->disablePlugins) {
30313 return;
30314 }
30315
30316 $repo = $this->composer->getRepositoryManager()->getLocalRepository();
30317 $globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
30318 if ($repo) {
30319 $this->loadRepository($repo);
30320 }
30321 if ($globalRepo) {
30322 $this->loadRepository($globalRepo);
30323 }
30324 }
30325
30326
30327
30328
30329
30330
30331 public function getPlugins()
30332 {
30333 return $this->plugins;
30334 }
30335
30336
30337
30338
30339
30340
30341 public function getGlobalComposer()
30342 {
30343 return $this->globalComposer;
30344 }
30345
30346
30347
30348
30349
30350
30351
30352
30353
30354
30355
30356
30357 public function registerPackage(PackageInterface $package, $failOnMissingClasses = false)
30358 {
30359 if ($this->disablePlugins) {
30360 return;
30361 }
30362
30363 if ($package->getType() === 'composer-plugin') {
30364 $requiresComposer = null;
30365 foreach ($package->getRequires() as $link) { 
30366 if ('composer-plugin-api' === $link->getTarget()) {
30367 $requiresComposer = $link->getConstraint();
30368 break;
30369 }
30370 }
30371
30372 if (!$requiresComposer) {
30373 throw new \RuntimeException("Plugin ".$package->getName()." is missing a require statement for a version of the composer-plugin-api package.");
30374 }
30375
30376 $currentPluginApiVersion = $this->getPluginApiVersion();
30377 $currentPluginApiConstraint = new Constraint('==', $this->versionParser->normalize($currentPluginApiVersion));
30378
30379 if ($requiresComposer->getPrettyString() === '1.0.0' && $this->getPluginApiVersion() === '1.0.0') {
30380 $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>');
30381 } elseif (!$requiresComposer->matches($currentPluginApiConstraint)) {
30382 $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>');
30383
30384 return;
30385 }
30386 }
30387
30388 $oldInstallerPlugin = ($package->getType() === 'composer-installer');
30389
30390 if (in_array($package->getName(), $this->registeredPlugins)) {
30391 return;
30392 }
30393
30394 $extra = $package->getExtra();
30395 if (empty($extra['class'])) {
30396 throw new \UnexpectedValueException('Error while installing '.$package->getPrettyName().', composer-plugin packages should have a class defined in their extra key to be usable.');
30397 }
30398 $classes = is_array($extra['class']) ? $extra['class'] : array($extra['class']);
30399
30400 $localRepo = $this->composer->getRepositoryManager()->getLocalRepository();
30401 $globalRepo = $this->globalComposer ? $this->globalComposer->getRepositoryManager()->getLocalRepository() : null;
30402
30403 $pool = new Pool('dev');
30404 $pool->addRepository($localRepo);
30405 if ($globalRepo) {
30406 $pool->addRepository($globalRepo);
30407 }
30408
30409 $autoloadPackages = array($package->getName() => $package);
30410 $autoloadPackages = $this->collectDependencies($pool, $autoloadPackages, $package);
30411
30412 $generator = $this->composer->getAutoloadGenerator();
30413 $autoloads = array();
30414 foreach ($autoloadPackages as $autoloadPackage) {
30415 $downloadPath = $this->getInstallPath($autoloadPackage, ($globalRepo && $globalRepo->hasPackage($autoloadPackage)));
30416 $autoloads[] = array($autoloadPackage, $downloadPath);
30417 }
30418
30419 $map = $generator->parseAutoloads($autoloads, new Package('dummy', '1.0.0.0', '1.0.0'));
30420 $classLoader = $generator->createLoader($map);
30421 $classLoader->register();
30422
30423 foreach ($classes as $class) {
30424 if (class_exists($class, false)) {
30425 $class = trim($class, '\\');
30426 $path = $classLoader->findFile($class);
30427 $code = file_get_contents($path);
30428 $separatorPos = strrpos($class, '\\');
30429 $className = $class;
30430 if ($separatorPos) {
30431 $className = substr($class, $separatorPos + 1);
30432 }
30433 $code = preg_replace('{^((?:final\s+)?(?:\s*))class\s+('.preg_quote($className).')}mi', '$1class $2_composer_tmp'.self::$classCounter, $code, 1);
30434 $code = str_replace('__FILE__', var_export($path, true), $code);
30435 $code = str_replace('__DIR__', var_export(dirname($path), true), $code);
30436 $code = str_replace('__CLASS__', var_export($class, true), $code);
30437 $code = preg_replace('/^\s*<\?(php)?/i', '', $code, 1);
30438 eval($code);
30439 $class .= '_composer_tmp'.self::$classCounter;
30440 self::$classCounter++;
30441 }
30442
30443 if ($oldInstallerPlugin) {
30444 $installer = new $class($this->io, $this->composer);
30445 $this->composer->getInstallationManager()->addInstaller($installer);
30446 } elseif (class_exists($class)) {
30447 $plugin = new $class();
30448 $this->addPlugin($plugin);
30449 $this->registeredPlugins[] = $package->getName();
30450 } elseif ($failOnMissingClasses) {
30451 throw new \UnexpectedValueException('Plugin '.$package->getName().' could not be initialized, class not found: '.$class);
30452 }
30453 }
30454 }
30455
30456
30457
30458
30459
30460
30461 protected function getPluginApiVersion()
30462 {
30463 return PluginInterface::PLUGIN_API_VERSION;
30464 }
30465
30466
30467
30468
30469
30470
30471
30472
30473
30474
30475 public function addPlugin(PluginInterface $plugin)
30476 {
30477 $this->io->writeError('Loading plugin '.get_class($plugin), true, IOInterface::DEBUG);
30478 $this->plugins[] = $plugin;
30479 $plugin->activate($this->composer, $this->io);
30480
30481 if ($plugin instanceof EventSubscriberInterface) {
30482 $this->composer->getEventDispatcher()->addSubscriber($plugin);
30483 }
30484 }
30485
30486
30487
30488
30489
30490
30491
30492
30493
30494
30495
30496
30497 private function loadRepository(RepositoryInterface $repo)
30498 {
30499 foreach ($repo->getPackages() as $package) { 
30500 if ($package instanceof AliasPackage) {
30501 continue;
30502 }
30503 if ('composer-plugin' === $package->getType()) {
30504 $this->registerPackage($package);
30505
30506  } elseif ('composer-installer' === $package->getType()) {
30507 $this->registerPackage($package);
30508 }
30509 }
30510 }
30511
30512
30513
30514
30515
30516
30517
30518
30519
30520
30521 private function collectDependencies(Pool $pool, array $collected, PackageInterface $package)
30522 {
30523 $requires = array_merge(
30524 $package->getRequires(),
30525 $package->getDevRequires()
30526 );
30527
30528 foreach ($requires as $requireLink) {
30529 $requiredPackage = $this->lookupInstalledPackage($pool, $requireLink);
30530 if ($requiredPackage && !isset($collected[$requiredPackage->getName()])) {
30531 $collected[$requiredPackage->getName()] = $requiredPackage;
30532 $collected = $this->collectDependencies($pool, $collected, $requiredPackage);
30533 }
30534 }
30535
30536 return $collected;
30537 }
30538
30539
30540
30541
30542
30543
30544
30545
30546
30547
30548
30549 private function lookupInstalledPackage(Pool $pool, Link $link)
30550 {
30551 $packages = $pool->whatProvides($link->getTarget(), $link->getConstraint());
30552
30553 return (!empty($packages)) ? $packages[0] : null;
30554 }
30555
30556
30557
30558
30559
30560
30561
30562
30563
30564 private function getInstallPath(PackageInterface $package, $global = false)
30565 {
30566 if (!$global) {
30567 return $this->composer->getInstallationManager()->getInstallPath($package);
30568 }
30569
30570 return $this->globalComposer->getInstallationManager()->getInstallPath($package);
30571 }
30572
30573
30574
30575
30576
30577
30578
30579 protected function getCapabilityImplementationClassName(PluginInterface $plugin, $capability)
30580 {
30581 if (!($plugin instanceof Capable)) {
30582 return null;
30583 }
30584
30585 $capabilities = (array) $plugin->getCapabilities();
30586
30587 if (!empty($capabilities[$capability]) && is_string($capabilities[$capability]) && trim($capabilities[$capability])) {
30588 return trim($capabilities[$capability]);
30589 }
30590
30591 if (
30592 array_key_exists($capability, $capabilities)
30593 && (empty($capabilities[$capability]) || !is_string($capabilities[$capability]) || !trim($capabilities[$capability]))
30594 ) {
30595 throw new \UnexpectedValueException('Plugin '.get_class($plugin).' provided invalid capability class name(s), got '.var_export($capabilities[$capability], 1));
30596 }
30597 }
30598
30599
30600
30601
30602
30603
30604
30605
30606
30607 public function getPluginCapability(PluginInterface $plugin, $capabilityClassName, array $ctorArgs = array())
30608 {
30609 if ($capabilityClass = $this->getCapabilityImplementationClassName($plugin, $capabilityClassName)) {
30610 if (!class_exists($capabilityClass)) {
30611 throw new \RuntimeException("Cannot instantiate Capability, as class $capabilityClass from plugin ".get_class($plugin)." does not exist.");
30612 }
30613
30614 $ctorArgs['plugin'] = $plugin;
30615 $capabilityObj = new $capabilityClass($ctorArgs);
30616
30617
30618  if (!$capabilityObj instanceof Capability || !$capabilityObj instanceof $capabilityClassName) {
30619 throw new \RuntimeException(
30620 'Class ' . $capabilityClass . ' must implement both Composer\Plugin\Capability\Capability and '. $capabilityClassName . '.'
30621 );
30622 }
30623
30624 return $capabilityObj;
30625 }
30626 }
30627
30628
30629
30630
30631
30632
30633
30634
30635 public function getPluginCapabilities($capabilityClassName, array $ctorArgs = array())
30636 {
30637 $capabilities = array();
30638 foreach ($this->getPlugins() as $plugin) {
30639 if ($capability = $this->getPluginCapability($plugin, $capabilityClassName, $ctorArgs)) {
30640 $capabilities[] = $capability;
30641 }
30642 }
30643
30644 return $capabilities;
30645 }
30646 }
30647 <?php
30648
30649
30650
30651
30652
30653
30654
30655
30656
30657
30658
30659 namespace Composer\Plugin;
30660
30661 use Composer\EventDispatcher\Event;
30662 use Composer\Util\RemoteFilesystem;
30663
30664
30665
30666
30667
30668
30669 class PreFileDownloadEvent extends Event
30670 {
30671
30672
30673
30674 private $rfs;
30675
30676
30677
30678
30679 private $processedUrl;
30680
30681
30682
30683
30684
30685
30686
30687
30688 public function __construct($name, RemoteFilesystem $rfs, $processedUrl)
30689 {
30690 parent::__construct($name);
30691 $this->rfs = $rfs;
30692 $this->processedUrl = $processedUrl;
30693 }
30694
30695
30696
30697
30698
30699
30700 public function getRemoteFilesystem()
30701 {
30702 return $this->rfs;
30703 }
30704
30705
30706
30707
30708
30709
30710 public function setRemoteFilesystem(RemoteFilesystem $rfs)
30711 {
30712 $this->rfs = $rfs;
30713 }
30714
30715
30716
30717
30718
30719
30720 public function getProcessedUrl()
30721 {
30722 return $this->processedUrl;
30723 }
30724 }
30725 <?php
30726
30727
30728
30729
30730
30731
30732
30733
30734
30735
30736
30737 namespace Composer\Question;
30738
30739 use Symfony\Component\Console\Exception\InvalidArgumentException;
30740 use Symfony\Component\Console\Question\Question;
30741
30742
30743
30744
30745
30746
30747
30748
30749 class StrictConfirmationQuestion extends Question
30750 {
30751 private $trueAnswerRegex;
30752 private $falseAnswerRegex;
30753
30754
30755
30756
30757
30758
30759
30760
30761
30762 public function __construct($question, $default = true, $trueAnswerRegex = '/^y(?:es)?$/i', $falseAnswerRegex = '/^no?$/i')
30763 {
30764 parent::__construct($question, (bool) $default);
30765
30766 $this->trueAnswerRegex = $trueAnswerRegex;
30767 $this->falseAnswerRegex = $falseAnswerRegex;
30768 $this->setNormalizer($this->getDefaultNormalizer());
30769 $this->setValidator($this->getDefaultValidator());
30770 }
30771
30772
30773
30774
30775
30776
30777 private function getDefaultNormalizer()
30778 {
30779 $default = $this->getDefault();
30780 $trueRegex = $this->trueAnswerRegex;
30781 $falseRegex = $this->falseAnswerRegex;
30782
30783 return function ($answer) use ($default, $trueRegex, $falseRegex) {
30784 if (is_bool($answer)) {
30785 return $answer;
30786 }
30787 if (empty($answer) && !empty($default)) {
30788 return $default;
30789 }
30790
30791 if (preg_match($trueRegex, $answer)) {
30792 return true;
30793 }
30794
30795 if (preg_match($falseRegex, $answer)) {
30796 return false;
30797 }
30798
30799 return null;
30800 };
30801 }
30802
30803
30804
30805
30806
30807
30808 private function getDefaultValidator()
30809 {
30810 return function ($answer) {
30811 if (!is_bool($answer)) {
30812 throw new InvalidArgumentException('Please answer yes, y, no, or n.');
30813 }
30814
30815 return $answer;
30816 };
30817 }
30818 }
30819 <?php
30820
30821
30822
30823
30824
30825
30826
30827
30828
30829
30830
30831 namespace Composer\Repository;
30832
30833 use Composer\Package\AliasPackage;
30834 use Composer\Package\PackageInterface;
30835 use Composer\Package\CompletePackageInterface;
30836 use Composer\Package\Version\VersionParser;
30837 use Composer\Semver\Constraint\ConstraintInterface;
30838 use Composer\Semver\Constraint\Constraint;
30839
30840
30841
30842
30843
30844
30845 class ArrayRepository extends BaseRepository
30846 {
30847
30848 protected $packages;
30849
30850 public function __construct(array $packages = array())
30851 {
30852 foreach ($packages as $package) {
30853 $this->addPackage($package);
30854 }
30855 }
30856
30857
30858
30859
30860 public function findPackage($name, $constraint)
30861 {
30862 $name = strtolower($name);
30863
30864 if (!$constraint instanceof ConstraintInterface) {
30865 $versionParser = new VersionParser();
30866 $constraint = $versionParser->parseConstraints($constraint);
30867 }
30868
30869 foreach ($this->getPackages() as $package) {
30870 if ($name === $package->getName()) {
30871 $pkgConstraint = new Constraint('==', $package->getVersion());
30872 if ($constraint->matches($pkgConstraint)) {
30873 return $package;
30874 }
30875 }
30876 }
30877
30878 return null;
30879 }
30880
30881
30882
30883
30884 public function findPackages($name, $constraint = null)
30885 {
30886
30887  $name = strtolower($name);
30888 $packages = array();
30889
30890 if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
30891 $versionParser = new VersionParser();
30892 $constraint = $versionParser->parseConstraints($constraint);
30893 }
30894
30895 foreach ($this->getPackages() as $package) {
30896 if ($name === $package->getName()) {
30897 $pkgConstraint = new Constraint('==', $package->getVersion());
30898 if (null === $constraint || $constraint->matches($pkgConstraint)) {
30899 $packages[] = $package;
30900 }
30901 }
30902 }
30903
30904 return $packages;
30905 }
30906
30907
30908
30909
30910 public function search($query, $mode = 0, $type = null)
30911 {
30912 $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
30913
30914 $matches = array();
30915 foreach ($this->getPackages() as $package) {
30916 $name = $package->getName();
30917 if (isset($matches[$name])) {
30918 continue;
30919 }
30920 if (preg_match($regex, $name)
30921 || ($mode === self::SEARCH_FULLTEXT && $package instanceof CompletePackageInterface && preg_match($regex, implode(' ', (array) $package->getKeywords()) . ' ' . $package->getDescription()))
30922 ) {
30923 if (null !== $type && $package->getType() !== $type) {
30924 continue;
30925 }
30926
30927 $matches[$name] = array(
30928 'name' => $package->getPrettyName(),
30929 'description' => $package instanceof CompletePackageInterface ? $package->getDescription() : null,
30930 );
30931 }
30932 }
30933
30934 return array_values($matches);
30935 }
30936
30937
30938
30939
30940 public function hasPackage(PackageInterface $package)
30941 {
30942 $packageId = $package->getUniqueName();
30943
30944 foreach ($this->getPackages() as $repoPackage) {
30945 if ($packageId === $repoPackage->getUniqueName()) {
30946 return true;
30947 }
30948 }
30949
30950 return false;
30951 }
30952
30953
30954
30955
30956
30957
30958 public function addPackage(PackageInterface $package)
30959 {
30960 if (null === $this->packages) {
30961 $this->initialize();
30962 }
30963 $package->setRepository($this);
30964 $this->packages[] = $package;
30965
30966 if ($package instanceof AliasPackage) {
30967 $aliasedPackage = $package->getAliasOf();
30968 if (null === $aliasedPackage->getRepository()) {
30969 $this->addPackage($aliasedPackage);
30970 }
30971 }
30972 }
30973
30974 protected function createAliasPackage(PackageInterface $package, $alias, $prettyAlias)
30975 {
30976 return new AliasPackage($package instanceof AliasPackage ? $package->getAliasOf() : $package, $alias, $prettyAlias);
30977 }
30978
30979
30980
30981
30982
30983
30984 public function removePackage(PackageInterface $package)
30985 {
30986 $packageId = $package->getUniqueName();
30987
30988 foreach ($this->getPackages() as $key => $repoPackage) {
30989 if ($packageId === $repoPackage->getUniqueName()) {
30990 array_splice($this->packages, $key, 1);
30991
30992 return;
30993 }
30994 }
30995 }
30996
30997
30998
30999
31000 public function getPackages()
31001 {
31002 if (null === $this->packages) {
31003 $this->initialize();
31004 }
31005
31006 return $this->packages;
31007 }
31008
31009
31010
31011
31012
31013
31014 public function count()
31015 {
31016 return count($this->packages);
31017 }
31018
31019
31020
31021
31022 protected function initialize()
31023 {
31024 $this->packages = array();
31025 }
31026 }
31027 <?php
31028
31029
31030
31031
31032
31033
31034
31035
31036
31037
31038
31039 namespace Composer\Repository;
31040
31041 use Composer\IO\IOInterface;
31042 use Composer\Json\JsonFile;
31043 use Composer\Package\Loader\ArrayLoader;
31044 use Composer\Package\Loader\LoaderInterface;
31045
31046
31047
31048
31049 class ArtifactRepository extends ArrayRepository implements ConfigurableRepositoryInterface
31050 {
31051
31052 protected $loader;
31053
31054 protected $lookup;
31055 protected $repoConfig;
31056 private $io;
31057
31058 public function __construct(array $repoConfig, IOInterface $io)
31059 {
31060 parent::__construct();
31061 if (!extension_loaded('zip')) {
31062 throw new \RuntimeException('The artifact repository requires PHP\'s zip extension');
31063 }
31064
31065 $this->loader = new ArrayLoader();
31066 $this->lookup = $repoConfig['url'];
31067 $this->io = $io;
31068 $this->repoConfig = $repoConfig;
31069 }
31070
31071 public function getRepoConfig()
31072 {
31073 return $this->repoConfig;
31074 }
31075
31076 protected function initialize()
31077 {
31078 parent::initialize();
31079
31080 $this->scanDirectory($this->lookup);
31081 }
31082
31083 private function scanDirectory($path)
31084 {
31085 $io = $this->io;
31086
31087 $directory = new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::FOLLOW_SYMLINKS);
31088 $iterator = new \RecursiveIteratorIterator($directory);
31089 $regex = new \RegexIterator($iterator, '/^.+\.(zip|phar)$/i');
31090 foreach ($regex as $file) {
31091
31092 if (!$file->isFile()) {
31093 continue;
31094 }
31095
31096 $package = $this->getComposerInformation($file);
31097 if (!$package) {
31098 $io->writeError("File <comment>{$file->getBasename()}</comment> doesn't seem to hold a package", true, IOInterface::VERBOSE);
31099 continue;
31100 }
31101
31102 $template = 'Found package <info>%s</info> (<comment>%s</comment>) in file <info>%s</info>';
31103 $io->writeError(sprintf($template, $package->getName(), $package->getPrettyVersion(), $file->getBasename()), true, IOInterface::VERBOSE);
31104
31105 $this->addPackage($package);
31106 }
31107 }
31108
31109
31110
31111
31112
31113
31114
31115
31116 private function locateFile(\ZipArchive $zip, $filename)
31117 {
31118 $indexOfShortestMatch = false;
31119 $lengthOfShortestMatch = -1;
31120
31121 for ($i = 0; $i < $zip->numFiles; $i++) {
31122 $stat = $zip->statIndex($i);
31123 if (strcmp(basename($stat['name']), $filename) === 0) {
31124 $directoryName = dirname($stat['name']);
31125 if ($directoryName == '.') {
31126
31127  
31128  return $i;
31129 }
31130
31131 if (strpos($directoryName, '\\') !== false ||
31132 strpos($directoryName, '/') !== false) {
31133
31134  continue;
31135 }
31136
31137 $length = strlen($stat['name']);
31138 if ($indexOfShortestMatch === false || $length < $lengthOfShortestMatch) {
31139
31140  $contents = $zip->getFromIndex($i);
31141 if ($contents !== false) {
31142 $indexOfShortestMatch = $i;
31143 $lengthOfShortestMatch = $length;
31144 }
31145 }
31146 }
31147 }
31148
31149 return $indexOfShortestMatch;
31150 }
31151
31152 private function getComposerInformation(\SplFileInfo $file)
31153 {
31154 $zip = new \ZipArchive();
31155 $zip->open($file->getPathname());
31156
31157 if (0 == $zip->numFiles) {
31158 return false;
31159 }
31160
31161 $foundFileIndex = $this->locateFile($zip, 'composer.json');
31162 if (false === $foundFileIndex) {
31163 return false;
31164 }
31165
31166 $configurationFileName = $zip->getNameIndex($foundFileIndex);
31167
31168 $composerFile = "zip://{$file->getPathname()}#$configurationFileName";
31169 $json = file_get_contents($composerFile);
31170
31171 $package = JsonFile::parseJson($json, $composerFile);
31172 $package['dist'] = array(
31173 'type' => 'zip',
31174 'url' => strtr($file->getPathname(), '\\', '/'),
31175 'shasum' => sha1_file($file->getRealPath()),
31176 );
31177
31178 try {
31179 $package = $this->loader->load($package);
31180 } catch (\UnexpectedValueException $e) {
31181 throw new \UnexpectedValueException('Failed loading package in '.$file.': '.$e->getMessage(), 0, $e);
31182 }
31183
31184 return $package;
31185 }
31186 }
31187 <?php
31188
31189
31190
31191
31192
31193
31194
31195
31196
31197
31198
31199 namespace Composer\Repository;
31200
31201 use Composer\Package\RootPackageInterface;
31202 use Composer\Semver\Constraint\ConstraintInterface;
31203 use Composer\Semver\Constraint\Constraint;
31204 use Composer\Package\Link;
31205
31206
31207
31208
31209
31210
31211 abstract class BaseRepository implements RepositoryInterface
31212 {
31213
31214
31215
31216
31217
31218
31219
31220
31221
31222
31223
31224
31225
31226 public function getDependents($needle, $constraint = null, $invert = false, $recurse = true, $packagesFound = null)
31227 {
31228 $needles = (array) $needle;
31229 $results = array();
31230
31231
31232  if (null === $packagesFound) {
31233 $packagesFound = $needles;
31234 }
31235
31236
31237  $rootPackage = null;
31238 foreach ($this->getPackages() as $package) {
31239 if ($package instanceof RootPackageInterface) {
31240 $rootPackage = $package;
31241 break;
31242 }
31243 }
31244
31245
31246  foreach ($this->getPackages() as $package) {
31247 $links = $package->getRequires();
31248
31249
31250  
31251  $packagesInTree = $packagesFound;
31252
31253
31254  if (!$invert) {
31255 $links += $package->getReplaces();
31256 }
31257
31258
31259  if ($package instanceof RootPackageInterface) {
31260 $links += $package->getDevRequires();
31261 }
31262
31263
31264  foreach ($links as $link) {
31265 foreach ($needles as $needle) {
31266 if ($link->getTarget() === $needle) {
31267 if (is_null($constraint) || (($link->getConstraint()->matches($constraint) === !$invert))) {
31268
31269  if (in_array($link->getSource(), $packagesInTree)) {
31270 $results[$link->getSource()] = array($package, $link, false);
31271 continue;
31272 }
31273 $packagesInTree[] = $link->getSource();
31274 $dependents = $recurse ? $this->getDependents($link->getSource(), null, false, true, $packagesInTree) : array();
31275 $results[$link->getSource()] = array($package, $link, $dependents);
31276 }
31277 }
31278 }
31279 }
31280
31281
31282  if ($invert && in_array($package->getName(), $needles)) {
31283 foreach ($package->getConflicts() as $link) {
31284 foreach ($this->findPackages($link->getTarget()) as $pkg) {
31285 $version = new Constraint('=', $pkg->getVersion());
31286 if ($link->getConstraint()->matches($version) === $invert) {
31287 $results[] = array($package, $link, false);
31288 }
31289 }
31290 }
31291 }
31292
31293
31294  if ($invert && $constraint && in_array($package->getName(), $needles) && $constraint->matches(new Constraint('=', $package->getVersion()))) {
31295 foreach ($package->getRequires() as $link) {
31296 if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $link->getTarget())) {
31297 if ($this->findPackage($link->getTarget(), $link->getConstraint())) {
31298 continue;
31299 }
31300
31301 $platformPkg = $this->findPackage($link->getTarget(), '*');
31302 $description = $platformPkg ? 'but '.$platformPkg->getPrettyVersion().' is installed' : 'but it is missing';
31303 $results[] = array($package, new Link($package->getName(), $link->getTarget(), null, 'requires', $link->getPrettyConstraint().' '.$description), false);
31304
31305 continue;
31306 }
31307
31308 foreach ($this->getPackages() as $pkg) {
31309 if (!in_array($link->getTarget(), $pkg->getNames())) {
31310 continue;
31311 }
31312
31313 $version = new Constraint('=', $pkg->getVersion());
31314 if (!$link->getConstraint()->matches($version)) {
31315
31316  
31317  if ($rootPackage) {
31318 foreach (array_merge($rootPackage->getRequires(), $rootPackage->getDevRequires()) as $rootReq) {
31319 if (in_array($rootReq->getTarget(), $pkg->getNames()) && !$rootReq->getConstraint()->matches($link->getConstraint())) {
31320 $results[] = array($package, $link, false);
31321 $results[] = array($rootPackage, $rootReq, false);
31322 continue 3;
31323 }
31324 }
31325 $results[] = array($package, $link, false);
31326 $results[] = array($rootPackage, new Link($rootPackage->getName(), $link->getTarget(), null, 'does not require', 'but ' . $pkg->getPrettyVersion() . ' is installed'), false);
31327 } else {
31328
31329  $results[] = array($package, $link, false);
31330 }
31331 }
31332
31333 continue 2;
31334 }
31335 }
31336 }
31337 }
31338
31339 ksort($results);
31340
31341 return $results;
31342 }
31343 }
31344 <?php
31345
31346
31347
31348
31349
31350
31351
31352
31353
31354
31355
31356 namespace Composer\Repository;
31357
31358 use Composer\Package\Loader\ArrayLoader;
31359 use Composer\Package\PackageInterface;
31360 use Composer\Package\AliasPackage;
31361 use Composer\Package\Version\VersionParser;
31362 use Composer\DependencyResolver\Pool;
31363 use Composer\Json\JsonFile;
31364 use Composer\Cache;
31365 use Composer\Config;
31366 use Composer\Factory;
31367 use Composer\IO\IOInterface;
31368 use Composer\Util\RemoteFilesystem;
31369 use Composer\Plugin\PluginEvents;
31370 use Composer\Plugin\PreFileDownloadEvent;
31371 use Composer\EventDispatcher\EventDispatcher;
31372 use Composer\Downloader\TransportException;
31373 use Composer\Semver\Constraint\ConstraintInterface;
31374 use Composer\Semver\Constraint\Constraint;
31375
31376
31377
31378
31379 class ComposerRepository extends ArrayRepository implements ConfigurableRepositoryInterface
31380 {
31381 protected $config;
31382 protected $repoConfig;
31383 protected $options;
31384 protected $url;
31385 protected $baseUrl;
31386 protected $io;
31387 protected $rfs;
31388 protected $cache;
31389 protected $notifyUrl;
31390 protected $searchUrl;
31391 protected $hasProviders = false;
31392 protected $providersUrl;
31393 protected $lazyProvidersUrl;
31394 protected $providerListing;
31395 protected $providers = array();
31396 protected $providersByUid = array();
31397 protected $loader;
31398 protected $rootAliases;
31399 protected $allowSslDowngrade = false;
31400 protected $eventDispatcher;
31401 protected $sourceMirrors;
31402 protected $distMirrors;
31403 private $degradedMode = false;
31404 private $rootData;
31405 private $hasPartialPackages;
31406 private $partialPackagesByName;
31407
31408 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
31409 {
31410 parent::__construct();
31411 if (!preg_match('{^[\w.]+\??://}', $repoConfig['url'])) {
31412
31413  $repoConfig['url'] = 'http://'.$repoConfig['url'];
31414 }
31415 $repoConfig['url'] = rtrim($repoConfig['url'], '/');
31416
31417 if ('https?' === substr($repoConfig['url'], 0, 6)) {
31418 $repoConfig['url'] = (extension_loaded('openssl') ? 'https' : 'http') . substr($repoConfig['url'], 6);
31419 }
31420
31421 $urlBits = parse_url($repoConfig['url']);
31422 if ($urlBits === false || empty($urlBits['scheme'])) {
31423 throw new \UnexpectedValueException('Invalid url given for Composer repository: '.$repoConfig['url']);
31424 }
31425
31426 if (!isset($repoConfig['options'])) {
31427 $repoConfig['options'] = array();
31428 }
31429 if (isset($repoConfig['allow_ssl_downgrade']) && true === $repoConfig['allow_ssl_downgrade']) {
31430 $this->allowSslDowngrade = true;
31431 }
31432
31433 $this->config = $config;
31434 $this->options = $repoConfig['options'];
31435 $this->url = $repoConfig['url'];
31436 $this->baseUrl = rtrim(preg_replace('{(?:/[^/\\\\]+\.json)?(?:[?#].*)?$}', '', $this->url), '/');
31437 $this->io = $io;
31438 $this->cache = new Cache($io, $config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->url), 'a-z0-9.$');
31439 $this->loader = new ArrayLoader();
31440 if ($rfs && $this->options) {
31441 $rfs = clone $rfs;
31442 $rfs->setOptions($this->options);
31443 }
31444 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $this->config, $this->options);
31445 $this->eventDispatcher = $eventDispatcher;
31446 $this->repoConfig = $repoConfig;
31447 }
31448
31449 public function getRepoConfig()
31450 {
31451 return $this->repoConfig;
31452 }
31453
31454 public function setRootAliases(array $rootAliases)
31455 {
31456 $this->rootAliases = $rootAliases;
31457 }
31458
31459
31460
31461
31462 public function findPackage($name, $constraint)
31463 {
31464 if (!$this->hasProviders()) {
31465 return parent::findPackage($name, $constraint);
31466 }
31467
31468 $name = strtolower($name);
31469 if (!$constraint instanceof ConstraintInterface) {
31470 $versionParser = new VersionParser();
31471 $constraint = $versionParser->parseConstraints($constraint);
31472 }
31473
31474 foreach ($this->getProviderNames() as $providerName) {
31475 if ($name === $providerName) {
31476 $packages = $this->whatProvides(new Pool('dev'), $providerName);
31477 foreach ($packages as $package) {
31478 if ($name === $package->getName()) {
31479 $pkgConstraint = new Constraint('==', $package->getVersion());
31480 if ($constraint->matches($pkgConstraint)) {
31481 return $package;
31482 }
31483 }
31484 }
31485 break;
31486 }
31487 }
31488 }
31489
31490
31491
31492
31493 public function findPackages($name, $constraint = null)
31494 {
31495 if (!$this->hasProviders()) {
31496 return parent::findPackages($name, $constraint);
31497 }
31498
31499  $name = strtolower($name);
31500
31501 if (null !== $constraint && !$constraint instanceof ConstraintInterface) {
31502 $versionParser = new VersionParser();
31503 $constraint = $versionParser->parseConstraints($constraint);
31504 }
31505
31506 $packages = array();
31507
31508 foreach ($this->getProviderNames() as $providerName) {
31509 if ($name === $providerName) {
31510 $candidates = $this->whatProvides(new Pool('dev'), $providerName);
31511 foreach ($candidates as $package) {
31512 if ($name === $package->getName()) {
31513 $pkgConstraint = new Constraint('==', $package->getVersion());
31514 if (null === $constraint || $constraint->matches($pkgConstraint)) {
31515 $packages[] = $package;
31516 }
31517 }
31518 }
31519 break;
31520 }
31521 }
31522
31523 return $packages;
31524 }
31525
31526 public function getPackages()
31527 {
31528 if ($this->hasProviders()) {
31529 throw new \LogicException('Composer repositories that have providers can not load the complete list of packages, use getProviderNames instead.');
31530 }
31531
31532 return parent::getPackages();
31533 }
31534
31535
31536
31537
31538 public function search($query, $mode = 0, $type = null)
31539 {
31540 $this->loadRootServerFile();
31541
31542 if ($this->searchUrl && $mode === self::SEARCH_FULLTEXT) {
31543 $url = str_replace(array('%query%', '%type%'), array($query, $type), $this->searchUrl);
31544
31545 $hostname = parse_url($url, PHP_URL_HOST) ?: $url;
31546 $json = $this->rfs->getContents($hostname, $url, false);
31547 $results = JsonFile::parseJson($json, $url);
31548
31549 return $results['results'];
31550 }
31551
31552 if ($this->hasProviders()) {
31553 $results = array();
31554 $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i';
31555
31556 foreach ($this->getProviderNames() as $name) {
31557 if (preg_match($regex, $name)) {
31558 $results[] = array('name' => $name);
31559 }
31560 }
31561
31562 return $results;
31563 }
31564
31565 return parent::search($query, $mode);
31566 }
31567
31568 public function getProviderNames()
31569 {
31570 $this->loadRootServerFile();
31571
31572 if (null === $this->providerListing) {
31573 $this->loadProviderListings($this->loadRootServerFile());
31574 }
31575
31576 if ($this->lazyProvidersUrl) {
31577
31578  return array();
31579 }
31580
31581 if ($this->providersUrl) {
31582 return array_keys($this->providerListing);
31583 }
31584
31585 return array();
31586 }
31587
31588 protected function configurePackageTransportOptions(PackageInterface $package)
31589 {
31590 foreach ($package->getDistUrls() as $url) {
31591 if (strpos($url, $this->baseUrl) === 0) {
31592 $package->setTransportOptions($this->options);
31593
31594 return;
31595 }
31596 }
31597 }
31598
31599 public function hasProviders()
31600 {
31601 $this->loadRootServerFile();
31602
31603 return $this->hasProviders;
31604 }
31605
31606 public function resetPackageIds()
31607 {
31608 foreach ($this->providersByUid as $package) {
31609 if ($package instanceof AliasPackage) {
31610 $package->getAliasOf()->setId(-1);
31611 }
31612 $package->setId(-1);
31613 }
31614 }
31615
31616
31617
31618
31619
31620
31621
31622 public function whatProvides(Pool $pool, $name, $bypassFilters = false)
31623 {
31624 if (isset($this->providers[$name]) && !$bypassFilters) {
31625 return $this->providers[$name];
31626 }
31627
31628 if ($this->hasPartialPackages && null === $this->partialPackagesByName) {
31629 $this->initializePartialPackages();
31630 }
31631
31632 if (!$this->hasPartialPackages || !isset($this->partialPackagesByName[$name])) {
31633
31634  if (preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name) || '__root__' === $name || 'composer-plugin-api' === $name) {
31635 return array();
31636 }
31637
31638 if (null === $this->providerListing) {
31639 $this->loadProviderListings($this->loadRootServerFile());
31640 }
31641
31642 $useLastModifiedCheck = false;
31643 if ($this->lazyProvidersUrl && !isset($this->providerListing[$name])) {
31644 $hash = null;
31645 $url = str_replace('%package%', $name, $this->lazyProvidersUrl);
31646 $cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
31647 $useLastModifiedCheck = true;
31648 } elseif ($this->providersUrl) {
31649
31650  if (!isset($this->providerListing[$name])) {
31651 return array();
31652 }
31653
31654 $hash = $this->providerListing[$name]['sha256'];
31655 $url = str_replace(array('%package%', '%hash%'), array($name, $hash), $this->providersUrl);
31656 $cacheKey = 'provider-'.strtr($name, '/', '$').'.json';
31657 } else {
31658 return array();
31659 }
31660
31661 $packages = null;
31662 if ($cacheKey) {
31663 if (!$useLastModifiedCheck && $hash && $this->cache->sha256($cacheKey) === $hash) {
31664 $packages = json_decode($this->cache->read($cacheKey), true);
31665 } elseif ($useLastModifiedCheck) {
31666 if ($contents = $this->cache->read($cacheKey)) {
31667 $contents = json_decode($contents, true);
31668 if (isset($contents['last-modified'])) {
31669 $response = $this->fetchFileIfLastModified($url, $cacheKey, $contents['last-modified']);
31670 if (true === $response) {
31671 $packages = $contents;
31672 } elseif ($response) {
31673 $packages = $response;
31674 }
31675 }
31676 }
31677 }
31678 }
31679
31680 if (!$packages) {
31681 try {
31682 $packages = $this->fetchFile($url, $cacheKey, $hash, $useLastModifiedCheck);
31683 } catch (TransportException $e) {
31684
31685  if ($e->getStatusCode() === 404 && $this->lazyProvidersUrl) {
31686 $packages = array('packages' => array());
31687 } else {
31688 throw $e;
31689 }
31690 }
31691 }
31692
31693 $loadingPartialPackage = false;
31694 } else {
31695 $packages = array('packages' => array('versions' => $this->partialPackagesByName[$name]));
31696 $loadingPartialPackage = true;
31697 }
31698
31699 $this->providers[$name] = array();
31700 foreach ($packages['packages'] as $versions) {
31701 foreach ($versions as $version) {
31702 if (!$loadingPartialPackage && $this->hasPartialPackages && isset($this->partialPackagesByName[$version['name']])) {
31703 continue;
31704 }
31705
31706
31707  if (isset($this->providersByUid[$version['uid']])) {
31708
31709  if (!isset($this->providers[$name][$version['uid']])) {
31710
31711  if ($this->providersByUid[$version['uid']] instanceof AliasPackage) {
31712 $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']]->getAliasOf();
31713 $this->providers[$name][$version['uid'].'-alias'] = $this->providersByUid[$version['uid']];
31714 } else {
31715 $this->providers[$name][$version['uid']] = $this->providersByUid[$version['uid']];
31716 }
31717
31718  if (isset($this->providersByUid[$version['uid'].'-root'])) {
31719 $this->providers[$name][$version['uid'].'-root'] = $this->providersByUid[$version['uid'].'-root'];
31720 }
31721 }
31722 } else {
31723 if (!$bypassFilters && !$pool->isPackageAcceptable(strtolower($version['name']), VersionParser::parseStability($version['version']))) {
31724 continue;
31725 }
31726
31727
31728  $package = $this->createPackage($version, 'Composer\Package\CompletePackage');
31729 $package->setRepository($this);
31730
31731 if ($package instanceof AliasPackage) {
31732 $aliased = $package->getAliasOf();
31733 $aliased->setRepository($this);
31734
31735 $this->providers[$name][$version['uid']] = $aliased;
31736 $this->providers[$name][$version['uid'].'-alias'] = $package;
31737
31738
31739  $this->providersByUid[$version['uid']] = $package;
31740 } else {
31741 $this->providers[$name][$version['uid']] = $package;
31742 $this->providersByUid[$version['uid']] = $package;
31743 }
31744
31745
31746  unset($rootAliasData);
31747
31748 if (isset($this->rootAliases[$package->getName()][$package->getVersion()])) {
31749 $rootAliasData = $this->rootAliases[$package->getName()][$package->getVersion()];
31750 } elseif ($package instanceof AliasPackage && isset($this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()])) {
31751 $rootAliasData = $this->rootAliases[$package->getName()][$package->getAliasOf()->getVersion()];
31752 }
31753
31754 if (isset($rootAliasData)) {
31755 $alias = $this->createAliasPackage($package, $rootAliasData['alias_normalized'], $rootAliasData['alias']);
31756 $alias->setRepository($this);
31757
31758 $this->providers[$name][$version['uid'].'-root'] = $alias;
31759 $this->providersByUid[$version['uid'].'-root'] = $alias;
31760 }
31761 }
31762 }
31763 }
31764
31765 $result = $this->providers[$name];
31766
31767
31768  
31769  if ($bypassFilters) {
31770 foreach ($this->providers[$name] as $uid => $provider) {
31771 unset($this->providersByUid[$uid]);
31772 }
31773 unset($this->providers[$name]);
31774 }
31775
31776 return $result;
31777 }
31778
31779
31780
31781
31782 protected function initialize()
31783 {
31784 parent::initialize();
31785
31786 $repoData = $this->loadDataFromServer();
31787
31788 foreach ($repoData as $package) {
31789 $this->addPackage($this->createPackage($package, 'Composer\Package\CompletePackage'));
31790 }
31791 }
31792
31793
31794
31795
31796
31797
31798 public function addPackage(PackageInterface $package)
31799 {
31800 parent::addPackage($package);
31801 $this->configurePackageTransportOptions($package);
31802 }
31803
31804 protected function loadRootServerFile()
31805 {
31806 if (null !== $this->rootData) {
31807 return $this->rootData;
31808 }
31809
31810 if (!extension_loaded('openssl') && 'https' === substr($this->url, 0, 5)) {
31811 throw new \RuntimeException('You must enable the openssl extension in your php.ini to load information from '.$this->url);
31812 }
31813
31814 $jsonUrlParts = parse_url($this->url);
31815
31816 if (isset($jsonUrlParts['path']) && false !== strpos($jsonUrlParts['path'], '.json')) {
31817 $jsonUrl = $this->url;
31818 } else {
31819 $jsonUrl = $this->url . '/packages.json';
31820 }
31821
31822 $data = $this->fetchFile($jsonUrl, 'packages.json');
31823
31824 if (!empty($data['notify-batch'])) {
31825 $this->notifyUrl = $this->canonicalizeUrl($data['notify-batch']);
31826 } elseif (!empty($data['notify'])) {
31827 $this->notifyUrl = $this->canonicalizeUrl($data['notify']);
31828 }
31829
31830 if (!empty($data['search'])) {
31831 $this->searchUrl = $this->canonicalizeUrl($data['search']);
31832 }
31833
31834 if (!empty($data['mirrors'])) {
31835 foreach ($data['mirrors'] as $mirror) {
31836 if (!empty($mirror['git-url'])) {
31837 $this->sourceMirrors['git'][] = array('url' => $mirror['git-url'], 'preferred' => !empty($mirror['preferred']));
31838 }
31839 if (!empty($mirror['hg-url'])) {
31840 $this->sourceMirrors['hg'][] = array('url' => $mirror['hg-url'], 'preferred' => !empty($mirror['preferred']));
31841 }
31842 if (!empty($mirror['dist-url'])) {
31843 $this->distMirrors[] = array(
31844 'url' => $this->canonicalizeUrl($mirror['dist-url']),
31845 'preferred' => !empty($mirror['preferred']),
31846 );
31847 }
31848 }
31849 }
31850
31851 if (!empty($data['providers-lazy-url'])) {
31852 $this->lazyProvidersUrl = $this->canonicalizeUrl($data['providers-lazy-url']);
31853 $this->hasProviders = true;
31854
31855 $this->hasPartialPackages = !empty($data['packages']) && is_array($data['packages']);
31856 }
31857
31858 if ($this->allowSslDowngrade) {
31859 $this->url = str_replace('https://', 'http://', $this->url);
31860 $this->baseUrl = str_replace('https://', 'http://', $this->baseUrl);
31861 }
31862
31863 if (!empty($data['providers-url'])) {
31864 $this->providersUrl = $this->canonicalizeUrl($data['providers-url']);
31865 $this->hasProviders = true;
31866 }
31867
31868 if (!empty($data['providers']) || !empty($data['providers-includes'])) {
31869 $this->hasProviders = true;
31870 }
31871
31872
31873  if (preg_match('{^https?://packagist.org/?$}i', $this->url) && !empty($this->repoConfig['force-lazy-providers'])) {
31874 $this->url = 'https://packagist.org';
31875 $this->baseUrl = 'https://packagist.org';
31876 $this->lazyProvidersUrl = $this->canonicalizeUrl('https://packagist.org/p/%package%.json');
31877 $this->providersUrl = null;
31878 } elseif (!empty($this->repoConfig['force-lazy-providers'])) {
31879 $this->lazyProvidersUrl = $this->canonicalizeUrl('/p/%package%.json');
31880 $this->providersUrl = null;
31881 }
31882
31883 return $this->rootData = $data;
31884 }
31885
31886 protected function canonicalizeUrl($url)
31887 {
31888 if ('/' === $url[0]) {
31889 return preg_replace('{(https?://[^/]+).*}i', '$1' . $url, $this->url);
31890 }
31891
31892 return $url;
31893 }
31894
31895 protected function loadDataFromServer()
31896 {
31897 $data = $this->loadRootServerFile();
31898
31899 return $this->loadIncludes($data);
31900 }
31901
31902 protected function loadProviderListings($data)
31903 {
31904 if (isset($data['providers'])) {
31905 if (!is_array($this->providerListing)) {
31906 $this->providerListing = array();
31907 }
31908 $this->providerListing = array_merge($this->providerListing, $data['providers']);
31909 }
31910
31911 if ($this->providersUrl && isset($data['provider-includes'])) {
31912 $includes = $data['provider-includes'];
31913 foreach ($includes as $include => $metadata) {
31914 $url = $this->baseUrl . '/' . str_replace('%hash%', $metadata['sha256'], $include);
31915 $cacheKey = str_replace(array('%hash%','$'), '', $include);
31916 if ($this->cache->sha256($cacheKey) === $metadata['sha256']) {
31917 $includedData = json_decode($this->cache->read($cacheKey), true);
31918 } else {
31919 $includedData = $this->fetchFile($url, $cacheKey, $metadata['sha256']);
31920 }
31921
31922 $this->loadProviderListings($includedData);
31923 }
31924 }
31925 }
31926
31927 protected function loadIncludes($data)
31928 {
31929 $packages = array();
31930
31931
31932  if (!isset($data['packages']) && !isset($data['includes'])) {
31933 foreach ($data as $pkg) {
31934 foreach ($pkg['versions'] as $metadata) {
31935 $packages[] = $metadata;
31936 }
31937 }
31938
31939 return $packages;
31940 }
31941
31942 if (isset($data['packages'])) {
31943 foreach ($data['packages'] as $package => $versions) {
31944 foreach ($versions as $version => $metadata) {
31945 $packages[] = $metadata;
31946 }
31947 }
31948 }
31949
31950 if (isset($data['includes'])) {
31951 foreach ($data['includes'] as $include => $metadata) {
31952 if ($this->cache->sha1($include) === $metadata['sha1']) {
31953 $includedData = json_decode($this->cache->read($include), true);
31954 } else {
31955 $includedData = $this->fetchFile($include);
31956 }
31957 $packages = array_merge($packages, $this->loadIncludes($includedData));
31958 }
31959 }
31960
31961 return $packages;
31962 }
31963
31964 protected function createPackage(array $data, $class = 'Composer\Package\CompletePackage')
31965 {
31966 try {
31967 if (!isset($data['notification-url'])) {
31968 $data['notification-url'] = $this->notifyUrl;
31969 }
31970
31971 $package = $this->loader->load($data, $class);
31972 if (isset($this->sourceMirrors[$package->getSourceType()])) {
31973 $package->setSourceMirrors($this->sourceMirrors[$package->getSourceType()]);
31974 }
31975 $package->setDistMirrors($this->distMirrors);
31976 $this->configurePackageTransportOptions($package);
31977
31978 return $package;
31979 } catch (\Exception $e) {
31980 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);
31981 }
31982 }
31983
31984 protected function fetchFile($filename, $cacheKey = null, $sha256 = null, $storeLastModifiedTime = false)
31985 {
31986 if (null === $cacheKey) {
31987 $cacheKey = $filename;
31988 $filename = $this->baseUrl.'/'.$filename;
31989 }
31990
31991
31992  if (($pos = strpos($filename, '$')) && preg_match('{^https?://.*}i', $filename)) {
31993 $filename = substr($filename, 0, $pos) . '%24' . substr($filename, $pos + 1);
31994 }
31995
31996 $retries = 3;
31997 while ($retries--) {
31998 try {
31999 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename);
32000 if ($this->eventDispatcher) {
32001 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
32002 }
32003
32004 $hostname = parse_url($filename, PHP_URL_HOST) ?: $filename;
32005 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
32006
32007 $json = $rfs->getContents($hostname, $filename, false);
32008 if ($sha256 && $sha256 !== hash('sha256', $json)) {
32009
32010  if ($this->allowSslDowngrade) {
32011 $this->url = str_replace('http://', 'https://', $this->url);
32012 $this->baseUrl = str_replace('http://', 'https://', $this->baseUrl);
32013 $filename = str_replace('http://', 'https://', $filename);
32014 }
32015
32016 if ($retries) {
32017 usleep(100000);
32018
32019 continue;
32020 }
32021
32022
32023  throw new RepositorySecurityException('The contents of '.$filename.' do not match its signature. This should indicate a man-in-the-middle attack. Try running composer again and report this if you think it is a mistake.');
32024 }
32025
32026 $data = JsonFile::parseJson($json, $filename);
32027 if (!empty($data['warning'])) {
32028 $this->io->writeError('<warning>Warning from '.$this->url.': '.$data['warning'].'</warning>');
32029 }
32030 if (!empty($data['info'])) {
32031 $this->io->writeError('<info>Info from '.$this->url.': '.$data['info'].'</info>');
32032 }
32033
32034 if ($cacheKey) {
32035 if ($storeLastModifiedTime) {
32036 $lastModifiedDate = $rfs->findHeaderValue($rfs->getLastHeaders(), 'last-modified');
32037 if ($lastModifiedDate) {
32038 $data['last-modified'] = $lastModifiedDate;
32039 $json = json_encode($data);
32040 }
32041 }
32042 $this->cache->write($cacheKey, $json);
32043 }
32044
32045 break;
32046 } catch (\Exception $e) {
32047 if ($e instanceof TransportException && $e->getStatusCode() === 404) {
32048 throw $e;
32049 }
32050
32051 if ($retries) {
32052 usleep(100000);
32053 continue;
32054 }
32055
32056 if ($e instanceof RepositorySecurityException) {
32057 throw $e;
32058 }
32059
32060 if ($cacheKey && ($contents = $this->cache->read($cacheKey))) {
32061 if (!$this->degradedMode) {
32062 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
32063 $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>');
32064 }
32065 $this->degradedMode = true;
32066 $data = JsonFile::parseJson($contents, $this->cache->getRoot().$cacheKey);
32067
32068 break;
32069 }
32070
32071 throw $e;
32072 }
32073 }
32074
32075 return $data;
32076 }
32077
32078 protected function fetchFileIfLastModified($filename, $cacheKey, $lastModifiedTime)
32079 {
32080 $retries = 3;
32081 while ($retries--) {
32082 try {
32083 $preFileDownloadEvent = new PreFileDownloadEvent(PluginEvents::PRE_FILE_DOWNLOAD, $this->rfs, $filename);
32084 if ($this->eventDispatcher) {
32085 $this->eventDispatcher->dispatch($preFileDownloadEvent->getName(), $preFileDownloadEvent);
32086 }
32087
32088 $hostname = parse_url($filename, PHP_URL_HOST) ?: $filename;
32089 $rfs = $preFileDownloadEvent->getRemoteFilesystem();
32090 $options = array('http' => array('header' => array('If-Modified-Since: '.$lastModifiedTime)));
32091 $json = $rfs->getContents($hostname, $filename, false, $options);
32092 if ($json === '' && $rfs->findStatusCode($rfs->getLastHeaders()) === 304) {
32093 return true;
32094 }
32095
32096 $data = JsonFile::parseJson($json, $filename);
32097 if (!empty($data['warning'])) {
32098 $this->io->writeError('<warning>Warning from '.$this->url.': '.$data['warning'].'</warning>');
32099 }
32100 if (!empty($data['info'])) {
32101 $this->io->writeError('<info>Info from '.$this->url.': '.$data['info'].'</info>');
32102 }
32103
32104 $lastModifiedDate = $rfs->findHeaderValue($rfs->getLastHeaders(), 'last-modified');
32105 if ($lastModifiedDate) {
32106 $data['last-modified'] = $lastModifiedDate;
32107 $json = json_encode($data);
32108 }
32109 $this->cache->write($cacheKey, $json);
32110
32111 return $data;
32112 } catch (\Exception $e) {
32113 if ($e instanceof TransportException && $e->getStatusCode() === 404) {
32114 throw $e;
32115 }
32116
32117 if ($retries) {
32118 usleep(100000);
32119 continue;
32120 }
32121
32122 if (!$this->degradedMode) {
32123 $this->io->writeError('<warning>'.$e->getMessage().'</warning>');
32124 $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>');
32125 }
32126 $this->degradedMode = true;
32127
32128 return true;
32129 }
32130 }
32131 }
32132
32133
32134
32135
32136
32137
32138 private function initializePartialPackages()
32139 {
32140 $rootData = $this->loadRootServerFile();
32141
32142 $this->partialPackagesByName = array();
32143 foreach ($rootData['packages'] as $package => $versions) {
32144 $package = strtolower($package);
32145 foreach ($versions as $version) {
32146 $this->partialPackagesByName[$package][] = $version;
32147 if (!empty($version['provide']) && is_array($version['provide'])) {
32148 foreach ($version['provide'] as $provided => $providedVersion) {
32149 $this->partialPackagesByName[strtolower($provided)][] = $version;
32150 }
32151 }
32152 if (!empty($version['replace']) && is_array($version['replace'])) {
32153 foreach ($version['replace'] as $provided => $providedVersion) {
32154 $this->partialPackagesByName[strtolower($provided)][] = $version;
32155 }
32156 }
32157 }
32158 }
32159
32160
32161  $this->rootData = true;
32162 }
32163 }
32164 <?php
32165
32166
32167
32168
32169
32170
32171
32172
32173
32174
32175
32176 namespace Composer\Repository;
32177
32178 use Composer\Package\PackageInterface;
32179
32180
32181
32182
32183
32184
32185 class CompositeRepository extends BaseRepository
32186 {
32187
32188
32189
32190
32191 private $repositories;
32192
32193
32194
32195
32196
32197 public function __construct(array $repositories)
32198 {
32199 $this->repositories = array();
32200 foreach ($repositories as $repo) {
32201 $this->addRepository($repo);
32202 }
32203 }
32204
32205
32206
32207
32208
32209
32210 public function getRepositories()
32211 {
32212 return $this->repositories;
32213 }
32214
32215
32216
32217
32218 public function hasPackage(PackageInterface $package)
32219 {
32220 foreach ($this->repositories as $repository) {
32221
32222 if ($repository->hasPackage($package)) {
32223 return true;
32224 }
32225 }
32226
32227 return false;
32228 }
32229
32230
32231
32232
32233 public function findPackage($name, $constraint)
32234 {
32235 foreach ($this->repositories as $repository) {
32236
32237 $package = $repository->findPackage($name, $constraint);
32238 if (null !== $package) {
32239 return $package;
32240 }
32241 }
32242
32243 return null;
32244 }
32245
32246
32247
32248
32249 public function findPackages($name, $constraint = null)
32250 {
32251 $packages = array();
32252 foreach ($this->repositories as $repository) {
32253
32254 $packages[] = $repository->findPackages($name, $constraint);
32255 }
32256
32257 return $packages ? call_user_func_array('array_merge', $packages) : array();
32258 }
32259
32260
32261
32262
32263 public function search($query, $mode = 0, $type = null)
32264 {
32265 $matches = array();
32266 foreach ($this->repositories as $repository) {
32267
32268 $matches[] = $repository->search($query, $mode, $type);
32269 }
32270
32271 return $matches ? call_user_func_array('array_merge', $matches) : array();
32272 }
32273
32274
32275
32276
32277 public function getPackages()
32278 {
32279 $packages = array();
32280 foreach ($this->repositories as $repository) {
32281
32282 $packages[] = $repository->getPackages();
32283 }
32284
32285 return $packages ? call_user_func_array('array_merge', $packages) : array();
32286 }
32287
32288
32289
32290
32291 public function removePackage(PackageInterface $package)
32292 {
32293 foreach ($this->repositories as $repository) {
32294
32295 $repository->removePackage($package);
32296 }
32297 }
32298
32299
32300
32301
32302 public function count()
32303 {
32304 $total = 0;
32305 foreach ($this->repositories as $repository) {
32306
32307 $total += $repository->count();
32308 }
32309
32310 return $total;
32311 }
32312
32313
32314
32315
32316
32317 public function addRepository(RepositoryInterface $repository)
32318 {
32319 if ($repository instanceof self) {
32320 foreach ($repository->getRepositories() as $repo) {
32321 $this->addRepository($repo);
32322 }
32323 } else {
32324 $this->repositories[] = $repository;
32325 }
32326 }
32327 }
32328 <?php
32329
32330
32331
32332
32333
32334
32335
32336
32337
32338
32339
32340 namespace Composer\Repository;
32341
32342
32343
32344
32345
32346
32347 interface ConfigurableRepositoryInterface
32348 {
32349 public function getRepoConfig();
32350 }
32351 <?php
32352
32353
32354
32355
32356
32357
32358
32359
32360
32361
32362
32363 namespace Composer\Repository;
32364
32365 use Composer\Json\JsonFile;
32366 use Composer\Package\Loader\ArrayLoader;
32367 use Composer\Package\Dumper\ArrayDumper;
32368
32369
32370
32371
32372
32373
32374
32375 class FilesystemRepository extends WritableArrayRepository
32376 {
32377 private $file;
32378
32379
32380
32381
32382
32383
32384 public function __construct(JsonFile $repositoryFile)
32385 {
32386 parent::__construct();
32387 $this->file = $repositoryFile;
32388 }
32389
32390
32391
32392
32393 protected function initialize()
32394 {
32395 parent::initialize();
32396
32397 if (!$this->file->exists()) {
32398 return;
32399 }
32400
32401 try {
32402 $packages = $this->file->read();
32403
32404 if (!is_array($packages)) {
32405 throw new \UnexpectedValueException('Could not parse package list from the repository');
32406 }
32407 } catch (\Exception $e) {
32408 throw new InvalidRepositoryException('Invalid repository data in '.$this->file->getPath().', packages could not be loaded: ['.get_class($e).'] '.$e->getMessage());
32409 }
32410
32411 $loader = new ArrayLoader(null, true);
32412 foreach ($packages as $packageData) {
32413 $package = $loader->load($packageData);
32414 $this->addPackage($package);
32415 }
32416 }
32417
32418 public function reload()
32419 {
32420 $this->packages = null;
32421 $this->initialize();
32422 }
32423
32424
32425
32426
32427 public function write()
32428 {
32429 $data = array();
32430 $dumper = new ArrayDumper();
32431
32432 foreach ($this->getCanonicalPackages() as $package) {
32433 $data[] = $dumper->dump($package);
32434 }
32435
32436 $this->file->write($data);
32437 }
32438 }
32439 <?php
32440
32441
32442
32443
32444
32445
32446
32447
32448
32449
32450
32451 namespace Composer\Repository;
32452
32453
32454
32455
32456
32457
32458
32459
32460 class InstalledArrayRepository extends WritableArrayRepository implements InstalledRepositoryInterface
32461 {
32462 }
32463 <?php
32464
32465
32466
32467
32468
32469
32470
32471
32472
32473
32474
32475 namespace Composer\Repository;
32476
32477
32478
32479
32480
32481
32482 class InstalledFilesystemRepository extends FilesystemRepository implements InstalledRepositoryInterface
32483 {
32484 }
32485 <?php
32486
32487
32488
32489
32490
32491
32492
32493
32494
32495
32496
32497 namespace Composer\Repository;
32498
32499
32500
32501
32502
32503
32504
32505
32506 interface InstalledRepositoryInterface extends WritableRepositoryInterface
32507 {
32508 }
32509 <?php
32510
32511
32512
32513
32514
32515
32516
32517
32518
32519
32520
32521 namespace Composer\Repository;
32522
32523
32524
32525
32526
32527
32528 class InvalidRepositoryException extends \Exception
32529 {
32530 }
32531 <?php
32532
32533
32534
32535
32536
32537
32538
32539
32540
32541
32542
32543 namespace Composer\Repository;
32544
32545 use Composer\Package\Loader\ArrayLoader;
32546 use Composer\Package\Loader\ValidatingArrayLoader;
32547
32548
32549
32550
32551
32552
32553 class PackageRepository extends ArrayRepository
32554 {
32555 private $config;
32556
32557
32558
32559
32560
32561
32562 public function __construct(array $config)
32563 {
32564 parent::__construct();
32565 $this->config = $config['package'];
32566
32567
32568  if (!is_numeric(key($this->config))) {
32569 $this->config = array($this->config);
32570 }
32571 }
32572
32573
32574
32575
32576 protected function initialize()
32577 {
32578 parent::initialize();
32579
32580 $loader = new ValidatingArrayLoader(new ArrayLoader(null, true), false);
32581 foreach ($this->config as $package) {
32582 try {
32583 $package = $loader->load($package);
32584 } catch (\Exception $e) {
32585 throw new InvalidRepositoryException('A repository of type "package" contains an invalid package definition: '.$e->getMessage()."\n\nInvalid package definition:\n".json_encode($package));
32586 }
32587
32588 $this->addPackage($package);
32589 }
32590 }
32591 }
32592 <?php
32593
32594
32595
32596
32597
32598
32599
32600
32601
32602
32603
32604 namespace Composer\Repository;
32605
32606 use Composer\Config;
32607 use Composer\IO\IOInterface;
32608 use Composer\Json\JsonFile;
32609 use Composer\Package\Loader\ArrayLoader;
32610 use Composer\Package\Version\VersionGuesser;
32611 use Composer\Package\Version\VersionParser;
32612 use Composer\Util\Platform;
32613 use Composer\Util\ProcessExecutor;
32614
32615
32616
32617
32618
32619
32620
32621
32622
32623
32624
32625
32626
32627
32628
32629
32630
32631
32632
32633
32634
32635
32636
32637
32638
32639
32640
32641
32642
32643
32644
32645
32646
32647
32648
32649
32650 class PathRepository extends ArrayRepository implements ConfigurableRepositoryInterface
32651 {
32652
32653
32654
32655 private $loader;
32656
32657
32658
32659
32660 private $versionGuesser;
32661
32662
32663
32664
32665 private $url;
32666
32667
32668
32669
32670 private $repoConfig;
32671
32672
32673
32674
32675 private $process;
32676
32677
32678
32679
32680 private $options;
32681
32682
32683
32684
32685
32686
32687
32688
32689 public function __construct(array $repoConfig, IOInterface $io, Config $config)
32690 {
32691 if (!isset($repoConfig['url'])) {
32692 throw new \RuntimeException('You must specify the `url` configuration for the path repository');
32693 }
32694
32695 $this->loader = new ArrayLoader(null, true);
32696 $this->url = Platform::expandPath($repoConfig['url']);
32697 $this->process = new ProcessExecutor($io);
32698 $this->versionGuesser = new VersionGuesser($config, $this->process, new VersionParser());
32699 $this->repoConfig = $repoConfig;
32700 $this->options = isset($repoConfig['options']) ? $repoConfig['options'] : array();
32701
32702 parent::__construct();
32703 }
32704
32705 public function getRepoConfig()
32706 {
32707 return $this->repoConfig;
32708 }
32709
32710
32711
32712
32713
32714
32715 protected function initialize()
32716 {
32717 parent::initialize();
32718
32719 foreach ($this->getUrlMatches() as $url) {
32720 $path = realpath($url) . DIRECTORY_SEPARATOR;
32721 $composerFilePath = $path.'composer.json';
32722
32723 if (!file_exists($composerFilePath)) {
32724 continue;
32725 }
32726
32727 $json = file_get_contents($composerFilePath);
32728 $package = JsonFile::parseJson($json, $composerFilePath);
32729 $package['dist'] = array(
32730 'type' => 'path',
32731 'url' => $url,
32732 'reference' => sha1($json . serialize($this->options)),
32733 );
32734 $package['transport-options'] = $this->options;
32735
32736
32737  if (!isset($package['version']) && ($rootVersion = getenv('COMPOSER_ROOT_VERSION'))) {
32738 if (
32739 0 === $this->process->execute('git rev-parse HEAD', $ref1, $path)
32740 && 0 === $this->process->execute('git rev-parse HEAD', $ref2)
32741 && $ref1 === $ref2
32742 ) {
32743 $package['version'] = $rootVersion;
32744 }
32745 }
32746
32747 if (!isset($package['version'])) {
32748 $versionData = $this->versionGuesser->guessVersion($package, $path);
32749 $package['version'] = $versionData['version'] ?: 'dev-master';
32750 }
32751
32752 $output = '';
32753 if (is_dir($path . DIRECTORY_SEPARATOR . '.git') && 0 === $this->process->execute('git log -n1 --pretty=%H', $output, $path)) {
32754 $package['dist']['reference'] = trim($output);
32755 }
32756 $package = $this->loader->load($package);
32757 $this->addPackage($package);
32758 }
32759 }
32760
32761
32762
32763
32764
32765
32766 private function getUrlMatches()
32767 {
32768
32769  return array_map(function ($val) {
32770 return rtrim(str_replace(DIRECTORY_SEPARATOR, '/', $val), '/');
32771 }, glob($this->url, GLOB_MARK | GLOB_ONLYDIR));
32772 }
32773 }
32774 <?php
32775
32776
32777
32778
32779
32780
32781
32782
32783
32784
32785
32786 namespace Composer\Repository\Pear;
32787
32788 use Composer\Util\RemoteFilesystem;
32789
32790
32791
32792
32793
32794
32795
32796
32797 abstract class BaseChannelReader
32798 {
32799
32800
32801
32802 const CHANNEL_NS = 'http://pear.php.net/channel-1.0';
32803 const ALL_CATEGORIES_NS = 'http://pear.php.net/dtd/rest.allcategories';
32804 const CATEGORY_PACKAGES_INFO_NS = 'http://pear.php.net/dtd/rest.categorypackageinfo';
32805 const ALL_PACKAGES_NS = 'http://pear.php.net/dtd/rest.allpackages';
32806 const ALL_RELEASES_NS = 'http://pear.php.net/dtd/rest.allreleases';
32807 const PACKAGE_INFO_NS = 'http://pear.php.net/dtd/rest.package';
32808
32809
32810 private $rfs;
32811
32812 protected function __construct(RemoteFilesystem $rfs)
32813 {
32814 $this->rfs = $rfs;
32815 }
32816
32817
32818
32819
32820
32821
32822
32823
32824
32825 protected function requestContent($origin, $path)
32826 {
32827 $url = rtrim($origin, '/') . '/' . ltrim($path, '/');
32828 $content = $this->rfs->getContents($origin, $url, false);
32829 if (!$content) {
32830 throw new \UnexpectedValueException('The PEAR channel at ' . $url . ' did not respond.');
32831 }
32832
32833 return str_replace('http://pear.php.net/rest/', 'https://pear.php.net/rest/', $content);
32834 }
32835
32836
32837
32838
32839
32840
32841
32842
32843
32844 protected function requestXml($origin, $path)
32845 {
32846
32847  $xml = simplexml_load_string($this->requestContent($origin, $path), "SimpleXMLElement", LIBXML_NOERROR);
32848
32849 if (false === $xml) {
32850 throw new \UnexpectedValueException(sprintf('The PEAR channel at ' . $origin . ' is broken. (Invalid XML at file `%s`)', $path));
32851 }
32852
32853 return $xml;
32854 }
32855 }
32856 <?php
32857
32858
32859
32860
32861
32862
32863
32864
32865
32866
32867
32868 namespace Composer\Repository\Pear;
32869
32870
32871
32872
32873
32874
32875 class ChannelInfo
32876 {
32877 private $name;
32878 private $alias;
32879 private $packages;
32880
32881
32882
32883
32884
32885
32886 public function __construct($name, $alias, array $packages)
32887 {
32888 $this->name = $name;
32889 $this->alias = $alias;
32890 $this->packages = $packages;
32891 }
32892
32893
32894
32895
32896
32897
32898 public function getName()
32899 {
32900 return $this->name;
32901 }
32902
32903
32904
32905
32906
32907
32908 public function getAlias()
32909 {
32910 return $this->alias;
32911 }
32912
32913
32914
32915
32916
32917
32918 public function getPackages()
32919 {
32920 return $this->packages;
32921 }
32922 }
32923 <?php
32924
32925
32926
32927
32928
32929
32930
32931
32932
32933
32934
32935 namespace Composer\Repository\Pear;
32936
32937 use Composer\Util\RemoteFilesystem;
32938
32939
32940
32941
32942
32943
32944
32945
32946 class ChannelReader extends BaseChannelReader
32947 {
32948
32949 private $readerMap;
32950
32951 public function __construct(RemoteFilesystem $rfs)
32952 {
32953 parent::__construct($rfs);
32954
32955 $rest10reader = new ChannelRest10Reader($rfs);
32956 $rest11reader = new ChannelRest11Reader($rfs);
32957
32958 $this->readerMap = array(
32959 'REST1.3' => $rest11reader,
32960 'REST1.2' => $rest11reader,
32961 'REST1.1' => $rest11reader,
32962 'REST1.0' => $rest10reader,
32963 );
32964 }
32965
32966
32967
32968
32969
32970
32971
32972
32973 public function read($url)
32974 {
32975 $xml = $this->requestXml($url, "/channel.xml");
32976
32977 $channelName = (string) $xml->name;
32978 $channelAlias = (string) $xml->suggestedalias;
32979
32980 $supportedVersions = array_keys($this->readerMap);
32981 $selectedRestVersion = $this->selectRestVersion($xml, $supportedVersions);
32982 if (!$selectedRestVersion) {
32983 throw new \UnexpectedValueException(sprintf('PEAR repository %s does not supports any of %s protocols.', $url, implode(', ', $supportedVersions)));
32984 }
32985
32986 $reader = $this->readerMap[$selectedRestVersion['version']];
32987 $packageDefinitions = $reader->read($selectedRestVersion['baseUrl']);
32988
32989 return new ChannelInfo($channelName, $channelAlias, $packageDefinitions);
32990 }
32991
32992
32993
32994
32995
32996
32997
32998
32999 private function selectRestVersion($channelXml, $supportedVersions)
33000 {
33001 $channelXml->registerXPathNamespace('ns', self::CHANNEL_NS);
33002
33003 foreach ($supportedVersions as $version) {
33004 $xpathTest = "ns:servers/ns:*/ns:rest/ns:baseurl[@type='{$version}']";
33005 $testResult = $channelXml->xpath($xpathTest);
33006
33007 foreach ($testResult as $result) {
33008
33009  $result = (string) $result;
33010 if (preg_match('{^https://}i', $result)) {
33011 return array('version' => $version, 'baseUrl' => $result);
33012 }
33013 }
33014
33015
33016  if (count($testResult) > 0) {
33017 return array('version' => $version, 'baseUrl' => (string) $testResult[0]);
33018 }
33019 }
33020
33021 return null;
33022 }
33023 }
33024 <?php
33025
33026
33027
33028
33029
33030
33031
33032
33033
33034
33035
33036 namespace Composer\Repository\Pear;
33037
33038 use Composer\Downloader\TransportException;
33039
33040
33041
33042
33043
33044
33045
33046
33047
33048
33049
33050
33051 class ChannelRest10Reader extends BaseChannelReader
33052 {
33053 private $dependencyReader;
33054
33055 public function __construct($rfs)
33056 {
33057 parent::__construct($rfs);
33058
33059 $this->dependencyReader = new PackageDependencyParser();
33060 }
33061
33062
33063
33064
33065
33066
33067
33068
33069 public function read($baseUrl)
33070 {
33071 return $this->readPackages($baseUrl);
33072 }
33073
33074
33075
33076
33077
33078
33079
33080
33081 private function readPackages($baseUrl)
33082 {
33083 $result = array();
33084
33085 $xmlPath = '/p/packages.xml';
33086 $xml = $this->requestXml($baseUrl, $xmlPath);
33087 $xml->registerXPathNamespace('ns', self::ALL_PACKAGES_NS);
33088 foreach ($xml->xpath('ns:p') as $node) {
33089 $packageName = (string) $node;
33090 $packageInfo = $this->readPackage($baseUrl, $packageName);
33091 $result[] = $packageInfo;
33092 }
33093
33094 return $result;
33095 }
33096
33097
33098
33099
33100
33101
33102
33103
33104
33105 private function readPackage($baseUrl, $packageName)
33106 {
33107 $xmlPath = '/p/' . strtolower($packageName) . '/info.xml';
33108 $xml = $this->requestXml($baseUrl, $xmlPath);
33109 $xml->registerXPathNamespace('ns', self::PACKAGE_INFO_NS);
33110
33111 $channelName = (string) $xml->c;
33112 $packageName = (string) $xml->n;
33113 $license = (string) $xml->l;
33114 $shortDescription = (string) $xml->s;
33115 $description = (string) $xml->d;
33116
33117 return new PackageInfo(
33118 $channelName,
33119 $packageName,
33120 $license,
33121 $shortDescription,
33122 $description,
33123 $this->readPackageReleases($baseUrl, $packageName)
33124 );
33125 }
33126
33127
33128
33129
33130
33131
33132
33133
33134
33135
33136 private function readPackageReleases($baseUrl, $packageName)
33137 {
33138 $result = array();
33139
33140 try {
33141 $xmlPath = '/r/' . strtolower($packageName) . '/allreleases.xml';
33142 $xml = $this->requestXml($baseUrl, $xmlPath);
33143 $xml->registerXPathNamespace('ns', self::ALL_RELEASES_NS);
33144 foreach ($xml->xpath('ns:r') as $node) {
33145 $releaseVersion = (string) $node->v;
33146 $releaseStability = (string) $node->s;
33147
33148 try {
33149 $result[$releaseVersion] = new ReleaseInfo(
33150 $releaseStability,
33151 $this->readPackageReleaseDependencies($baseUrl, $packageName, $releaseVersion)
33152 );
33153 } catch (TransportException $exception) {
33154 if ($exception->getCode() != 404) {
33155 throw $exception;
33156 }
33157 }
33158 }
33159 } catch (TransportException $exception) {
33160 if ($exception->getCode() != 404) {
33161 throw $exception;
33162 }
33163 }
33164
33165 return $result;
33166 }
33167
33168
33169
33170
33171
33172
33173
33174
33175
33176
33177 private function readPackageReleaseDependencies($baseUrl, $packageName, $version)
33178 {
33179 $dependencyReader = new PackageDependencyParser();
33180
33181 $depthPath = '/r/' . strtolower($packageName) . '/deps.' . $version . '.txt';
33182 $content = $this->requestContent($baseUrl, $depthPath);
33183 $dependencyArray = unserialize($content);
33184 $result = $dependencyReader->buildDependencyInfo($dependencyArray);
33185
33186 return $result;
33187 }
33188 }
33189 <?php
33190
33191
33192
33193
33194
33195
33196
33197
33198
33199
33200
33201 namespace Composer\Repository\Pear;
33202
33203
33204
33205
33206
33207
33208
33209
33210
33211
33212 class ChannelRest11Reader extends BaseChannelReader
33213 {
33214 private $dependencyReader;
33215
33216 public function __construct($rfs)
33217 {
33218 parent::__construct($rfs);
33219
33220 $this->dependencyReader = new PackageDependencyParser();
33221 }
33222
33223
33224
33225
33226
33227
33228
33229
33230 public function read($baseUrl)
33231 {
33232 return $this->readChannelPackages($baseUrl);
33233 }
33234
33235
33236
33237
33238
33239
33240
33241
33242 private function readChannelPackages($baseUrl)
33243 {
33244 $result = array();
33245
33246 $xml = $this->requestXml($baseUrl, "/c/categories.xml");
33247 $xml->registerXPathNamespace('ns', self::ALL_CATEGORIES_NS);
33248 foreach ($xml->xpath('ns:c') as $node) {
33249 $categoryName = (string) $node;
33250 $categoryPackages = $this->readCategoryPackages($baseUrl, $categoryName);
33251 $result = array_merge($result, $categoryPackages);
33252 }
33253
33254 return $result;
33255 }
33256
33257
33258
33259
33260
33261
33262
33263
33264
33265 private function readCategoryPackages($baseUrl, $categoryName)
33266 {
33267 $result = array();
33268
33269 $categoryPath = '/c/'.urlencode($categoryName).'/packagesinfo.xml';
33270 $xml = $this->requestXml($baseUrl, $categoryPath);
33271 $xml->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
33272 foreach ($xml->xpath('ns:pi') as $node) {
33273 $packageInfo = $this->parsePackage($node);
33274 $result[] = $packageInfo;
33275 }
33276
33277 return $result;
33278 }
33279
33280
33281
33282
33283
33284
33285
33286 private function parsePackage($packageInfo)
33287 {
33288 $packageInfo->registerXPathNamespace('ns', self::CATEGORY_PACKAGES_INFO_NS);
33289 $channelName = (string) $packageInfo->p->c;
33290 $packageName = (string) $packageInfo->p->n;
33291 $license = (string) $packageInfo->p->l;
33292 $shortDescription = (string) $packageInfo->p->s;
33293 $description = (string) $packageInfo->p->d;
33294
33295 $dependencies = array();
33296 foreach ($packageInfo->xpath('ns:deps') as $node) {
33297 $dependencyVersion = (string) $node->v;
33298 $dependencyArray = unserialize((string) $node->d);
33299
33300 $dependencyInfo = $this->dependencyReader->buildDependencyInfo($dependencyArray);
33301
33302 $dependencies[$dependencyVersion] = $dependencyInfo;
33303 }
33304
33305 $releases = array();
33306 $releasesInfo = $packageInfo->xpath('ns:a/ns:r');
33307 if ($releasesInfo) {
33308 foreach ($releasesInfo as $node) {
33309 $releaseVersion = (string) $node->v;
33310 $releaseStability = (string) $node->s;
33311 $releases[$releaseVersion] = new ReleaseInfo(
33312 $releaseStability,
33313 isset($dependencies[$releaseVersion]) ? $dependencies[$releaseVersion] : new DependencyInfo(array(), array())
33314 );
33315 }
33316 }
33317
33318 return new PackageInfo(
33319 $channelName,
33320 $packageName,
33321 $license,
33322 $shortDescription,
33323 $description,
33324 $releases
33325 );
33326 }
33327 }
33328 <?php
33329
33330
33331
33332
33333
33334
33335
33336
33337
33338
33339
33340 namespace Composer\Repository\Pear;
33341
33342
33343
33344
33345
33346
33347 class DependencyConstraint
33348 {
33349 private $type;
33350 private $constraint;
33351 private $channelName;
33352 private $packageName;
33353
33354
33355
33356
33357
33358
33359
33360 public function __construct($type, $constraint, $channelName, $packageName)
33361 {
33362 $this->type = $type;
33363 $this->constraint = $constraint;
33364 $this->channelName = $channelName;
33365 $this->packageName = $packageName;
33366 }
33367
33368 public function getChannelName()
33369 {
33370 return $this->channelName;
33371 }
33372
33373 public function getConstraint()
33374 {
33375 return $this->constraint;
33376 }
33377
33378 public function getPackageName()
33379 {
33380 return $this->packageName;
33381 }
33382
33383 public function getType()
33384 {
33385 return $this->type;
33386 }
33387 }
33388 <?php
33389
33390
33391
33392
33393
33394
33395
33396
33397
33398
33399
33400 namespace Composer\Repository\Pear;
33401
33402
33403
33404
33405
33406
33407 class DependencyInfo
33408 {
33409 private $requires;
33410 private $optionals;
33411
33412
33413
33414
33415
33416 public function __construct($requires, $optionals)
33417 {
33418 $this->requires = $requires;
33419 $this->optionals = $optionals;
33420 }
33421
33422
33423
33424
33425 public function getRequires()
33426 {
33427 return $this->requires;
33428 }
33429
33430
33431
33432
33433 public function getOptionals()
33434 {
33435 return $this->optionals;
33436 }
33437 }
33438 <?php
33439
33440
33441
33442
33443
33444
33445
33446
33447
33448
33449
33450 namespace Composer\Repository\Pear;
33451
33452
33453
33454
33455
33456
33457 class PackageDependencyParser
33458 {
33459
33460
33461
33462
33463
33464
33465 public function buildDependencyInfo($depArray)
33466 {
33467 if (!is_array($depArray)) {
33468 return new DependencyInfo(array(), array());
33469 }
33470 if (!$this->isHash($depArray)) {
33471 return new DependencyInfo($this->buildDependency10Info($depArray), array());
33472 }
33473
33474 return $this->buildDependency20Info($depArray);
33475 }
33476
33477
33478
33479
33480
33481
33482
33483
33484
33485
33486
33487
33488
33489 private function buildDependency10Info($depArray)
33490 {
33491 static $dep10toOperatorMap = array('has' => '==', 'eq' => '==', 'ge' => '>=', 'gt' => '>', 'le' => '<=', 'lt' => '<', 'not' => '!=');
33492
33493 $result = array();
33494
33495 foreach ($depArray as $depItem) {
33496 if (empty($depItem['rel']) || !array_key_exists($depItem['rel'], $dep10toOperatorMap)) {
33497
33498  continue;
33499 }
33500
33501 $depType = !empty($depItem['optional']) && 'yes' == $depItem['optional']
33502 ? 'optional'
33503 : 'required';
33504 $depType = 'not' == $depItem['rel']
33505 ? 'conflicts'
33506 : $depType;
33507
33508 $depVersion = !empty($depItem['version']) ? $this->parseVersion($depItem['version']) : '*';
33509
33510
33511  $depVersionConstraint = ('has' == $depItem['rel'] || 'not' == $depItem['rel']) && '*' == $depVersion
33512 ? '*'
33513 : $dep10toOperatorMap[$depItem['rel']] . $depVersion;
33514
33515 switch ($depItem['type']) {
33516 case 'php':
33517 $depChannelName = 'php';
33518 $depPackageName = '';
33519 break;
33520 case 'pkg':
33521 $depChannelName = !empty($depItem['channel']) ? $depItem['channel'] : 'pear.php.net';
33522 $depPackageName = $depItem['name'];
33523 break;
33524 case 'ext':
33525 $depChannelName = 'ext';
33526 $depPackageName = $depItem['name'];
33527 break;
33528 case 'os':
33529 case 'sapi':
33530 $depChannelName = '';
33531 $depPackageName = '';
33532 break;
33533 default:
33534 $depChannelName = '';
33535 $depPackageName = '';
33536 break;
33537 }
33538
33539 if ('' != $depChannelName) {
33540 $result[] = new DependencyConstraint(
33541 $depType,
33542 $depVersionConstraint,
33543 $depChannelName,
33544 $depPackageName
33545 );
33546 }
33547 }
33548
33549 return $result;
33550 }
33551
33552
33553
33554
33555
33556
33557
33558 private function buildDependency20Info($depArray)
33559 {
33560 $result = array();
33561 $optionals = array();
33562 $defaultOptionals = array();
33563 foreach ($depArray as $depType => $depTypeGroup) {
33564 if (!is_array($depTypeGroup)) {
33565 continue;
33566 }
33567 if ('required' == $depType || 'optional' == $depType) {
33568 foreach ($depTypeGroup as $depItemType => $depItem) {
33569 switch ($depItemType) {
33570 case 'php':
33571 $result[] = new DependencyConstraint(
33572 $depType,
33573 $this->parse20VersionConstraint($depItem),
33574 'php',
33575 ''
33576 );
33577 break;
33578 case 'package':
33579 $deps = $this->buildDepPackageConstraints($depItem, $depType);
33580 $result = array_merge($result, $deps);
33581 break;
33582 case 'extension':
33583 $deps = $this->buildDepExtensionConstraints($depItem, $depType);
33584 $result = array_merge($result, $deps);
33585 break;
33586 case 'subpackage':
33587 $deps = $this->buildDepPackageConstraints($depItem, 'replaces');
33588 $defaultOptionals += $deps;
33589 break;
33590 case 'os':
33591 case 'pearinstaller':
33592 break;
33593 default:
33594 break;
33595 }
33596 }
33597 } elseif ('group' == $depType) {
33598 if ($this->isHash($depTypeGroup)) {
33599 $depTypeGroup = array($depTypeGroup);
33600 }
33601
33602 foreach ($depTypeGroup as $depItem) {
33603 $groupName = $depItem['attribs']['name'];
33604 if (!isset($optionals[$groupName])) {
33605 $optionals[$groupName] = array();
33606 }
33607
33608 if (isset($depItem['subpackage'])) {
33609 $optionals[$groupName] += $this->buildDepPackageConstraints($depItem['subpackage'], 'replaces');
33610 } else {
33611 $result += $this->buildDepPackageConstraints($depItem['package'], 'optional');
33612 }
33613 }
33614 }
33615 }
33616
33617 if (count($defaultOptionals) > 0) {
33618 $optionals['*'] = $defaultOptionals;
33619 }
33620
33621 return new DependencyInfo($result, $optionals);
33622 }
33623
33624
33625
33626
33627
33628
33629
33630
33631 private function buildDepExtensionConstraints($depItem, $depType)
33632 {
33633 if ($this->isHash($depItem)) {
33634 $depItem = array($depItem);
33635 }
33636
33637 $result = array();
33638 foreach ($depItem as $subDepItem) {
33639 $depChannelName = 'ext';
33640 $depPackageName = $subDepItem['name'];
33641 $depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
33642
33643 $result[] = new DependencyConstraint(
33644 $depType,
33645 $depVersionConstraint,
33646 $depChannelName,
33647 $depPackageName
33648 );
33649 }
33650
33651 return $result;
33652 }
33653
33654
33655
33656
33657
33658
33659
33660
33661 private function buildDepPackageConstraints($depItem, $depType)
33662 {
33663 if ($this->isHash($depItem)) {
33664 $depItem = array($depItem);
33665 }
33666
33667 $result = array();
33668 foreach ($depItem as $subDepItem) {
33669 if (!array_key_exists('channel', $subDepItem)) {
33670 $subDepItem['channel'] = $subDepItem['uri'];
33671 }
33672 $depChannelName = $subDepItem['channel'];
33673 $depPackageName = $subDepItem['name'];
33674 $depVersionConstraint = $this->parse20VersionConstraint($subDepItem);
33675 if (isset($subDepItem['conflicts'])) {
33676 $depType = 'conflicts';
33677 }
33678
33679 $result[] = new DependencyConstraint(
33680 $depType,
33681 $depVersionConstraint,
33682 $depChannelName,
33683 $depPackageName
33684 );
33685 }
33686
33687 return $result;
33688 }
33689
33690
33691
33692
33693
33694
33695
33696 private function parse20VersionConstraint(array $data)
33697 {
33698 static $dep20toOperatorMap = array('has' => '==', 'min' => '>=', 'max' => '<=', 'exclude' => '!=');
33699
33700 $versions = array();
33701 $values = array_intersect_key($data, $dep20toOperatorMap);
33702 if (0 == count($values)) {
33703 return '*';
33704 }
33705 if (isset($values['min']) && isset($values['exclude']) && $data['min'] == $data['exclude']) {
33706 $versions[] = '>' . $this->parseVersion($values['min']);
33707 } elseif (isset($values['max']) && isset($values['exclude']) && $data['max'] == $data['exclude']) {
33708 $versions[] = '<' . $this->parseVersion($values['max']);
33709 } else {
33710 foreach ($values as $op => $version) {
33711 if ('exclude' == $op && is_array($version)) {
33712 foreach ($version as $versionPart) {
33713 $versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($versionPart);
33714 }
33715 } else {
33716 $versions[] = $dep20toOperatorMap[$op] . $this->parseVersion($version);
33717 }
33718 }
33719 }
33720
33721 return implode(',', $versions);
33722 }
33723
33724
33725
33726
33727
33728
33729
33730 private function parseVersion($version)
33731 {
33732 if (preg_match('{^v?(\d{1,3})(\.\d+)?(\.\d+)?(\.\d+)?}i', $version, $matches)) {
33733 $version = $matches[1]
33734 .(!empty($matches[2]) ? $matches[2] : '.0')
33735 .(!empty($matches[3]) ? $matches[3] : '.0')
33736 .(!empty($matches[4]) ? $matches[4] : '.0');
33737
33738 return $version;
33739 }
33740
33741 return null;
33742 }
33743
33744
33745
33746
33747
33748
33749
33750 private function isHash(array $array)
33751 {
33752 return !array_key_exists(1, $array) && !array_key_exists(0, $array);
33753 }
33754 }
33755 <?php
33756
33757
33758
33759
33760
33761
33762
33763
33764
33765
33766
33767 namespace Composer\Repository\Pear;
33768
33769
33770
33771
33772
33773
33774 class PackageInfo
33775 {
33776 private $channelName;
33777 private $packageName;
33778 private $license;
33779 private $shortDescription;
33780 private $description;
33781 private $releases;
33782
33783
33784
33785
33786
33787
33788
33789
33790
33791 public function __construct($channelName, $packageName, $license, $shortDescription, $description, $releases)
33792 {
33793 $this->channelName = $channelName;
33794 $this->packageName = $packageName;
33795 $this->license = $license;
33796 $this->shortDescription = $shortDescription;
33797 $this->description = $description;
33798 $this->releases = $releases;
33799 }
33800
33801
33802
33803
33804 public function getChannelName()
33805 {
33806 return $this->channelName;
33807 }
33808
33809
33810
33811
33812 public function getPackageName()
33813 {
33814 return $this->packageName;
33815 }
33816
33817
33818
33819
33820 public function getDescription()
33821 {
33822 return $this->description;
33823 }
33824
33825
33826
33827
33828 public function getShortDescription()
33829 {
33830 return $this->shortDescription;
33831 }
33832
33833
33834
33835
33836 public function getLicense()
33837 {
33838 return $this->license;
33839 }
33840
33841
33842
33843
33844 public function getReleases()
33845 {
33846 return $this->releases;
33847 }
33848 }
33849 <?php
33850
33851
33852
33853
33854
33855
33856
33857
33858
33859
33860
33861 namespace Composer\Repository\Pear;
33862
33863
33864
33865
33866
33867
33868 class ReleaseInfo
33869 {
33870 private $stability;
33871 private $dependencyInfo;
33872
33873
33874
33875
33876
33877 public function __construct($stability, $dependencyInfo)
33878 {
33879 $this->stability = $stability;
33880 $this->dependencyInfo = $dependencyInfo;
33881 }
33882
33883
33884
33885
33886 public function getDependencyInfo()
33887 {
33888 return $this->dependencyInfo;
33889 }
33890
33891
33892
33893
33894 public function getStability()
33895 {
33896 return $this->stability;
33897 }
33898 }
33899 <?php
33900
33901
33902
33903
33904
33905
33906
33907
33908
33909
33910
33911 namespace Composer\Repository;
33912
33913 use Composer\IO\IOInterface;
33914 use Composer\Semver\VersionParser as SemverVersionParser;
33915 use Composer\Package\Version\VersionParser;
33916 use Composer\Repository\Pear\ChannelReader;
33917 use Composer\Package\CompletePackage;
33918 use Composer\Repository\Pear\ChannelInfo;
33919 use Composer\EventDispatcher\EventDispatcher;
33920 use Composer\Package\Link;
33921 use Composer\Semver\Constraint\Constraint;
33922 use Composer\Util\RemoteFilesystem;
33923 use Composer\Config;
33924 use Composer\Factory;
33925
33926
33927
33928
33929
33930
33931
33932
33933
33934
33935 class PearRepository extends ArrayRepository implements ConfigurableRepositoryInterface
33936 {
33937 private $url;
33938 private $io;
33939 private $rfs;
33940 private $versionParser;
33941 private $repoConfig;
33942
33943
33944
33945
33946 private $vendorAlias;
33947
33948 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, RemoteFilesystem $rfs = null)
33949 {
33950 parent::__construct();
33951 if (!preg_match('{^https?://}', $repoConfig['url'])) {
33952 $repoConfig['url'] = 'http://'.$repoConfig['url'];
33953 }
33954
33955 $urlBits = parse_url($repoConfig['url']);
33956 if (empty($urlBits['scheme']) || empty($urlBits['host'])) {
33957 throw new \UnexpectedValueException('Invalid url given for PEAR repository: '.$repoConfig['url']);
33958 }
33959
33960 $this->url = rtrim($repoConfig['url'], '/');
33961 $this->io = $io;
33962 $this->rfs = $rfs ?: Factory::createRemoteFilesystem($this->io, $config);
33963 $this->vendorAlias = isset($repoConfig['vendor-alias']) ? $repoConfig['vendor-alias'] : null;
33964 $this->versionParser = new VersionParser();
33965 $this->repoConfig = $repoConfig;
33966 }
33967
33968 public function getRepoConfig()
33969 {
33970 return $this->repoConfig;
33971 }
33972
33973 protected function initialize()
33974 {
33975 parent::initialize();
33976
33977 $this->io->writeError('Initializing PEAR repository '.$this->url);
33978
33979 $reader = new ChannelReader($this->rfs);
33980 try {
33981 $channelInfo = $reader->read($this->url);
33982 } catch (\Exception $e) {
33983 $this->io->writeError('<warning>PEAR repository from '.$this->url.' could not be loaded. '.$e->getMessage().'</warning>');
33984
33985 return;
33986 }
33987 $packages = $this->buildComposerPackages($channelInfo, $this->versionParser);
33988 foreach ($packages as $package) {
33989 $this->addPackage($package);
33990 }
33991 }
33992
33993
33994
33995
33996
33997
33998
33999
34000 private function buildComposerPackages(ChannelInfo $channelInfo, SemverVersionParser $versionParser)
34001 {
34002 $result = array();
34003 foreach ($channelInfo->getPackages() as $packageDefinition) {
34004 foreach ($packageDefinition->getReleases() as $version => $releaseInfo) {
34005 try {
34006 $normalizedVersion = $versionParser->normalize($version);
34007 } catch (\UnexpectedValueException $e) {
34008 $this->io->writeError('Could not load '.$packageDefinition->getPackageName().' '.$version.': '.$e->getMessage(), true, IOInterface::VERBOSE);
34009 continue;
34010 }
34011
34012 $composerPackageName = $this->buildComposerPackageName($packageDefinition->getChannelName(), $packageDefinition->getPackageName());
34013
34014
34015  
34016  $urlBits = parse_url($this->url);
34017 $scheme = (isset($urlBits['scheme']) && 'https' === $urlBits['scheme'] && extension_loaded('openssl')) ? 'https' : 'http';
34018 $distUrl = "{$scheme}://{$packageDefinition->getChannelName()}/get/{$packageDefinition->getPackageName()}-{$version}.tgz";
34019
34020 $requires = array();
34021 $suggests = array();
34022 $conflicts = array();
34023 $replaces = array();
34024
34025
34026  
34027  if ($channelInfo->getName() == $packageDefinition->getChannelName()) {
34028 $composerPackageAlias = $this->buildComposerPackageName($channelInfo->getAlias(), $packageDefinition->getPackageName());
34029 $aliasConstraint = new Constraint('==', $normalizedVersion);
34030 $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
34031 }
34032
34033
34034  if (!empty($this->vendorAlias)
34035 && ($this->vendorAlias != 'pear-'.$channelInfo->getAlias() || $channelInfo->getName() != $packageDefinition->getChannelName())
34036 ) {
34037 $composerPackageAlias = "{$this->vendorAlias}/{$packageDefinition->getPackageName()}";
34038 $aliasConstraint = new Constraint('==', $normalizedVersion);
34039 $replaces[] = new Link($composerPackageName, $composerPackageAlias, $aliasConstraint, 'replaces', (string) $aliasConstraint);
34040 }
34041
34042 foreach ($releaseInfo->getDependencyInfo()->getRequires() as $dependencyConstraint) {
34043 $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
34044 $constraint = $versionParser->parseConstraints($dependencyConstraint->getConstraint());
34045 $link = new Link($composerPackageName, $dependencyPackageName, $constraint, $dependencyConstraint->getType(), $dependencyConstraint->getConstraint());
34046 switch ($dependencyConstraint->getType()) {
34047 case 'required':
34048 $requires[] = $link;
34049 break;
34050 case 'conflicts':
34051 $conflicts[] = $link;
34052 break;
34053 case 'replaces':
34054 $replaces[] = $link;
34055 break;
34056 }
34057 }
34058
34059 foreach ($releaseInfo->getDependencyInfo()->getOptionals() as $group => $dependencyConstraints) {
34060 foreach ($dependencyConstraints as $dependencyConstraint) {
34061 $dependencyPackageName = $this->buildComposerPackageName($dependencyConstraint->getChannelName(), $dependencyConstraint->getPackageName());
34062 $suggests[$group.'-'.$dependencyPackageName] = $dependencyConstraint->getConstraint();
34063 }
34064 }
34065
34066 $package = new CompletePackage($composerPackageName, $normalizedVersion, $version);
34067 $package->setType('pear-library');
34068 $package->setDescription($packageDefinition->getDescription());
34069 $package->setLicense(array($packageDefinition->getLicense()));
34070 $package->setDistType('file');
34071 $package->setDistUrl($distUrl);
34072 $package->setAutoload(array('classmap' => array('')));
34073 $package->setIncludePaths(array('/'));
34074 $package->setRequires($requires);
34075 $package->setConflicts($conflicts);
34076 $package->setSuggests($suggests);
34077 $package->setReplaces($replaces);
34078 $result[] = $package;
34079 }
34080 }
34081
34082 return $result;
34083 }
34084
34085 private function buildComposerPackageName($channelName, $packageName)
34086 {
34087 if ('php' === $channelName) {
34088 return "php";
34089 }
34090 if ('ext' === $channelName) {
34091 return "ext-{$packageName}";
34092 }
34093
34094 return "pear-{$channelName}/{$packageName}";
34095 }
34096 }
34097 <?php
34098
34099
34100
34101
34102
34103
34104
34105
34106
34107
34108
34109 namespace Composer\Repository;
34110
34111 use Composer\XdebugHandler;
34112 use Composer\Package\CompletePackage;
34113 use Composer\Package\PackageInterface;
34114 use Composer\Package\Version\VersionParser;
34115 use Composer\Plugin\PluginInterface;
34116 use Composer\Util\Silencer;
34117
34118
34119
34120
34121 class PlatformRepository extends ArrayRepository
34122 {
34123 const PLATFORM_PACKAGE_REGEX = '{^(?:php(?:-64bit|-ipv6|-zts|-debug)?|hhvm|(?:ext|lib)-[^/]+)$}i';
34124
34125 private $versionParser;
34126
34127
34128
34129
34130
34131
34132
34133
34134 private $overrides = array();
34135
34136 public function __construct(array $packages = array(), array $overrides = array())
34137 {
34138 foreach ($overrides as $name => $version) {
34139 $this->overrides[strtolower($name)] = array('name' => $name, 'version' => $version);
34140 }
34141 parent::__construct($packages);
34142 }
34143
34144 protected function initialize()
34145 {
34146 parent::initialize();
34147
34148 $this->versionParser = new VersionParser();
34149
34150
34151  
34152  foreach ($this->overrides as $override) {
34153
34154  if (!preg_match(self::PLATFORM_PACKAGE_REGEX, $override['name'])) {
34155 throw new \InvalidArgumentException('Invalid platform package name in config.platform: '.$override['name']);
34156 }
34157
34158 $this->addOverriddenPackage($override);
34159 }
34160
34161 $prettyVersion = PluginInterface::PLUGIN_API_VERSION;
34162 $version = $this->versionParser->normalize($prettyVersion);
34163 $composerPluginApi = new CompletePackage('composer-plugin-api', $version, $prettyVersion);
34164 $composerPluginApi->setDescription('The Composer Plugin API');
34165 $this->addPackage($composerPluginApi);
34166
34167 try {
34168 $prettyVersion = PHP_VERSION;
34169 $version = $this->versionParser->normalize($prettyVersion);
34170 } catch (\UnexpectedValueException $e) {
34171 $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', PHP_VERSION);
34172 $version = $this->versionParser->normalize($prettyVersion);
34173 }
34174
34175 $php = new CompletePackage('php', $version, $prettyVersion);
34176 $php->setDescription('The PHP interpreter');
34177 $this->addPackage($php);
34178
34179 if (PHP_DEBUG) {
34180 $phpdebug = new CompletePackage('php-debug', $version, $prettyVersion);
34181 $phpdebug->setDescription('The PHP interpreter, with debugging symbols');
34182 $this->addPackage($phpdebug);
34183 }
34184
34185 if (defined('PHP_ZTS') && PHP_ZTS) {
34186 $phpzts = new CompletePackage('php-zts', $version, $prettyVersion);
34187 $phpzts->setDescription('The PHP interpreter, with Zend Thread Safety');
34188 $this->addPackage($phpzts);
34189 }
34190
34191 if (PHP_INT_SIZE === 8) {
34192 $php64 = new CompletePackage('php-64bit', $version, $prettyVersion);
34193 $php64->setDescription('The PHP interpreter, 64bit');
34194 $this->addPackage($php64);
34195 }
34196
34197
34198  
34199  if (defined('AF_INET6') || Silencer::call('inet_pton', '::') !== false) {
34200 $phpIpv6 = new CompletePackage('php-ipv6', $version, $prettyVersion);
34201 $phpIpv6->setDescription('The PHP interpreter, with IPv6 support');
34202 $this->addPackage($phpIpv6);
34203 }
34204
34205 $loadedExtensions = get_loaded_extensions();
34206
34207
34208  foreach ($loadedExtensions as $name) {
34209 if (in_array($name, array('standard', 'Core'))) {
34210 continue;
34211 }
34212
34213 $reflExt = new \ReflectionExtension($name);
34214 $prettyVersion = $reflExt->getVersion();
34215 $this->addExtension($name, $prettyVersion);
34216 }
34217
34218
34219  if (!in_array('xdebug', $loadedExtensions, true) && ($prettyVersion = strval(getenv(XdebugHandler::ENV_VERSION)))) {
34220 $this->addExtension('xdebug', $prettyVersion);
34221 }
34222
34223
34224  
34225  
34226  foreach ($loadedExtensions as $name) {
34227 $prettyVersion = null;
34228 $description = 'The '.$name.' PHP library';
34229 switch ($name) {
34230 case 'curl':
34231 $curlVersion = curl_version();
34232 $prettyVersion = $curlVersion['version'];
34233 break;
34234
34235 case 'iconv':
34236 $prettyVersion = ICONV_VERSION;
34237 break;
34238
34239 case 'intl':
34240 $name = 'ICU';
34241 if (defined('INTL_ICU_VERSION')) {
34242 $prettyVersion = INTL_ICU_VERSION;
34243 } else {
34244 $reflector = new \ReflectionExtension('intl');
34245
34246 ob_start();
34247 $reflector->info();
34248 $output = ob_get_clean();
34249
34250 preg_match('/^ICU version => (.*)$/m', $output, $matches);
34251 $prettyVersion = $matches[1];
34252 }
34253
34254 break;
34255
34256 case 'libxml':
34257 $prettyVersion = LIBXML_DOTTED_VERSION;
34258 break;
34259
34260 case 'openssl':
34261 $prettyVersion = preg_replace_callback('{^(?:OpenSSL|LibreSSL)?\s*([0-9.]+)([a-z]*).*}i', function ($match) {
34262 if (empty($match[2])) {
34263 return $match[1];
34264 }
34265
34266
34267  
34268
34269 if (!preg_match('{^z*[a-z]$}', $match[2])) {
34270
34271  return 0;
34272 }
34273
34274 $len = strlen($match[2]);
34275 $patchVersion = ($len - 1) * 26; 
34276  $patchVersion += ord($match[2][$len - 1]) - 96;
34277
34278 return $match[1].'.'.$patchVersion;
34279 }, OPENSSL_VERSION_TEXT);
34280
34281 $description = OPENSSL_VERSION_TEXT;
34282 break;
34283
34284 case 'pcre':
34285 $prettyVersion = preg_replace('{^(\S+).*}', '$1', PCRE_VERSION);
34286 break;
34287
34288 case 'uuid':
34289 $prettyVersion = phpversion('uuid');
34290 break;
34291
34292 case 'xsl':
34293 $prettyVersion = LIBXSLT_DOTTED_VERSION;
34294 break;
34295
34296 default:
34297
34298  continue 2;
34299 }
34300
34301 try {
34302 $version = $this->versionParser->normalize($prettyVersion);
34303 } catch (\UnexpectedValueException $e) {
34304 continue;
34305 }
34306
34307 $lib = new CompletePackage('lib-'.$name, $version, $prettyVersion);
34308 $lib->setDescription($description);
34309 $this->addPackage($lib);
34310 }
34311
34312 if (defined('HHVM_VERSION')) {
34313 try {
34314 $prettyVersion = HHVM_VERSION;
34315 $version = $this->versionParser->normalize($prettyVersion);
34316 } catch (\UnexpectedValueException $e) {
34317 $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', HHVM_VERSION);
34318 $version = $this->versionParser->normalize($prettyVersion);
34319 }
34320
34321 $hhvm = new CompletePackage('hhvm', $version, $prettyVersion);
34322 $hhvm->setDescription('The HHVM Runtime (64bit)');
34323 $this->addPackage($hhvm);
34324 }
34325 }
34326
34327
34328
34329
34330 public function addPackage(PackageInterface $package)
34331 {
34332
34333  if (isset($this->overrides[$package->getName()])) {
34334 $overrider = $this->findPackage($package->getName(), '*');
34335 $overrider->setDescription($overrider->getDescription().' (actual: '.$package->getPrettyVersion().')');
34336
34337 return;
34338 }
34339
34340
34341  if (isset($this->overrides['php']) && 0 === strpos($package->getName(), 'php-')) {
34342 $overrider = $this->addOverriddenPackage($this->overrides['php'], $package->getPrettyName());
34343 $overrider->setDescription($overrider->getDescription().' (actual: '.$package->getPrettyVersion().')');
34344
34345 return;
34346 }
34347
34348 parent::addPackage($package);
34349 }
34350
34351 private function addOverriddenPackage(array $override, $name = null)
34352 {
34353 $version = $this->versionParser->normalize($override['version']);
34354 $package = new CompletePackage($name ?: $override['name'], $version, $override['version']);
34355 $package->setDescription('Package overridden via config.platform');
34356 $package->setExtra(array('config.platform' => true));
34357 parent::addPackage($package);
34358
34359 return $package;
34360 }
34361
34362
34363
34364
34365
34366
34367
34368 private function addExtension($name, $prettyVersion)
34369 {
34370 $extraDescription = null;
34371
34372 try {
34373 $version = $this->versionParser->normalize($prettyVersion);
34374 } catch (\UnexpectedValueException $e) {
34375 $extraDescription = ' (actual version: '.$prettyVersion.')';
34376 if (preg_match('{^(\d+\.\d+\.\d+(?:\.\d+)?)}', $prettyVersion, $match)) {
34377 $prettyVersion = $match[1];
34378 } else {
34379 $prettyVersion = '0';
34380 }
34381 $version = $this->versionParser->normalize($prettyVersion);
34382 }
34383
34384 $packageName = $this->buildPackageName($name);
34385 $ext = new CompletePackage($packageName, $version, $prettyVersion);
34386 $ext->setDescription('The '.$name.' PHP extension'.$extraDescription);
34387 $this->addPackage($ext);
34388 }
34389
34390 private function buildPackageName($name)
34391 {
34392 return 'ext-' . str_replace(' ', '-', $name);
34393 }
34394 }
34395 <?php
34396
34397
34398
34399
34400
34401
34402
34403
34404
34405
34406
34407 namespace Composer\Repository;
34408
34409 use Composer\Factory;
34410 use Composer\IO\IOInterface;
34411 use Composer\Config;
34412 use Composer\EventDispatcher\EventDispatcher;
34413 use Composer\Util\RemoteFilesystem;
34414 use Composer\Json\JsonFile;
34415
34416
34417
34418
34419 class RepositoryFactory
34420 {
34421
34422
34423
34424
34425
34426
34427
34428 public static function configFromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false)
34429 {
34430 if (0 === strpos($repository, 'http')) {
34431 $repoConfig = array('type' => 'composer', 'url' => $repository);
34432 } elseif ("json" === pathinfo($repository, PATHINFO_EXTENSION)) {
34433 $json = new JsonFile($repository, Factory::createRemoteFilesystem($io, $config));
34434 $data = $json->read();
34435 if (!empty($data['packages']) || !empty($data['includes']) || !empty($data['provider-includes'])) {
34436 $repoConfig = array('type' => 'composer', 'url' => 'file://' . strtr(realpath($repository), '\\', '/'));
34437 } elseif ($allowFilesystem) {
34438 $repoConfig = array('type' => 'filesystem', 'json' => $json);
34439 } else {
34440 throw new \InvalidArgumentException("Invalid repository URL ($repository) given. This file does not contain a valid composer repository.");
34441 }
34442 } elseif ('{' === substr($repository, 0, 1)) {
34443
34444  $repoConfig = JsonFile::parseJson($repository);
34445 } else {
34446 throw new \InvalidArgumentException("Invalid repository url ($repository) given. Has to be a .json file, an http url or a JSON object.");
34447 }
34448
34449 return $repoConfig;
34450 }
34451
34452
34453
34454
34455
34456
34457
34458
34459 public static function fromString(IOInterface $io, Config $config, $repository, $allowFilesystem = false)
34460 {
34461 $repoConfig = static::configFromString($io, $config, $repository, $allowFilesystem);
34462
34463 return static::createRepo($io, $config, $repoConfig);
34464 }
34465
34466
34467
34468
34469
34470
34471
34472 public static function createRepo(IOInterface $io, Config $config, array $repoConfig)
34473 {
34474 $rm = static::manager($io, $config, null, Factory::createRemoteFilesystem($io, $config));
34475 $repos = static::createRepos($rm, array($repoConfig));
34476
34477 return reset($repos);
34478 }
34479
34480
34481
34482
34483
34484
34485
34486 public static function defaultRepos(IOInterface $io = null, Config $config = null, RepositoryManager $rm = null)
34487 {
34488 if (!$config) {
34489 $config = Factory::createConfig($io);
34490 }
34491 if (!$rm) {
34492 if (!$io) {
34493 throw new \InvalidArgumentException('This function requires either an IOInterface or a RepositoryManager');
34494 }
34495 $rm = static::manager($io, $config, null, Factory::createRemoteFilesystem($io, $config));
34496 }
34497
34498 return static::createRepos($rm, $config->getRepositories());
34499 }
34500
34501
34502
34503
34504
34505
34506
34507
34508 public static function manager(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
34509 {
34510 $rm = new RepositoryManager($io, $config, $eventDispatcher, $rfs);
34511 $rm->setRepositoryClass('composer', 'Composer\Repository\ComposerRepository');
34512 $rm->setRepositoryClass('vcs', 'Composer\Repository\VcsRepository');
34513 $rm->setRepositoryClass('package', 'Composer\Repository\PackageRepository');
34514 $rm->setRepositoryClass('pear', 'Composer\Repository\PearRepository');
34515 $rm->setRepositoryClass('git', 'Composer\Repository\VcsRepository');
34516 $rm->setRepositoryClass('github', 'Composer\Repository\VcsRepository');
34517 $rm->setRepositoryClass('gitlab', 'Composer\Repository\VcsRepository');
34518 $rm->setRepositoryClass('svn', 'Composer\Repository\VcsRepository');
34519 $rm->setRepositoryClass('fossil', 'Composer\Repository\VcsRepository');
34520 $rm->setRepositoryClass('perforce', 'Composer\Repository\VcsRepository');
34521 $rm->setRepositoryClass('hg', 'Composer\Repository\VcsRepository');
34522 $rm->setRepositoryClass('artifact', 'Composer\Repository\ArtifactRepository');
34523 $rm->setRepositoryClass('path', 'Composer\Repository\PathRepository');
34524
34525 return $rm;
34526 }
34527
34528
34529
34530
34531 private static function createRepos(RepositoryManager $rm, array $repoConfigs)
34532 {
34533 $repos = array();
34534
34535 foreach ($repoConfigs as $index => $repo) {
34536 if (is_string($repo)) {
34537 throw new \UnexpectedValueException('"repositories" should be an array of repository definitions, only a single repository was given');
34538 }
34539 if (!is_array($repo)) {
34540 throw new \UnexpectedValueException('Repository "'.$index.'" ('.json_encode($repo).') should be an array, '.gettype($repo).' given');
34541 }
34542 if (!isset($repo['type'])) {
34543 throw new \UnexpectedValueException('Repository "'.$index.'" ('.json_encode($repo).') must have a type defined');
34544 }
34545 $name = is_int($index) && isset($repo['url']) ? preg_replace('{^https?://}i', '', $repo['url']) : $index;
34546 while (isset($repos[$name])) {
34547 $name .= '2';
34548 }
34549 if ($repo['type'] === 'filesystem') {
34550 $repos[$name] = new FilesystemRepository($repo['json']);
34551 } else {
34552 $repos[$name] = $rm->createRepository($repo['type'], $repo, $index);
34553 }
34554 }
34555
34556 return $repos;
34557 }
34558 }
34559 <?php
34560
34561
34562
34563
34564
34565
34566
34567
34568
34569
34570
34571 namespace Composer\Repository;
34572
34573 use Composer\Package\PackageInterface;
34574
34575
34576
34577
34578
34579
34580
34581
34582 interface RepositoryInterface extends \Countable
34583 {
34584 const SEARCH_FULLTEXT = 0;
34585 const SEARCH_NAME = 1;
34586
34587
34588
34589
34590
34591
34592
34593
34594 public function hasPackage(PackageInterface $package);
34595
34596
34597
34598
34599
34600
34601
34602
34603
34604 public function findPackage($name, $constraint);
34605
34606
34607
34608
34609
34610
34611
34612
34613
34614 public function findPackages($name, $constraint = null);
34615
34616
34617
34618
34619
34620
34621 public function getPackages();
34622
34623
34624
34625
34626
34627
34628
34629
34630
34631 public function search($query, $mode = 0);
34632 }
34633 <?php
34634
34635
34636
34637
34638
34639
34640
34641
34642
34643
34644
34645 namespace Composer\Repository;
34646
34647 use Composer\IO\IOInterface;
34648 use Composer\Config;
34649 use Composer\EventDispatcher\EventDispatcher;
34650 use Composer\Package\PackageInterface;
34651 use Composer\Util\RemoteFilesystem;
34652
34653
34654
34655
34656
34657
34658
34659
34660 class RepositoryManager
34661 {
34662 private $localRepository;
34663 private $repositories = array();
34664 private $repositoryClasses = array();
34665 private $io;
34666 private $config;
34667 private $eventDispatcher;
34668 private $rfs;
34669
34670 public function __construct(IOInterface $io, Config $config, EventDispatcher $eventDispatcher = null, RemoteFilesystem $rfs = null)
34671 {
34672 $this->io = $io;
34673 $this->config = $config;
34674 $this->eventDispatcher = $eventDispatcher;
34675 $this->rfs = $rfs;
34676 }
34677
34678
34679
34680
34681
34682
34683
34684
34685
34686 public function findPackage($name, $constraint)
34687 {
34688 foreach ($this->repositories as $repository) {
34689 if ($package = $repository->findPackage($name, $constraint)) {
34690 return $package;
34691 }
34692 }
34693
34694 return null;
34695 }
34696
34697
34698
34699
34700
34701
34702
34703
34704
34705 public function findPackages($name, $constraint)
34706 {
34707 $packages = array();
34708
34709 foreach ($this->repositories as $repository) {
34710 $packages = array_merge($packages, $repository->findPackages($name, $constraint));
34711 }
34712
34713 return $packages;
34714 }
34715
34716
34717
34718
34719
34720
34721 public function addRepository(RepositoryInterface $repository)
34722 {
34723 $this->repositories[] = $repository;
34724 }
34725
34726
34727
34728
34729
34730
34731
34732
34733 public function prependRepository(RepositoryInterface $repository)
34734 {
34735 array_unshift($this->repositories, $repository);
34736 }
34737
34738
34739
34740
34741
34742
34743
34744
34745
34746
34747 public function createRepository($type, $config, $name = null)
34748 {
34749 if (!isset($this->repositoryClasses[$type])) {
34750 throw new \InvalidArgumentException('Repository type is not registered: '.$type);
34751 }
34752
34753 if (isset($config['packagist']) && false === $config['packagist']) {
34754 $this->io->writeError('<warning>Repository "'.$name.'" ('.json_encode($config).') has a packagist key which should be in its own repository definition</warning>');
34755 }
34756
34757 $class = $this->repositoryClasses[$type];
34758
34759 $reflMethod = new \ReflectionMethod($class, '__construct');
34760 $params = $reflMethod->getParameters();
34761 if (isset($params[4]) && $params[4]->getClass() && $params[4]->getClass()->getName() === 'Composer\Util\RemoteFilesystem') {
34762 return new $class($config, $this->io, $this->config, $this->eventDispatcher, $this->rfs);
34763 }
34764
34765 return new $class($config, $this->io, $this->config, $this->eventDispatcher);
34766 }
34767
34768
34769
34770
34771
34772
34773
34774 public function setRepositoryClass($type, $class)
34775 {
34776 $this->repositoryClasses[$type] = $class;
34777 }
34778
34779
34780
34781
34782
34783
34784 public function getRepositories()
34785 {
34786 return $this->repositories;
34787 }
34788
34789
34790
34791
34792
34793
34794 public function setLocalRepository(WritableRepositoryInterface $repository)
34795 {
34796 $this->localRepository = $repository;
34797 }
34798
34799
34800
34801
34802
34803
34804 public function getLocalRepository()
34805 {
34806 return $this->localRepository;
34807 }
34808 }
34809 <?php
34810
34811
34812
34813
34814
34815
34816
34817
34818
34819
34820
34821 namespace Composer\Repository;
34822
34823
34824
34825
34826
34827
34828 class RepositorySecurityException extends \Exception
34829 {
34830 }
34831 <?php
34832
34833
34834
34835
34836
34837
34838
34839
34840
34841
34842
34843 namespace Composer\Repository\Vcs;
34844
34845 use Composer\Cache;
34846 use Composer\Downloader\TransportException;
34847 use Composer\Json\JsonFile;
34848 use Composer\Util\Bitbucket;
34849
34850 abstract class BitbucketDriver extends VcsDriver
34851 {
34852
34853 protected $cache;
34854 protected $owner;
34855 protected $repository;
34856 protected $hasIssues;
34857 protected $rootIdentifier;
34858 protected $tags;
34859 protected $branches;
34860 protected $infoCache = array();
34861 protected $branchesUrl = '';
34862 protected $tagsUrl = '';
34863 protected $homeUrl = '';
34864 protected $website = '';
34865 protected $cloneHttpsUrl = '';
34866
34867
34868
34869
34870 protected $fallbackDriver;
34871
34872 protected $vcsType;
34873
34874
34875
34876
34877 public function initialize()
34878 {
34879 preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+?)(\.git|/?)$#', $this->url, $match);
34880 $this->owner = $match[1];
34881 $this->repository = $match[2];
34882 $this->originUrl = 'bitbucket.org';
34883 $this->cache = new Cache(
34884 $this->io,
34885 implode('/', array(
34886 $this->config->get('cache-repo-dir'),
34887 $this->originUrl,
34888 $this->owner,
34889 $this->repository,
34890 ))
34891 );
34892 }
34893
34894
34895
34896
34897 public function getUrl()
34898 {
34899 if ($this->fallbackDriver) {
34900 return $this->fallbackDriver->getUrl();
34901 }
34902
34903 return $this->cloneHttpsUrl;
34904 }
34905
34906
34907
34908
34909
34910
34911
34912 protected function getRepoData()
34913 {
34914 $resource = sprintf(
34915 'https://api.bitbucket.org/2.0/repositories/%s/%s?%s',
34916 $this->owner,
34917 $this->repository,
34918 http_build_query(
34919 array('fields' => '-project,-owner'),
34920 null,
34921 '&'
34922 )
34923 );
34924
34925 $repoData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource, true), $resource);
34926 if ($this->fallbackDriver) {
34927 return false;
34928 }
34929 $this->parseCloneUrls($repoData['links']['clone']);
34930
34931 $this->hasIssues = !empty($repoData['has_issues']);
34932 $this->branchesUrl = $repoData['links']['branches']['href'];
34933 $this->tagsUrl = $repoData['links']['tags']['href'];
34934 $this->homeUrl = $repoData['links']['html']['href'];
34935 $this->website = $repoData['website'];
34936 $this->vcsType = $repoData['scm'];
34937
34938 return true;
34939 }
34940
34941
34942
34943
34944 public function getComposerInformation($identifier)
34945 {
34946 if ($this->fallbackDriver) {
34947 return $this->fallbackDriver->getComposerInformation($identifier);
34948 }
34949
34950 if (!isset($this->infoCache[$identifier])) {
34951 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
34952 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
34953 }
34954
34955 $composer = $this->getBaseComposerInformation($identifier);
34956
34957
34958  if (!isset($composer['support']['source'])) {
34959 $label = array_search(
34960 $identifier,
34961 $this->getTags()
34962 ) ?: array_search(
34963 $identifier,
34964 $this->getBranches()
34965 ) ?: $identifier;
34966
34967 if (array_key_exists($label, $tags = $this->getTags())) {
34968 $hash = $tags[$label];
34969 } elseif (array_key_exists($label, $branches = $this->getBranches())) {
34970 $hash = $branches[$label];
34971 }
34972
34973 if (! isset($hash)) {
34974 $composer['support']['source'] = sprintf(
34975 'https://%s/%s/%s/src',
34976 $this->originUrl,
34977 $this->owner,
34978 $this->repository
34979 );
34980 } else {
34981 $composer['support']['source'] = sprintf(
34982 'https://%s/%s/%s/src/%s/?at=%s',
34983 $this->originUrl,
34984 $this->owner,
34985 $this->repository,
34986 $hash,
34987 $label
34988 );
34989 }
34990 }
34991 if (!isset($composer['support']['issues']) && $this->hasIssues) {
34992 $composer['support']['issues'] = sprintf(
34993 'https://%s/%s/%s/issues',
34994 $this->originUrl,
34995 $this->owner,
34996 $this->repository
34997 );
34998 }
34999 if (!isset($composer['homepage'])) {
35000 $composer['homepage'] = empty($this->website) ? $this->homeUrl : $this->website;
35001 }
35002
35003 $this->infoCache[$identifier] = $composer;
35004
35005 if ($this->shouldCache($identifier)) {
35006 $this->cache->write($identifier, json_encode($composer));
35007 }
35008 }
35009
35010 return $this->infoCache[$identifier];
35011 }
35012
35013
35014
35015
35016 public function getFileContent($file, $identifier)
35017 {
35018 if ($this->fallbackDriver) {
35019 return $this->fallbackDriver->getFileContent($file, $identifier);
35020 }
35021
35022 $resource = sprintf(
35023 'https://api.bitbucket.org/1.0/repositories/%s/%s/raw/%s/%s',
35024 $this->owner,
35025 $this->repository,
35026 $identifier,
35027 $file
35028 );
35029
35030 return $this->getContentsWithOAuthCredentials($resource);
35031 }
35032
35033
35034
35035
35036 public function getChangeDate($identifier)
35037 {
35038 if ($this->fallbackDriver) {
35039 return $this->fallbackDriver->getChangeDate($identifier);
35040 }
35041
35042 $resource = sprintf(
35043 'https://api.bitbucket.org/2.0/repositories/%s/%s/commit/%s?fields=date',
35044 $this->owner,
35045 $this->repository,
35046 $identifier
35047 );
35048 $commit = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
35049
35050 return new \DateTime($commit['date']);
35051 }
35052
35053
35054
35055
35056 public function getSource($identifier)
35057 {
35058 if ($this->fallbackDriver) {
35059 return $this->fallbackDriver->getSource($identifier);
35060 }
35061
35062 return array('type' => $this->vcsType, 'url' => $this->getUrl(), 'reference' => $identifier);
35063 }
35064
35065
35066
35067
35068 public function getDist($identifier)
35069 {
35070 if ($this->fallbackDriver) {
35071 return $this->fallbackDriver->getDist($identifier);
35072 }
35073
35074 $url = sprintf(
35075 'https://bitbucket.org/%s/%s/get/%s.zip',
35076 $this->owner,
35077 $this->repository,
35078 $identifier
35079 );
35080
35081 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
35082 }
35083
35084
35085
35086
35087 public function getTags()
35088 {
35089 if ($this->fallbackDriver) {
35090 return $this->fallbackDriver->getTags();
35091 }
35092
35093 if (null === $this->tags) {
35094 $this->tags = array();
35095 $resource = sprintf(
35096 '%s?%s',
35097 $this->tagsUrl,
35098 http_build_query(
35099 array(
35100 'pagelen' => 100,
35101 'fields' => 'values.name,values.target.hash,next',
35102 'sort' => '-target.date',
35103 ),
35104 null,
35105 '&'
35106 )
35107 );
35108 $hasNext = true;
35109 while ($hasNext) {
35110 $tagsData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
35111 foreach ($tagsData['values'] as $data) {
35112 $this->tags[$data['name']] = $data['target']['hash'];
35113 }
35114 if (empty($tagsData['next'])) {
35115 $hasNext = false;
35116 } else {
35117 $resource = $tagsData['next'];
35118 }
35119 }
35120 if ($this->vcsType === 'hg') {
35121 unset($this->tags['tip']);
35122 }
35123 }
35124
35125 return $this->tags;
35126 }
35127
35128
35129
35130
35131 public function getBranches()
35132 {
35133 if ($this->fallbackDriver) {
35134 return $this->fallbackDriver->getBranches();
35135 }
35136
35137 if (null === $this->branches) {
35138 $this->branches = array();
35139 $resource = sprintf(
35140 '%s?%s',
35141 $this->branchesUrl,
35142 http_build_query(
35143 array(
35144 'pagelen' => 100,
35145 'fields' => 'values.name,values.target.hash,values.heads,next',
35146 'sort' => '-target.date',
35147 ),
35148 null,
35149 '&'
35150 )
35151 );
35152 $hasNext = true;
35153 while ($hasNext) {
35154 $branchData = JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
35155 foreach ($branchData['values'] as $data) {
35156
35157  if ($this->vcsType === 'hg' && empty($data['heads'])) {
35158 continue;
35159 }
35160
35161 $this->branches[$data['name']] = $data['target']['hash'];
35162 }
35163 if (empty($branchData['next'])) {
35164 $hasNext = false;
35165 } else {
35166 $resource = $branchData['next'];
35167 }
35168 }
35169 }
35170
35171 return $this->branches;
35172 }
35173
35174
35175
35176
35177
35178
35179
35180
35181
35182 protected function getContentsWithOAuthCredentials($url, $fetchingRepoData = false)
35183 {
35184 try {
35185 return parent::getContents($url);
35186 } catch (TransportException $e) {
35187 $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process, $this->remoteFilesystem);
35188
35189 if (403 === $e->getCode() || (401 === $e->getCode() && strpos($e->getMessage(), 'Could not authenticate against') === 0)) {
35190 if (!$this->io->hasAuthentication($this->originUrl)
35191 && $bitbucketUtil->authorizeOAuth($this->originUrl)
35192 ) {
35193 return parent::getContents($url);
35194 }
35195
35196 if (!$this->io->isInteractive() && $fetchingRepoData) {
35197 return $this->attemptCloneFallback();
35198 }
35199 }
35200
35201 throw $e;
35202 }
35203 }
35204
35205
35206
35207
35208
35209
35210 abstract protected function generateSshUrl();
35211
35212 protected function attemptCloneFallback()
35213 {
35214 try {
35215 $this->setupFallbackDriver($this->generateSshUrl());
35216 } catch (\RuntimeException $e) {
35217 $this->fallbackDriver = null;
35218
35219 $this->io->writeError(
35220 '<error>Failed to clone the ' . $this->generateSshUrl() . ' repository, try running in interactive mode'
35221 . ' so that you can enter your Bitbucket OAuth consumer credentials</error>'
35222 );
35223 throw $e;
35224 }
35225 }
35226
35227
35228
35229
35230
35231 abstract protected function setupFallbackDriver($url);
35232
35233
35234
35235
35236
35237 protected function parseCloneUrls(array $cloneLinks)
35238 {
35239 foreach ($cloneLinks as $cloneLink) {
35240 if ($cloneLink['name'] === 'https') {
35241
35242  
35243  $this->cloneHttpsUrl = preg_replace('/https:\/\/([^@]+@)?/', 'https://', $cloneLink['href']);
35244 }
35245 }
35246 }
35247
35248
35249
35250
35251 protected function getMainBranchData()
35252 {
35253 $resource = sprintf(
35254 'https://api.bitbucket.org/1.0/repositories/%s/%s/main-branch',
35255 $this->owner,
35256 $this->repository
35257 );
35258
35259 return JsonFile::parseJson($this->getContentsWithOAuthCredentials($resource), $resource);
35260 }
35261 }
35262 <?php
35263
35264
35265
35266
35267
35268
35269
35270
35271
35272
35273
35274 namespace Composer\Repository\Vcs;
35275
35276 use Composer\Config;
35277 use Composer\Util\ProcessExecutor;
35278 use Composer\Util\Filesystem;
35279 use Composer\IO\IOInterface;
35280
35281
35282
35283
35284 class FossilDriver extends VcsDriver
35285 {
35286 protected $tags;
35287 protected $branches;
35288 protected $rootIdentifier;
35289 protected $repoFile;
35290 protected $checkoutDir;
35291 protected $infoCache = array();
35292
35293
35294
35295
35296 public function initialize()
35297 {
35298 if (Filesystem::isLocalPath($this->url)) {
35299 $this->checkoutDir = $this->url;
35300 } else {
35301 $this->repoFile = $this->config->get('cache-repo-dir') . '/' . preg_replace('{[^a-z0-9]}i', '-', $this->url) . '.fossil';
35302 $this->checkoutDir = $this->config->get('cache-vcs-dir') . '/' . preg_replace('{[^a-z0-9]}i', '-', $this->url) . '/';
35303
35304 $fs = new Filesystem();
35305 $fs->ensureDirectoryExists($this->checkoutDir);
35306
35307 if (!is_writable(dirname($this->checkoutDir))) {
35308 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$this->checkoutDir.'" directory is not writable by the current user.');
35309 }
35310
35311
35312  $this->config->prohibitUrlByConfig($this->url, $this->io);
35313
35314
35315  if (is_file($this->repoFile) && is_dir($this->checkoutDir) && 0 === $this->process->execute('fossil info', $output, $this->checkoutDir)) {
35316 if (0 !== $this->process->execute('fossil pull', $output, $this->checkoutDir)) {
35317 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')</error>');
35318 }
35319 } else {
35320
35321  $fs->removeDirectory($this->checkoutDir);
35322 $fs->remove($this->repoFile);
35323
35324 $fs->ensureDirectoryExists($this->checkoutDir);
35325
35326 if (0 !== $this->process->execute(sprintf('fossil clone %s %s', ProcessExecutor::escape($this->url), ProcessExecutor::escape($this->repoFile)), $output)) {
35327 $output = $this->process->getErrorOutput();
35328
35329 if (0 !== $this->process->execute('fossil version', $ignoredOutput)) {
35330 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());
35331 }
35332
35333 throw new \RuntimeException('Failed to clone '.$this->url.' to repository ' . $this->repoFile . "\n\n" .$output);
35334 }
35335
35336 if (0 !== $this->process->execute(sprintf('fossil open %s', ProcessExecutor::escape($this->repoFile)), $output, $this->checkoutDir)) {
35337 $output = $this->process->getErrorOutput();
35338
35339 throw new \RuntimeException('Failed to open repository '.$this->repoFile.' in ' . $this->checkoutDir . "\n\n" .$output);
35340 }
35341 }
35342 }
35343
35344 $this->getTags();
35345 $this->getBranches();
35346 }
35347
35348
35349
35350
35351 public function getRootIdentifier()
35352 {
35353 if (null === $this->rootIdentifier) {
35354 $this->rootIdentifier = 'trunk';
35355 }
35356
35357 return $this->rootIdentifier;
35358 }
35359
35360
35361
35362
35363 public function getUrl()
35364 {
35365 return $this->url;
35366 }
35367
35368
35369
35370
35371 public function getSource($identifier)
35372 {
35373 return array('type' => 'fossil', 'url' => $this->getUrl(), 'reference' => $identifier);
35374 }
35375
35376
35377
35378
35379 public function getDist($identifier)
35380 {
35381 return null;
35382 }
35383
35384
35385
35386
35387 public function getFileContent($file, $identifier)
35388 {
35389 $command = sprintf('fossil cat -r %s %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
35390 $this->process->execute($command, $content, $this->checkoutDir);
35391
35392 if (!trim($content)) {
35393 return null;
35394 }
35395
35396 return $content;
35397 }
35398
35399
35400
35401
35402 public function getChangeDate($identifier)
35403 {
35404 $this->process->execute(sprintf('fossil finfo composer.json | head -n 2 | tail -n 1 | awk \'{print $1}\''), $output, $this->checkoutDir);
35405
35406 return new \DateTime(trim($output), new \DateTimeZone('UTC'));
35407 }
35408
35409
35410
35411
35412 public function getTags()
35413 {
35414 if (null === $this->tags) {
35415 $tags = array();
35416
35417 $this->process->execute('fossil tag list', $output, $this->checkoutDir);
35418 foreach ($this->process->splitLines($output) as $tag) {
35419 $tags[$tag] = $tag;
35420 }
35421
35422 $this->tags = $tags;
35423 }
35424
35425 return $this->tags;
35426 }
35427
35428
35429
35430
35431 public function getBranches()
35432 {
35433 if (null === $this->branches) {
35434 $branches = array();
35435 $bookmarks = array();
35436
35437 $this->process->execute('fossil branch list', $output, $this->checkoutDir);
35438 foreach ($this->process->splitLines($output) as $branch) {
35439 $branch = trim(preg_replace('/^\*/', '', trim($branch)));
35440 $branches[$branch] = $branch;
35441 }
35442
35443 $this->branches = $branches;
35444 }
35445
35446 return $this->branches;
35447 }
35448
35449
35450
35451
35452 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
35453 {
35454 if (preg_match('#(^(?:https?|ssh)://(?:[^@]@)?(?:chiselapp\.com|fossil\.))#i', $url)) {
35455 return true;
35456 }
35457
35458 if (preg_match('!/fossil/|\.fossil!', $url)) {
35459 return true;
35460 }
35461
35462
35463  if (Filesystem::isLocalPath($url)) {
35464 $url = Filesystem::getPlatformPath($url);
35465 if (!is_dir($url)) {
35466 return false;
35467 }
35468
35469 $process = new ProcessExecutor();
35470
35471  if ($process->execute('fossil info', $output, $url) === 0) {
35472 return true;
35473 }
35474 }
35475
35476 return false;
35477 }
35478 }
35479 <?php
35480
35481
35482
35483
35484
35485
35486
35487
35488
35489
35490
35491 namespace Composer\Repository\Vcs;
35492
35493 use Composer\Config;
35494 use Composer\IO\IOInterface;
35495
35496
35497
35498
35499 class GitBitbucketDriver extends BitbucketDriver
35500 {
35501
35502
35503
35504 public function getRootIdentifier()
35505 {
35506 if ($this->fallbackDriver) {
35507 return $this->fallbackDriver->getRootIdentifier();
35508 }
35509
35510 if (null === $this->rootIdentifier) {
35511 if (! $this->getRepoData()) {
35512 return $this->fallbackDriver->getRootIdentifier();
35513 }
35514
35515 if ($this->vcsType !== 'git') {
35516 throw new \RuntimeException(
35517 $this->url.' does not appear to be a git repository, use '.
35518 $this->cloneHttpsUrl.' if this is a mercurial bitbucket repository'
35519 );
35520 }
35521
35522 $mainBranchData = $this->getMainBranchData();
35523 $this->rootIdentifier = !empty($mainBranchData['name']) ? $mainBranchData['name'] : 'master';
35524 }
35525
35526 return $this->rootIdentifier;
35527 }
35528
35529
35530
35531
35532 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
35533 {
35534 if (!preg_match('#^https?://bitbucket\.org/([^/]+)/(.+?)\.git$#', $url)) {
35535 return false;
35536 }
35537
35538 if (!extension_loaded('openssl')) {
35539 $io->writeError('Skipping Bitbucket git driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
35540
35541 return false;
35542 }
35543
35544 return true;
35545 }
35546
35547
35548
35549
35550 protected function setupFallbackDriver($url)
35551 {
35552 $this->fallbackDriver = new GitDriver(
35553 array('url' => $url),
35554 $this->io,
35555 $this->config,
35556 $this->process,
35557 $this->remoteFilesystem
35558 );
35559 $this->fallbackDriver->initialize();
35560 }
35561
35562
35563
35564
35565 protected function generateSshUrl()
35566 {
35567 return 'git@' . $this->originUrl . ':' . $this->owner.'/'.$this->repository.'.git';
35568 }
35569 }
35570 <?php
35571
35572
35573
35574
35575
35576
35577
35578
35579
35580
35581
35582 namespace Composer\Repository\Vcs;
35583
35584 use Composer\Util\ProcessExecutor;
35585 use Composer\Util\Filesystem;
35586 use Composer\Util\Git as GitUtil;
35587 use Composer\IO\IOInterface;
35588 use Composer\Cache;
35589 use Composer\Config;
35590
35591
35592
35593
35594 class GitDriver extends VcsDriver
35595 {
35596 protected $cache;
35597 protected $tags;
35598 protected $branches;
35599 protected $rootIdentifier;
35600 protected $repoDir;
35601 protected $infoCache = array();
35602
35603
35604
35605
35606 public function initialize()
35607 {
35608 if (Filesystem::isLocalPath($this->url)) {
35609 $this->url = preg_replace('{[\\/]\.git/?$}', '', $this->url);
35610 $this->repoDir = $this->url;
35611 $cacheUrl = realpath($this->url);
35612 } else {
35613 $this->repoDir = $this->config->get('cache-vcs-dir') . '/' . preg_replace('{[^a-z0-9.]}i', '-', $this->url) . '/';
35614
35615 GitUtil::cleanEnv();
35616
35617 $fs = new Filesystem();
35618 $fs->ensureDirectoryExists(dirname($this->repoDir));
35619
35620 if (!is_writable(dirname($this->repoDir))) {
35621 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.dirname($this->repoDir).'" directory is not writable by the current user.');
35622 }
35623
35624 if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $this->url)) {
35625 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.');
35626 }
35627
35628 $gitUtil = new GitUtil($this->io, $this->config, $this->process, $fs);
35629 if (!$gitUtil->syncMirror($this->url, $this->repoDir)) {
35630 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated</error>');
35631 }
35632
35633 $cacheUrl = $this->url;
35634 }
35635
35636 $this->getTags();
35637 $this->getBranches();
35638
35639 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $cacheUrl));
35640 }
35641
35642
35643
35644
35645 public function getRootIdentifier()
35646 {
35647 if (null === $this->rootIdentifier) {
35648 $this->rootIdentifier = 'master';
35649
35650
35651  $this->process->execute('git branch --no-color', $output, $this->repoDir);
35652 $branches = $this->process->splitLines($output);
35653 if (!in_array('* master', $branches)) {
35654 foreach ($branches as $branch) {
35655 if ($branch && preg_match('{^\* +(\S+)}', $branch, $match)) {
35656 $this->rootIdentifier = $match[1];
35657 break;
35658 }
35659 }
35660 }
35661 }
35662
35663 return $this->rootIdentifier;
35664 }
35665
35666
35667
35668
35669 public function getUrl()
35670 {
35671 return $this->url;
35672 }
35673
35674
35675
35676
35677 public function getSource($identifier)
35678 {
35679 return array('type' => 'git', 'url' => $this->getUrl(), 'reference' => $identifier);
35680 }
35681
35682
35683
35684
35685 public function getDist($identifier)
35686 {
35687 return null;
35688 }
35689
35690
35691
35692
35693 public function getFileContent($file, $identifier)
35694 {
35695 $resource = sprintf('%s:%s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
35696 $this->process->execute(sprintf('git show %s', $resource), $content, $this->repoDir);
35697
35698 if (!trim($content)) {
35699 return null;
35700 }
35701
35702 return $content;
35703 }
35704
35705
35706
35707
35708 public function getChangeDate($identifier)
35709 {
35710 $this->process->execute(sprintf(
35711 'git log -1 --format=%%at %s',
35712 ProcessExecutor::escape($identifier)
35713 ), $output, $this->repoDir);
35714
35715 return new \DateTime('@'.trim($output), new \DateTimeZone('UTC'));
35716 }
35717
35718
35719
35720
35721 public function getTags()
35722 {
35723 if (null === $this->tags) {
35724 $this->tags = array();
35725
35726 $this->process->execute('git show-ref --tags --dereference', $output, $this->repoDir);
35727 foreach ($output = $this->process->splitLines($output) as $tag) {
35728 if ($tag && preg_match('{^([a-f0-9]{40}) refs/tags/(\S+?)(\^\{\})?$}', $tag, $match)) {
35729 $this->tags[$match[2]] = $match[1];
35730 }
35731 }
35732 }
35733
35734 return $this->tags;
35735 }
35736
35737
35738
35739
35740 public function getBranches()
35741 {
35742 if (null === $this->branches) {
35743 $branches = array();
35744
35745 $this->process->execute('git branch --no-color --no-abbrev -v', $output, $this->repoDir);
35746 foreach ($this->process->splitLines($output) as $branch) {
35747 if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) {
35748 if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+)(?: .*)?$}', $branch, $match)) {
35749 $branches[$match[1]] = $match[2];
35750 }
35751 }
35752 }
35753
35754 $this->branches = $branches;
35755 }
35756
35757 return $this->branches;
35758 }
35759
35760
35761
35762
35763 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
35764 {
35765 if (preg_match('#(^git://|\.git/?$|git(?:olite)?@|//git\.|//github.com/)#i', $url)) {
35766 return true;
35767 }
35768
35769
35770  if (Filesystem::isLocalPath($url)) {
35771 $url = Filesystem::getPlatformPath($url);
35772 if (!is_dir($url)) {
35773 return false;
35774 }
35775
35776 $process = new ProcessExecutor($io);
35777
35778  if ($process->execute('git tag', $output, $url) === 0) {
35779 return true;
35780 }
35781 }
35782
35783 if (!$deep) {
35784 return false;
35785 }
35786
35787 $process = new ProcessExecutor($io);
35788 if ($process->execute('git ls-remote --heads ' . ProcessExecutor::escape($url), $output) === 0) {
35789 return true;
35790 }
35791
35792 return false;
35793 }
35794 }
35795 <?php
35796
35797
35798
35799
35800
35801
35802
35803
35804
35805
35806
35807 namespace Composer\Repository\Vcs;
35808
35809 use Composer\Config;
35810 use Composer\Downloader\TransportException;
35811 use Composer\Json\JsonFile;
35812 use Composer\Cache;
35813 use Composer\IO\IOInterface;
35814 use Composer\Util\GitHub;
35815
35816
35817
35818
35819 class GitHubDriver extends VcsDriver
35820 {
35821 protected $cache;
35822 protected $owner;
35823 protected $repository;
35824 protected $tags;
35825 protected $branches;
35826 protected $rootIdentifier;
35827 protected $repoData;
35828 protected $hasIssues;
35829 protected $infoCache = array();
35830 protected $isPrivate = false;
35831
35832
35833
35834
35835
35836
35837 protected $gitDriver;
35838
35839
35840
35841
35842 public function initialize()
35843 {
35844 preg_match('#^(?:(?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git|/)?$#', $this->url, $match);
35845 $this->owner = $match[3];
35846 $this->repository = $match[4];
35847 $this->originUrl = !empty($match[1]) ? $match[1] : $match[2];
35848 if ($this->originUrl === 'www.github.com') {
35849 $this->originUrl = 'github.com';
35850 }
35851 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->owner.'/'.$this->repository);
35852
35853 if (isset($this->repoConfig['no-api']) && $this->repoConfig['no-api']) {
35854 $this->setupGitDriver($this->url);
35855
35856 return;
35857 }
35858
35859 $this->fetchRootIdentifier();
35860 }
35861
35862 public function getRepositoryUrl()
35863 {
35864 return 'https://'.$this->originUrl.'/'.$this->owner.'/'.$this->repository;
35865 }
35866
35867
35868
35869
35870 public function getRootIdentifier()
35871 {
35872 if ($this->gitDriver) {
35873 return $this->gitDriver->getRootIdentifier();
35874 }
35875
35876 return $this->rootIdentifier;
35877 }
35878
35879
35880
35881
35882 public function getUrl()
35883 {
35884 if ($this->gitDriver) {
35885 return $this->gitDriver->getUrl();
35886 }
35887
35888 return 'https://' . $this->originUrl . '/'.$this->owner.'/'.$this->repository.'.git';
35889 }
35890
35891
35892
35893
35894 protected function getApiUrl()
35895 {
35896 if ('github.com' === $this->originUrl) {
35897 $apiUrl = 'api.github.com';
35898 } else {
35899 $apiUrl = $this->originUrl . '/api/v3';
35900 }
35901
35902 return 'https://' . $apiUrl;
35903 }
35904
35905
35906
35907
35908 public function getSource($identifier)
35909 {
35910 if ($this->gitDriver) {
35911 return $this->gitDriver->getSource($identifier);
35912 }
35913 if ($this->isPrivate) {
35914
35915  
35916  $url = $this->generateSshUrl();
35917 } else {
35918 $url = $this->getUrl();
35919 }
35920
35921 return array('type' => 'git', 'url' => $url, 'reference' => $identifier);
35922 }
35923
35924
35925
35926
35927 public function getDist($identifier)
35928 {
35929 $url = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/zipball/'.$identifier;
35930
35931 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
35932 }
35933
35934
35935
35936
35937 public function getComposerInformation($identifier)
35938 {
35939 if ($this->gitDriver) {
35940 return $this->gitDriver->getComposerInformation($identifier);
35941 }
35942
35943 if (!isset($this->infoCache[$identifier])) {
35944 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
35945 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
35946 }
35947
35948 $composer = $this->getBaseComposerInformation($identifier);
35949 if ($composer) {
35950
35951
35952  if (!isset($composer['support']['source'])) {
35953 $label = array_search($identifier, $this->getTags()) ?: array_search($identifier, $this->getBranches()) ?: $identifier;
35954 $composer['support']['source'] = sprintf('https://%s/%s/%s/tree/%s', $this->originUrl, $this->owner, $this->repository, $label);
35955 }
35956 if (!isset($composer['support']['issues']) && $this->hasIssues) {
35957 $composer['support']['issues'] = sprintf('https://%s/%s/%s/issues', $this->originUrl, $this->owner, $this->repository);
35958 }
35959 }
35960
35961 if ($this->shouldCache($identifier)) {
35962 $this->cache->write($identifier, json_encode($composer));
35963 }
35964
35965 $this->infoCache[$identifier] = $composer;
35966 }
35967
35968 return $this->infoCache[$identifier];
35969 }
35970
35971
35972
35973
35974 public function getFileContent($file, $identifier)
35975 {
35976 if ($this->gitDriver) {
35977 return $this->gitDriver->getFileContent($file, $identifier);
35978 }
35979
35980 $notFoundRetries = 2;
35981 while ($notFoundRetries) {
35982 try {
35983 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/contents/' . $file . '?ref='.urlencode($identifier);
35984 $resource = JsonFile::parseJson($this->getContents($resource));
35985 if (empty($resource['content']) || $resource['encoding'] !== 'base64' || !($content = base64_decode($resource['content']))) {
35986 throw new \RuntimeException('Could not retrieve ' . $file . ' for '.$identifier);
35987 }
35988
35989 return $content;
35990 } catch (TransportException $e) {
35991 if (404 !== $e->getCode()) {
35992 throw $e;
35993 }
35994
35995
35996  
35997  $notFoundRetries--;
35998
35999 return null;
36000 }
36001 }
36002
36003 return null;
36004 }
36005
36006
36007
36008
36009 public function getChangeDate($identifier)
36010 {
36011 if ($this->gitDriver) {
36012 return $this->gitDriver->getChangeDate($identifier);
36013 }
36014
36015 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/commits/'.urlencode($identifier);
36016 $commit = JsonFile::parseJson($this->getContents($resource), $resource);
36017
36018 return new \DateTime($commit['commit']['committer']['date']);
36019 }
36020
36021
36022
36023
36024 public function getTags()
36025 {
36026 if ($this->gitDriver) {
36027 return $this->gitDriver->getTags();
36028 }
36029 if (null === $this->tags) {
36030 $this->tags = array();
36031 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/tags?per_page=100';
36032
36033 do {
36034 $tagsData = JsonFile::parseJson($this->getContents($resource), $resource);
36035 foreach ($tagsData as $tag) {
36036 $this->tags[$tag['name']] = $tag['commit']['sha'];
36037 }
36038
36039 $resource = $this->getNextPage();
36040 } while ($resource);
36041 }
36042
36043 return $this->tags;
36044 }
36045
36046
36047
36048
36049 public function getBranches()
36050 {
36051 if ($this->gitDriver) {
36052 return $this->gitDriver->getBranches();
36053 }
36054 if (null === $this->branches) {
36055 $this->branches = array();
36056 $resource = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository.'/git/refs/heads?per_page=100';
36057
36058 $branchBlacklist = array('gh-pages');
36059
36060 do {
36061 $branchData = JsonFile::parseJson($this->getContents($resource), $resource);
36062 foreach ($branchData as $branch) {
36063 $name = substr($branch['ref'], 11);
36064 if (!in_array($name, $branchBlacklist)) {
36065 $this->branches[$name] = $branch['object']['sha'];
36066 }
36067 }
36068
36069 $resource = $this->getNextPage();
36070 } while ($resource);
36071 }
36072
36073 return $this->branches;
36074 }
36075
36076
36077
36078
36079 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
36080 {
36081 if (!preg_match('#^((?:https?|git)://([^/]+)/|git@([^:]+):)([^/]+)/(.+?)(?:\.git|/)?$#', $url, $matches)) {
36082 return false;
36083 }
36084
36085 $originUrl = !empty($matches[2]) ? $matches[2] : $matches[3];
36086 if (!in_array(preg_replace('{^www\.}i', '', $originUrl), $config->get('github-domains'))) {
36087 return false;
36088 }
36089
36090 if (!extension_loaded('openssl')) {
36091 $io->writeError('Skipping GitHub driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
36092
36093 return false;
36094 }
36095
36096 return true;
36097 }
36098
36099
36100
36101
36102
36103
36104 public function getRepoData()
36105 {
36106 $this->fetchRootIdentifier();
36107
36108 return $this->repoData;
36109 }
36110
36111
36112
36113
36114
36115
36116 protected function generateSshUrl()
36117 {
36118 return 'git@' . $this->originUrl . ':'.$this->owner.'/'.$this->repository.'.git';
36119 }
36120
36121
36122
36123
36124 protected function getContents($url, $fetchingRepoData = false)
36125 {
36126 try {
36127 return parent::getContents($url);
36128 } catch (TransportException $e) {
36129 $gitHubUtil = new GitHub($this->io, $this->config, $this->process, $this->remoteFilesystem);
36130
36131 switch ($e->getCode()) {
36132 case 401:
36133 case 404:
36134
36135  if (!$fetchingRepoData) {
36136 throw $e;
36137 }
36138
36139 if ($gitHubUtil->authorizeOAuth($this->originUrl)) {
36140 return parent::getContents($url);
36141 }
36142
36143 if (!$this->io->isInteractive()) {
36144 return $this->attemptCloneFallback();
36145 }
36146
36147 $scopesIssued = array();
36148 $scopesNeeded = array();
36149 if ($headers = $e->getHeaders()) {
36150 if ($scopes = $this->remoteFilesystem->findHeaderValue($headers, 'X-OAuth-Scopes')) {
36151 $scopesIssued = explode(' ', $scopes);
36152 }
36153 if ($scopes = $this->remoteFilesystem->findHeaderValue($headers, 'X-Accepted-OAuth-Scopes')) {
36154 $scopesNeeded = explode(' ', $scopes);
36155 }
36156 }
36157 $scopesFailed = array_diff($scopesNeeded, $scopesIssued);
36158 if (!$headers || count($scopesFailed)) {
36159 $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'Your GitHub credentials are required to fetch private repository metadata (<info>'.$this->url.'</info>)');
36160 }
36161
36162 return parent::getContents($url);
36163
36164 case 403:
36165 if (!$this->io->hasAuthentication($this->originUrl) && $gitHubUtil->authorizeOAuth($this->originUrl)) {
36166 return parent::getContents($url);
36167 }
36168
36169 if (!$this->io->isInteractive() && $fetchingRepoData) {
36170 return $this->attemptCloneFallback();
36171 }
36172
36173 $rateLimited = false;
36174 foreach ($e->getHeaders() as $header) {
36175 if (preg_match('{^X-RateLimit-Remaining: *0$}i', trim($header))) {
36176 $rateLimited = true;
36177 }
36178 }
36179
36180 if (!$this->io->hasAuthentication($this->originUrl)) {
36181 if (!$this->io->isInteractive()) {
36182 $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>');
36183 throw $e;
36184 }
36185
36186 $gitHubUtil->authorizeOAuthInteractively($this->originUrl, 'API limit exhausted. Enter your GitHub credentials to get a larger API limit (<info>'.$this->url.'</info>)');
36187
36188 return parent::getContents($url);
36189 }
36190
36191 if ($rateLimited) {
36192 $rateLimit = $this->getRateLimit($e->getHeaders());
36193 $this->io->writeError(sprintf(
36194 '<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>',
36195 $rateLimit['limit'],
36196 $rateLimit['reset']
36197 ));
36198 }
36199
36200 throw $e;
36201
36202 default:
36203 throw $e;
36204 }
36205 }
36206 }
36207
36208
36209
36210
36211
36212
36213
36214
36215 protected function getRateLimit(array $headers)
36216 {
36217 $rateLimit = array(
36218 'limit' => '?',
36219 'reset' => '?',
36220 );
36221
36222 foreach ($headers as $header) {
36223 $header = trim($header);
36224 if (false === strpos($header, 'X-RateLimit-')) {
36225 continue;
36226 }
36227 list($type, $value) = explode(':', $header, 2);
36228 switch ($type) {
36229 case 'X-RateLimit-Limit':
36230 $rateLimit['limit'] = (int) trim($value);
36231 break;
36232 case 'X-RateLimit-Reset':
36233 $rateLimit['reset'] = date('Y-m-d H:i:s', (int) trim($value));
36234 break;
36235 }
36236 }
36237
36238 return $rateLimit;
36239 }
36240
36241
36242
36243
36244
36245
36246 protected function fetchRootIdentifier()
36247 {
36248 if ($this->repoData) {
36249 return;
36250 }
36251
36252 $repoDataUrl = $this->getApiUrl() . '/repos/'.$this->owner.'/'.$this->repository;
36253
36254 $this->repoData = JsonFile::parseJson($this->getContents($repoDataUrl, true), $repoDataUrl);
36255 if (null === $this->repoData && null !== $this->gitDriver) {
36256 return;
36257 }
36258
36259 $this->owner = $this->repoData['owner']['login'];
36260 $this->repository = $this->repoData['name'];
36261
36262 $this->isPrivate = !empty($this->repoData['private']);
36263 if (isset($this->repoData['default_branch'])) {
36264 $this->rootIdentifier = $this->repoData['default_branch'];
36265 } elseif (isset($this->repoData['master_branch'])) {
36266 $this->rootIdentifier = $this->repoData['master_branch'];
36267 } else {
36268 $this->rootIdentifier = 'master';
36269 }
36270 $this->hasIssues = !empty($this->repoData['has_issues']);
36271 }
36272
36273 protected function attemptCloneFallback()
36274 {
36275 $this->isPrivate = true;
36276
36277 try {
36278
36279  
36280  
36281  
36282  $this->setupGitDriver($this->generateSshUrl());
36283
36284 return;
36285 } catch (\RuntimeException $e) {
36286 $this->gitDriver = null;
36287
36288 $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>');
36289 throw $e;
36290 }
36291 }
36292
36293 protected function setupGitDriver($url)
36294 {
36295 $this->gitDriver = new GitDriver(
36296 array('url' => $url),
36297 $this->io,
36298 $this->config,
36299 $this->process,
36300 $this->remoteFilesystem
36301 );
36302 $this->gitDriver->initialize();
36303 }
36304
36305 protected function getNextPage()
36306 {
36307 $headers = $this->remoteFilesystem->getLastHeaders();
36308 foreach ($headers as $header) {
36309 if (substr($header, 0, 5) === 'Link:') {
36310 $links = explode(',', substr($header, 5));
36311 foreach ($links as $link) {
36312 if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) {
36313 return $match[1];
36314 }
36315 }
36316 }
36317 }
36318 }
36319 }
36320 <?php
36321
36322
36323
36324
36325
36326
36327
36328
36329
36330
36331
36332 namespace Composer\Repository\Vcs;
36333
36334 use Composer\Config;
36335 use Composer\Cache;
36336 use Composer\IO\IOInterface;
36337 use Composer\Json\JsonFile;
36338 use Composer\Downloader\TransportException;
36339 use Composer\Util\RemoteFilesystem;
36340 use Composer\Util\GitLab;
36341
36342
36343
36344
36345
36346
36347
36348 class GitLabDriver extends VcsDriver
36349 {
36350 private $scheme;
36351 private $namespace;
36352 private $repository;
36353
36354
36355
36356
36357 private $project;
36358
36359
36360
36361
36362 private $commits = array();
36363
36364
36365
36366
36367 private $tags;
36368
36369
36370
36371
36372 private $branches;
36373
36374
36375
36376
36377
36378
36379 protected $gitDriver;
36380
36381
36382
36383
36384
36385
36386 private $isPrivate = true;
36387
36388 const URL_REGEX = '#^(?:(?P<scheme>https?)://(?P<domain>.+?)/|git@(?P<domain2>[^:]+):)(?P<parts>.+)/(?P<repo>[^/]+?)(?:\.git|/)?$#';
36389
36390
36391
36392
36393
36394
36395
36396
36397 public function initialize()
36398 {
36399 if (!preg_match(self::URL_REGEX, $this->url, $match)) {
36400 throw new \InvalidArgumentException('The URL provided is invalid. It must be the HTTP URL of a GitLab project.');
36401 }
36402
36403 $guessedDomain = !empty($match['domain']) ? $match['domain'] : $match['domain2'];
36404 $configuredDomains = $this->config->get('gitlab-domains');
36405 $urlParts = explode('/', $match['parts']);
36406
36407 $this->scheme = !empty($match['scheme'])
36408 ? $match['scheme']
36409 : (isset($this->repoConfig['secure-http']) && $this->repoConfig['secure-http'] === false ? 'http' : 'https')
36410 ;
36411 $this->originUrl = $this->determineOrigin($configuredDomains, $guessedDomain, $urlParts);
36412 $this->namespace = implode('/', $urlParts);
36413 $this->repository = preg_replace('#(\.git)$#', '', $match['repo']);
36414
36415 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->namespace.'/'.$this->repository);
36416
36417 $this->fetchProject();
36418 }
36419
36420
36421
36422
36423
36424
36425
36426 public function setRemoteFilesystem(RemoteFilesystem $remoteFilesystem)
36427 {
36428 $this->remoteFilesystem = $remoteFilesystem;
36429 }
36430
36431
36432
36433
36434 public function getFileContent($file, $identifier)
36435 {
36436 if ($this->gitDriver) {
36437 return $this->gitDriver->getFileContent($file, $identifier);
36438 }
36439
36440
36441  if (!preg_match('{[a-f0-9]{40}}i', $identifier)) {
36442 $branches = $this->getBranches();
36443 if (isset($branches[$identifier])) {
36444 $identifier = $branches[$identifier];
36445 }
36446 }
36447
36448 $resource = $this->getApiUrl().'/repository/files/'.$this->urlEncodeAll($file).'/raw?ref='.$identifier;
36449
36450 try {
36451 $content = $this->getContents($resource);
36452 } catch (TransportException $e) {
36453 if ($e->getCode() !== 404) {
36454 throw $e;
36455 }
36456
36457 return null;
36458 }
36459
36460 return $content;
36461 }
36462
36463
36464
36465
36466 public function getChangeDate($identifier)
36467 {
36468 if ($this->gitDriver) {
36469 return $this->gitDriver->getChangeDate($identifier);
36470 }
36471
36472 if (isset($this->commits[$identifier])) {
36473 return new \DateTime($this->commits[$identifier]['committed_date']);
36474 }
36475
36476 return new \DateTime();
36477 }
36478
36479
36480
36481
36482 public function getRepositoryUrl()
36483 {
36484 return $this->isPrivate ? $this->project['ssh_url_to_repo'] : $this->project['http_url_to_repo'];
36485 }
36486
36487
36488
36489
36490 public function getUrl()
36491 {
36492 if ($this->gitDriver) {
36493 return $this->gitDriver->getUrl();
36494 }
36495
36496 return $this->project['web_url'];
36497 }
36498
36499
36500
36501
36502 public function getDist($identifier)
36503 {
36504 $url = $this->getApiUrl().'/repository/archive.zip?sha='.$identifier;
36505
36506 return array('type' => 'zip', 'url' => $url, 'reference' => $identifier, 'shasum' => '');
36507 }
36508
36509
36510
36511
36512 public function getSource($identifier)
36513 {
36514 if ($this->gitDriver) {
36515 return $this->gitDriver->getSource($identifier);
36516 }
36517
36518 return array('type' => 'git', 'url' => $this->getRepositoryUrl(), 'reference' => $identifier);
36519 }
36520
36521
36522
36523
36524 public function getRootIdentifier()
36525 {
36526 if ($this->gitDriver) {
36527 return $this->gitDriver->getRootIdentifier();
36528 }
36529
36530 return $this->project['default_branch'];
36531 }
36532
36533
36534
36535
36536 public function getBranches()
36537 {
36538 if ($this->gitDriver) {
36539 return $this->gitDriver->getBranches();
36540 }
36541
36542 if (!$this->branches) {
36543 $this->branches = $this->getReferences('branches');
36544 }
36545
36546 return $this->branches;
36547 }
36548
36549
36550
36551
36552 public function getTags()
36553 {
36554 if ($this->gitDriver) {
36555 return $this->gitDriver->getTags();
36556 }
36557
36558 if (!$this->tags) {
36559 $this->tags = $this->getReferences('tags');
36560 }
36561
36562 return $this->tags;
36563 }
36564
36565
36566
36567
36568 public function getApiUrl()
36569 {
36570 return $this->scheme.'://'.$this->originUrl.'/api/v4/projects/'.$this->urlEncodeAll($this->namespace).'%2F'.$this->urlEncodeAll($this->repository);
36571 }
36572
36573
36574
36575
36576
36577
36578
36579 private function urlEncodeAll($string)
36580 {
36581 $encoded = '';
36582 for ($i = 0; isset($string[$i]); $i++) {
36583 $character = $string[$i];
36584 if (!ctype_alnum($character) && !in_array($character, array('-', '_'), true)) {
36585 $character = '%' . sprintf('%02X', ord($character));
36586 }
36587 $encoded .= $character;
36588 }
36589
36590 return $encoded;
36591 }
36592
36593
36594
36595
36596
36597
36598 protected function getReferences($type)
36599 {
36600 $perPage = 100;
36601 $resource = $this->getApiUrl().'/repository/'.$type.'?per_page='.$perPage;
36602
36603 $references = array();
36604 do {
36605 $data = JsonFile::parseJson($this->getContents($resource), $resource);
36606
36607 foreach ($data as $datum) {
36608 $references[$datum['name']] = $datum['commit']['id'];
36609
36610
36611  
36612  $this->commits[$datum['commit']['id']] = $datum['commit'];
36613 }
36614
36615 if (count($data) >= $perPage) {
36616 $resource = $this->getNextPage();
36617 } else {
36618 $resource = false;
36619 }
36620 } while ($resource);
36621
36622 return $references;
36623 }
36624
36625 protected function fetchProject()
36626 {
36627
36628  $resource = $this->getApiUrl();
36629 $this->project = JsonFile::parseJson($this->getContents($resource, true), $resource);
36630 if (isset($this->project['visibility'])) {
36631 $this->isPrivate = $this->project['visibility'] !== 'public';
36632 } else {
36633
36634  $this->isPrivate = false;
36635 }
36636 }
36637
36638 protected function attemptCloneFallback()
36639 {
36640 try {
36641 if ($this->isPrivate === false) {
36642 $url = $this->generatePublicUrl();
36643 } else {
36644 $url = $this->generateSshUrl();
36645 }
36646
36647
36648  
36649  
36650  $this->setupGitDriver($url);
36651
36652 return;
36653 } catch (\RuntimeException $e) {
36654 $this->gitDriver = null;
36655
36656 $this->io->writeError('<error>Failed to clone the '.$url.' repository, try running in interactive mode so that you can enter your credentials</error>');
36657 throw $e;
36658 }
36659 }
36660
36661
36662
36663
36664
36665
36666 protected function generateSshUrl()
36667 {
36668 return 'git@' . $this->originUrl . ':'.$this->namespace.'/'.$this->repository.'.git';
36669 }
36670
36671 protected function generatePublicUrl()
36672 {
36673 return 'https://' . $this->originUrl . '/'.$this->namespace.'/'.$this->repository.'.git';
36674 }
36675
36676 protected function setupGitDriver($url)
36677 {
36678 $this->gitDriver = new GitDriver(
36679 array('url' => $url),
36680 $this->io,
36681 $this->config,
36682 $this->process,
36683 $this->remoteFilesystem
36684 );
36685 $this->gitDriver->initialize();
36686 }
36687
36688
36689
36690
36691 protected function getContents($url, $fetchingRepoData = false)
36692 {
36693 try {
36694 $res = parent::getContents($url);
36695
36696 if ($fetchingRepoData) {
36697 $json = JsonFile::parseJson($res, $url);
36698
36699
36700  if (!isset($json['default_branch'])) {
36701 if (!empty($json['id'])) {
36702 $this->isPrivate = false;
36703 }
36704
36705 throw new TransportException('GitLab API seems to not be authenticated as it did not return a default_branch', 401);
36706 }
36707 }
36708
36709 return $res;
36710 } catch (TransportException $e) {
36711 $gitLabUtil = new GitLab($this->io, $this->config, $this->process, $this->remoteFilesystem);
36712
36713 switch ($e->getCode()) {
36714 case 401:
36715 case 404:
36716
36717  if (!$fetchingRepoData) {
36718 throw $e;
36719 }
36720
36721 if ($gitLabUtil->authorizeOAuth($this->originUrl)) {
36722 return parent::getContents($url);
36723 }
36724
36725 if (!$this->io->isInteractive()) {
36726 return $this->attemptCloneFallback();
36727 }
36728 $this->io->writeError('<warning>Failed to download ' . $this->namespace . '/' . $this->repository . ':' . $e->getMessage() . '</warning>');
36729 $gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, 'Your credentials are required to fetch private repository metadata (<info>'.$this->url.'</info>)');
36730
36731 return parent::getContents($url);
36732
36733 case 403:
36734 if (!$this->io->hasAuthentication($this->originUrl) && $gitLabUtil->authorizeOAuth($this->originUrl)) {
36735 return parent::getContents($url);
36736 }
36737
36738 if (!$this->io->isInteractive() && $fetchingRepoData) {
36739 return $this->attemptCloneFallback();
36740 }
36741
36742 throw $e;
36743
36744 default:
36745 throw $e;
36746 }
36747 }
36748 }
36749
36750
36751
36752
36753
36754
36755
36756 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
36757 {
36758 if (!preg_match(self::URL_REGEX, $url, $match)) {
36759 return false;
36760 }
36761
36762 $scheme = !empty($match['scheme']) ? $match['scheme'] : null;
36763 $guessedDomain = !empty($match['domain']) ? $match['domain'] : $match['domain2'];
36764 $urlParts = explode('/', $match['parts']);
36765
36766 if (false === self::determineOrigin((array) $config->get('gitlab-domains'), $guessedDomain, $urlParts)) {
36767 return false;
36768 }
36769
36770 if ('https' === $scheme && !extension_loaded('openssl')) {
36771 $io->writeError('Skipping GitLab driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
36772
36773 return false;
36774 }
36775
36776 return true;
36777 }
36778
36779 private function getNextPage()
36780 {
36781 $headers = $this->remoteFilesystem->getLastHeaders();
36782 foreach ($headers as $header) {
36783 if (preg_match('{^link:\s*(.+?)\s*$}i', $header, $match)) {
36784 $links = explode(',', $match[1]);
36785 foreach ($links as $link) {
36786 if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) {
36787 return $match[1];
36788 }
36789 }
36790 }
36791 }
36792 }
36793
36794
36795
36796
36797
36798
36799
36800 private static function determineOrigin(array $configuredDomains, $guessedDomain, array &$urlParts)
36801 {
36802 if (in_array($guessedDomain, $configuredDomains)) {
36803 return $guessedDomain;
36804 }
36805
36806 while (null !== ($part = array_shift($urlParts))) {
36807 $guessedDomain .= '/' . $part;
36808
36809 if (in_array($guessedDomain, $configuredDomains)) {
36810 return $guessedDomain;
36811 }
36812 }
36813
36814 return false;
36815 }
36816 }
36817 <?php
36818
36819
36820
36821
36822
36823
36824
36825
36826
36827
36828
36829 namespace Composer\Repository\Vcs;
36830
36831 use Composer\Config;
36832 use Composer\IO\IOInterface;
36833
36834
36835
36836
36837 class HgBitbucketDriver extends BitbucketDriver
36838 {
36839
36840
36841
36842 public function getRootIdentifier()
36843 {
36844 if ($this->fallbackDriver) {
36845 return $this->fallbackDriver->getRootIdentifier();
36846 }
36847
36848 if (null === $this->rootIdentifier) {
36849 if (! $this->getRepoData()) {
36850 return $this->fallbackDriver->getRootIdentifier();
36851 }
36852
36853 if ($this->vcsType !== 'hg') {
36854 throw new \RuntimeException(
36855 $this->url.' does not appear to be a mercurial repository, use '.
36856 $this->cloneHttpsUrl.' if this is a git bitbucket repository'
36857 );
36858 }
36859
36860 $mainBranchData = $this->getMainBranchData();
36861 $this->rootIdentifier = !empty($mainBranchData['name']) ? $mainBranchData['name'] : 'default';
36862 }
36863
36864 return $this->rootIdentifier;
36865 }
36866
36867
36868
36869
36870 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
36871 {
36872 if (!preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+)/?$#', $url)) {
36873 return false;
36874 }
36875
36876 if (!extension_loaded('openssl')) {
36877 $io->writeError('Skipping Bitbucket hg driver for '.$url.' because the OpenSSL PHP extension is missing.', true, IOInterface::VERBOSE);
36878
36879 return false;
36880 }
36881
36882 return true;
36883 }
36884
36885
36886
36887
36888 protected function setupFallbackDriver($url)
36889 {
36890 $this->fallbackDriver = new HgDriver(
36891 array('url' => $url),
36892 $this->io,
36893 $this->config,
36894 $this->process,
36895 $this->remoteFilesystem
36896 );
36897 $this->fallbackDriver->initialize();
36898 }
36899
36900
36901
36902
36903 protected function generateSshUrl()
36904 {
36905 return 'ssh://hg@' . $this->originUrl . '/' . $this->owner.'/'.$this->repository;
36906 }
36907 }
36908 <?php
36909
36910
36911
36912
36913
36914
36915
36916
36917
36918
36919
36920 namespace Composer\Repository\Vcs;
36921
36922 use Composer\Config;
36923 use Composer\Util\ProcessExecutor;
36924 use Composer\Util\Filesystem;
36925 use Composer\IO\IOInterface;
36926
36927
36928
36929
36930 class HgDriver extends VcsDriver
36931 {
36932 protected $tags;
36933 protected $branches;
36934 protected $rootIdentifier;
36935 protected $repoDir;
36936 protected $infoCache = array();
36937
36938
36939
36940
36941 public function initialize()
36942 {
36943 if (Filesystem::isLocalPath($this->url)) {
36944 $this->repoDir = $this->url;
36945 } else {
36946 $cacheDir = $this->config->get('cache-vcs-dir');
36947 $this->repoDir = $cacheDir . '/' . preg_replace('{[^a-z0-9]}i', '-', $this->url) . '/';
36948
36949 $fs = new Filesystem();
36950 $fs->ensureDirectoryExists($cacheDir);
36951
36952 if (!is_writable(dirname($this->repoDir))) {
36953 throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.$cacheDir.'" directory is not writable by the current user.');
36954 }
36955
36956
36957  $this->config->prohibitUrlByConfig($this->url, $this->io);
36958
36959
36960  if (is_dir($this->repoDir) && 0 === $this->process->execute('hg summary', $output, $this->repoDir)) {
36961 if (0 !== $this->process->execute('hg pull', $output, $this->repoDir)) {
36962 $this->io->writeError('<error>Failed to update '.$this->url.', package information from this repository may be outdated ('.$this->process->getErrorOutput().')</error>');
36963 }
36964 } else {
36965
36966  $fs->removeDirectory($this->repoDir);
36967
36968 if (0 !== $this->process->execute(sprintf('hg clone --noupdate %s %s', ProcessExecutor::escape($this->url), ProcessExecutor::escape($this->repoDir)), $output, $cacheDir)) {
36969 $output = $this->process->getErrorOutput();
36970
36971 if (0 !== $this->process->execute('hg --version', $ignoredOutput)) {
36972 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());
36973 }
36974
36975 throw new \RuntimeException('Failed to clone '.$this->url.', could not read packages from it' . "\n\n" .$output);
36976 }
36977 }
36978 }
36979
36980 $this->getTags();
36981 $this->getBranches();
36982 }
36983
36984
36985
36986
36987 public function getRootIdentifier()
36988 {
36989 if (null === $this->rootIdentifier) {
36990 $this->process->execute(sprintf('hg tip --template "{node}"'), $output, $this->repoDir);
36991 $output = $this->process->splitLines($output);
36992 $this->rootIdentifier = $output[0];
36993 }
36994
36995 return $this->rootIdentifier;
36996 }
36997
36998
36999
37000
37001 public function getUrl()
37002 {
37003 return $this->url;
37004 }
37005
37006
37007
37008
37009 public function getSource($identifier)
37010 {
37011 return array('type' => 'hg', 'url' => $this->getUrl(), 'reference' => $identifier);
37012 }
37013
37014
37015
37016
37017 public function getDist($identifier)
37018 {
37019 return null;
37020 }
37021
37022
37023
37024
37025 public function getFileContent($file, $identifier)
37026 {
37027 $resource = sprintf('hg cat -r %s %s', ProcessExecutor::escape($identifier), ProcessExecutor::escape($file));
37028 $this->process->execute($resource, $content, $this->repoDir);
37029
37030 if (!trim($content)) {
37031 return;
37032 }
37033
37034 return $content;
37035 }
37036
37037
37038
37039
37040 public function getChangeDate($identifier)
37041 {
37042 $this->process->execute(
37043 sprintf(
37044 'hg log --template "{date|rfc3339date}" -r %s',
37045 ProcessExecutor::escape($identifier)
37046 ),
37047 $output,
37048 $this->repoDir
37049 );
37050
37051 return new \DateTime(trim($output), new \DateTimeZone('UTC'));
37052 }
37053
37054
37055
37056
37057 public function getTags()
37058 {
37059 if (null === $this->tags) {
37060 $tags = array();
37061
37062 $this->process->execute('hg tags', $output, $this->repoDir);
37063 foreach ($this->process->splitLines($output) as $tag) {
37064 if ($tag && preg_match('(^([^\s]+)\s+\d+:(.*)$)', $tag, $match)) {
37065 $tags[$match[1]] = $match[2];
37066 }
37067 }
37068 unset($tags['tip']);
37069
37070 $this->tags = $tags;
37071 }
37072
37073 return $this->tags;
37074 }
37075
37076
37077
37078
37079 public function getBranches()
37080 {
37081 if (null === $this->branches) {
37082 $branches = array();
37083 $bookmarks = array();
37084
37085 $this->process->execute('hg branches', $output, $this->repoDir);
37086 foreach ($this->process->splitLines($output) as $branch) {
37087 if ($branch && preg_match('(^([^\s]+)\s+\d+:([a-f0-9]+))', $branch, $match)) {
37088 $branches[$match[1]] = $match[2];
37089 }
37090 }
37091
37092 $this->process->execute('hg bookmarks', $output, $this->repoDir);
37093 foreach ($this->process->splitLines($output) as $branch) {
37094 if ($branch && preg_match('(^(?:[\s*]*)([^\s]+)\s+\d+:(.*)$)', $branch, $match)) {
37095 $bookmarks[$match[1]] = $match[2];
37096 }
37097 }
37098
37099
37100  $this->branches = array_merge($bookmarks, $branches);
37101 }
37102
37103 return $this->branches;
37104 }
37105
37106
37107
37108
37109 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37110 {
37111 if (preg_match('#(^(?:https?|ssh)://(?:[^@]+@)?bitbucket.org|https://(?:.*?)\.kilnhg.com)#i', $url)) {
37112 return true;
37113 }
37114
37115
37116  if (Filesystem::isLocalPath($url)) {
37117 $url = Filesystem::getPlatformPath($url);
37118 if (!is_dir($url)) {
37119 return false;
37120 }
37121
37122 $process = new ProcessExecutor();
37123
37124  if ($process->execute('hg summary', $output, $url) === 0) {
37125 return true;
37126 }
37127 }
37128
37129 if (!$deep) {
37130 return false;
37131 }
37132
37133 $processExecutor = new ProcessExecutor();
37134 $exit = $processExecutor->execute(sprintf('hg identify %s', ProcessExecutor::escape($url)), $ignored);
37135
37136 return $exit === 0;
37137 }
37138 }
37139 <?php
37140
37141
37142
37143
37144
37145
37146
37147
37148
37149
37150
37151 namespace Composer\Repository\Vcs;
37152
37153 use Composer\Config;
37154 use Composer\IO\IOInterface;
37155 use Composer\Util\ProcessExecutor;
37156 use Composer\Util\Perforce;
37157
37158
37159
37160
37161 class PerforceDriver extends VcsDriver
37162 {
37163 protected $depot;
37164 protected $branch;
37165
37166 protected $perforce;
37167
37168
37169
37170
37171 public function initialize()
37172 {
37173 $this->depot = $this->repoConfig['depot'];
37174 $this->branch = '';
37175 if (!empty($this->repoConfig['branch'])) {
37176 $this->branch = $this->repoConfig['branch'];
37177 }
37178
37179 $this->initPerforce($this->repoConfig);
37180 $this->perforce->p4Login();
37181 $this->perforce->checkStream();
37182
37183 $this->perforce->writeP4ClientSpec();
37184 $this->perforce->connectClient();
37185
37186 return true;
37187 }
37188
37189 private function initPerforce($repoConfig)
37190 {
37191 if (!empty($this->perforce)) {
37192 return;
37193 }
37194
37195 $repoDir = $this->config->get('cache-vcs-dir') . '/' . $this->depot;
37196 $this->perforce = Perforce::create($repoConfig, $this->getUrl(), $repoDir, $this->process, $this->io);
37197 }
37198
37199
37200
37201
37202 public function getFileContent($file, $identifier)
37203 {
37204 return $this->perforce->getFileContent($file, $identifier);
37205 }
37206
37207
37208
37209
37210 public function getChangeDate($identifier)
37211 {
37212 return null;
37213 }
37214
37215
37216
37217
37218 public function getRootIdentifier()
37219 {
37220 return $this->branch;
37221 }
37222
37223
37224
37225
37226 public function getBranches()
37227 {
37228 $branches = $this->perforce->getBranches();
37229
37230 return $branches;
37231 }
37232
37233
37234
37235
37236 public function getTags()
37237 {
37238 $tags = $this->perforce->getTags();
37239
37240 return $tags;
37241 }
37242
37243
37244
37245
37246 public function getDist($identifier)
37247 {
37248 return null;
37249 }
37250
37251
37252
37253
37254 public function getSource($identifier)
37255 {
37256 $source = array(
37257 'type' => 'perforce',
37258 'url' => $this->repoConfig['url'],
37259 'reference' => $identifier,
37260 'p4user' => $this->perforce->getUser(),
37261 );
37262
37263 return $source;
37264 }
37265
37266
37267
37268
37269 public function getUrl()
37270 {
37271 return $this->url;
37272 }
37273
37274
37275
37276
37277 public function hasComposerFile($identifier)
37278 {
37279 $composerInfo = $this->perforce->getComposerInformation('//' . $this->depot . '/' . $identifier);
37280 $composerInfoIdentifier = $identifier;
37281
37282 return !empty($composerInfo);
37283 }
37284
37285
37286
37287
37288 public function getContents($url)
37289 {
37290 return false;
37291 }
37292
37293
37294
37295
37296 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37297 {
37298 if ($deep || preg_match('#\b(perforce|p4)\b#i', $url)) {
37299 return Perforce::checkServerExists($url, new ProcessExecutor($io));
37300 }
37301
37302 return false;
37303 }
37304
37305
37306
37307
37308 public function cleanup()
37309 {
37310 $this->perforce->cleanupClientSpec();
37311 $this->perforce = null;
37312 }
37313
37314 public function getDepot()
37315 {
37316 return $this->depot;
37317 }
37318
37319 public function getBranch()
37320 {
37321 return $this->branch;
37322 }
37323 }
37324 <?php
37325
37326
37327
37328
37329
37330
37331
37332
37333
37334
37335
37336 namespace Composer\Repository\Vcs;
37337
37338 use Composer\Cache;
37339 use Composer\Config;
37340 use Composer\Json\JsonFile;
37341 use Composer\Util\ProcessExecutor;
37342 use Composer\Util\Filesystem;
37343 use Composer\Util\Svn as SvnUtil;
37344 use Composer\IO\IOInterface;
37345 use Composer\Downloader\TransportException;
37346
37347
37348
37349
37350
37351 class SvnDriver extends VcsDriver
37352 {
37353
37354
37355
37356 protected $cache;
37357 protected $baseUrl;
37358 protected $tags;
37359 protected $branches;
37360 protected $rootIdentifier;
37361 protected $infoCache = array();
37362
37363 protected $trunkPath = 'trunk';
37364 protected $branchesPath = 'branches';
37365 protected $tagsPath = 'tags';
37366 protected $packagePath = '';
37367 protected $cacheCredentials = true;
37368
37369
37370
37371
37372 private $util;
37373
37374
37375
37376
37377 public function initialize()
37378 {
37379 $this->url = $this->baseUrl = rtrim(self::normalizeUrl($this->url), '/');
37380
37381 SvnUtil::cleanEnv();
37382
37383 if (isset($this->repoConfig['trunk-path'])) {
37384 $this->trunkPath = $this->repoConfig['trunk-path'];
37385 }
37386 if (isset($this->repoConfig['branches-path'])) {
37387 $this->branchesPath = $this->repoConfig['branches-path'];
37388 }
37389 if (isset($this->repoConfig['tags-path'])) {
37390 $this->tagsPath = $this->repoConfig['tags-path'];
37391 }
37392 if (array_key_exists('svn-cache-credentials', $this->repoConfig)) {
37393 $this->cacheCredentials = (bool) $this->repoConfig['svn-cache-credentials'];
37394 }
37395 if (isset($this->repoConfig['package-path'])) {
37396 $this->packagePath = '/' . trim($this->repoConfig['package-path'], '/');
37397 }
37398
37399 if (false !== ($pos = strrpos($this->url, '/' . $this->trunkPath))) {
37400 $this->baseUrl = substr($this->url, 0, $pos);
37401 }
37402
37403 $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $this->baseUrl));
37404
37405 $this->getBranches();
37406 $this->getTags();
37407 }
37408
37409
37410
37411
37412 public function getRootIdentifier()
37413 {
37414 return $this->rootIdentifier ?: $this->trunkPath;
37415 }
37416
37417
37418
37419
37420 public function getUrl()
37421 {
37422 return $this->url;
37423 }
37424
37425
37426
37427
37428 public function getSource($identifier)
37429 {
37430 return array('type' => 'svn', 'url' => $this->baseUrl, 'reference' => $identifier);
37431 }
37432
37433
37434
37435
37436 public function getDist($identifier)
37437 {
37438 return null;
37439 }
37440
37441
37442
37443
37444 public function getComposerInformation($identifier)
37445 {
37446 if (!isset($this->infoCache[$identifier])) {
37447 if ($res = $this->cache->read($identifier.'.json')) {
37448 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
37449 }
37450
37451 $composer = $this->getBaseComposerInformation($identifier);
37452
37453 $this->cache->write($identifier.'.json', json_encode($composer));
37454
37455 $this->infoCache[$identifier] = $composer;
37456 }
37457
37458 return $this->infoCache[$identifier];
37459 }
37460
37461
37462
37463
37464
37465 public function getFileContent($file, $identifier)
37466 {
37467 $identifier = '/' . trim($identifier, '/') . '/';
37468
37469 preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match);
37470 if (!empty($match[2])) {
37471 $path = $match[1];
37472 $rev = $match[2];
37473 } else {
37474 $path = $identifier;
37475 $rev = '';
37476 }
37477
37478 try {
37479 $resource = $path.$file;
37480 $output = $this->execute('svn cat', $this->baseUrl . $resource . $rev);
37481 if (!trim($output)) {
37482 return null;
37483 }
37484 } catch (\RuntimeException $e) {
37485 throw new TransportException($e->getMessage());
37486 }
37487
37488 return $output;
37489 }
37490
37491
37492
37493
37494 public function getChangeDate($identifier)
37495 {
37496 $identifier = '/' . trim($identifier, '/') . '/';
37497
37498 preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match);
37499 if (!empty($match[2])) {
37500 $path = $match[1];
37501 $rev = $match[2];
37502 } else {
37503 $path = $identifier;
37504 $rev = '';
37505 }
37506
37507 $output = $this->execute('svn info', $this->baseUrl . $path . $rev);
37508 foreach ($this->process->splitLines($output) as $line) {
37509 if ($line && preg_match('{^Last Changed Date: ([^(]+)}', $line, $match)) {
37510 return new \DateTime($match[1], new \DateTimeZone('UTC'));
37511 }
37512 }
37513
37514 return null;
37515 }
37516
37517
37518
37519
37520 public function getTags()
37521 {
37522 if (null === $this->tags) {
37523 $this->tags = array();
37524
37525 if ($this->tagsPath !== false) {
37526 $output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->tagsPath);
37527 if ($output) {
37528 foreach ($this->process->splitLines($output) as $line) {
37529 $line = trim($line);
37530 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
37531 if (isset($match[1]) && isset($match[2]) && $match[2] !== './') {
37532 $this->tags[rtrim($match[2], '/')] = $this->buildIdentifier(
37533 '/' . $this->tagsPath . '/' . $match[2],
37534 $match[1]
37535 );
37536 }
37537 }
37538 }
37539 }
37540 }
37541 }
37542
37543 return $this->tags;
37544 }
37545
37546
37547
37548
37549 public function getBranches()
37550 {
37551 if (null === $this->branches) {
37552 $this->branches = array();
37553
37554 if (false === $this->trunkPath) {
37555 $trunkParent = $this->baseUrl . '/';
37556 } else {
37557 $trunkParent = $this->baseUrl . '/' . $this->trunkPath;
37558 }
37559
37560 $output = $this->execute('svn ls --verbose', $trunkParent);
37561 if ($output) {
37562 foreach ($this->process->splitLines($output) as $line) {
37563 $line = trim($line);
37564 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
37565 if (isset($match[1]) && isset($match[2]) && $match[2] === './') {
37566 $this->branches['trunk'] = $this->buildIdentifier(
37567 '/' . $this->trunkPath,
37568 $match[1]
37569 );
37570 $this->rootIdentifier = $this->branches['trunk'];
37571 break;
37572 }
37573 }
37574 }
37575 }
37576 unset($output);
37577
37578 if ($this->branchesPath !== false) {
37579 $output = $this->execute('svn ls --verbose', $this->baseUrl . '/' . $this->branchesPath);
37580 if ($output) {
37581 foreach ($this->process->splitLines(trim($output)) as $line) {
37582 $line = trim($line);
37583 if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) {
37584 if (isset($match[1]) && isset($match[2]) && $match[2] !== './') {
37585 $this->branches[rtrim($match[2], '/')] = $this->buildIdentifier(
37586 '/' . $this->branchesPath . '/' . $match[2],
37587 $match[1]
37588 );
37589 }
37590 }
37591 }
37592 }
37593 }
37594 }
37595
37596 return $this->branches;
37597 }
37598
37599
37600
37601
37602 public static function supports(IOInterface $io, Config $config, $url, $deep = false)
37603 {
37604 $url = self::normalizeUrl($url);
37605 if (preg_match('#(^svn://|^svn\+ssh://|svn\.)#i', $url)) {
37606 return true;
37607 }
37608
37609
37610  if (!$deep && !Filesystem::isLocalPath($url)) {
37611 return false;
37612 }
37613
37614 $processExecutor = new ProcessExecutor();
37615
37616 $exit = $processExecutor->execute(
37617 "svn info --non-interactive {$url}",
37618 $ignoredOutput
37619 );
37620
37621 if ($exit === 0) {
37622
37623  return true;
37624 }
37625
37626
37627  if (false !== stripos($processExecutor->getErrorOutput(), 'authorization failed:')) {
37628
37629  
37630  return true;
37631 }
37632
37633
37634  if (false !== stripos($processExecutor->getErrorOutput(), 'Authentication failed')) {
37635
37636  
37637  return true;
37638 }
37639
37640 return false;
37641 }
37642
37643
37644
37645
37646
37647
37648
37649
37650 protected static function normalizeUrl($url)
37651 {
37652 $fs = new Filesystem();
37653 if ($fs->isAbsolutePath($url)) {
37654 return 'file://' . strtr($url, '\\', '/');
37655 }
37656
37657 return $url;
37658 }
37659
37660
37661
37662
37663
37664
37665
37666
37667
37668
37669 protected function execute($command, $url)
37670 {
37671 if (null === $this->util) {
37672 $this->util = new SvnUtil($this->baseUrl, $this->io, $this->config, $this->process);
37673 $this->util->setCacheCredentials($this->cacheCredentials);
37674 }
37675
37676 try {
37677 return $this->util->execute($command, $url);
37678 } catch (\RuntimeException $e) {
37679 if (0 !== $this->process->execute('svn --version', $ignoredOutput)) {
37680 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());
37681 }
37682
37683 throw new \RuntimeException(
37684 'Repository '.$this->url.' could not be processed, '.$e->getMessage()
37685 );
37686 }
37687 }
37688
37689
37690
37691
37692
37693
37694
37695
37696
37697 protected function buildIdentifier($baseDir, $revision)
37698 {
37699 return rtrim($baseDir, '/') . $this->packagePath . '/@' . $revision;
37700 }
37701 }
37702 <?php
37703
37704
37705
37706
37707
37708
37709
37710
37711
37712
37713
37714 namespace Composer\Repository\Vcs;
37715
37716 use Composer\Cache;
37717 use Composer\Downloader\TransportException;
37718 use Composer\Config;
37719 use Composer\Factory;
37720 use Composer\IO\IOInterface;
37721 use Composer\Json\JsonFile;
37722 use Composer\Util\ProcessExecutor;
37723 use Composer\Util\RemoteFilesystem;
37724 use Composer\Util\Filesystem;
37725
37726
37727
37728
37729
37730
37731 abstract class VcsDriver implements VcsDriverInterface
37732 {
37733
37734 protected $url;
37735
37736 protected $originUrl;
37737
37738 protected $repoConfig;
37739
37740 protected $io;
37741
37742 protected $config;
37743
37744 protected $process;
37745
37746 protected $remoteFilesystem;
37747
37748 protected $infoCache = array();
37749
37750 protected $cache;
37751
37752
37753
37754
37755
37756
37757
37758
37759
37760
37761 final public function __construct(array $repoConfig, IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
37762 {
37763 if (Filesystem::isLocalPath($repoConfig['url'])) {
37764 $repoConfig['url'] = Filesystem::getPlatformPath($repoConfig['url']);
37765 }
37766
37767 $this->url = $repoConfig['url'];
37768 $this->originUrl = $repoConfig['url'];
37769 $this->repoConfig = $repoConfig;
37770 $this->io = $io;
37771 $this->config = $config;
37772 $this->process = $process ?: new ProcessExecutor($io);
37773 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
37774 }
37775
37776
37777
37778
37779
37780
37781
37782 protected function shouldCache($identifier)
37783 {
37784 return $this->cache && preg_match('{[a-f0-9]{40}}i', $identifier);
37785 }
37786
37787
37788
37789
37790 public function getComposerInformation($identifier)
37791 {
37792 if (!isset($this->infoCache[$identifier])) {
37793 if ($this->shouldCache($identifier) && $res = $this->cache->read($identifier)) {
37794 return $this->infoCache[$identifier] = JsonFile::parseJson($res);
37795 }
37796
37797 $composer = $this->getBaseComposerInformation($identifier);
37798
37799 if ($this->shouldCache($identifier)) {
37800 $this->cache->write($identifier, json_encode($composer));
37801 }
37802
37803 $this->infoCache[$identifier] = $composer;
37804 }
37805
37806 return $this->infoCache[$identifier];
37807 }
37808
37809 protected function getBaseComposerInformation($identifier)
37810 {
37811 $composerFileContent = $this->getFileContent('composer.json', $identifier);
37812
37813 if (!$composerFileContent) {
37814 return null;
37815 }
37816
37817 $composer = JsonFile::parseJson($composerFileContent, $identifier . ':composer.json');
37818
37819 if (empty($composer['time']) && $changeDate = $this->getChangeDate($identifier)) {
37820 $composer['time'] = $changeDate->format(DATE_RFC3339);
37821 }
37822
37823 return $composer;
37824 }
37825
37826
37827
37828
37829 public function hasComposerFile($identifier)
37830 {
37831 try {
37832 return (bool) $this->getComposerInformation($identifier);
37833 } catch (TransportException $e) {
37834 }
37835
37836 return false;
37837 }
37838
37839
37840
37841
37842
37843
37844
37845
37846 protected function getScheme()
37847 {
37848 if (extension_loaded('openssl')) {
37849 return 'https';
37850 }
37851
37852 return 'http';
37853 }
37854
37855
37856
37857
37858
37859
37860
37861
37862 protected function getContents($url)
37863 {
37864 $options = isset($this->repoConfig['options']) ? $this->repoConfig['options'] : array();
37865
37866 return $this->remoteFilesystem->getContents($this->originUrl, $url, false, $options);
37867 }
37868
37869
37870
37871
37872 public function cleanup()
37873 {
37874 return;
37875 }
37876 }
37877 <?php
37878
37879
37880
37881
37882
37883
37884
37885
37886
37887
37888
37889 namespace Composer\Repository\Vcs;
37890
37891 use Composer\Config;
37892 use Composer\IO\IOInterface;
37893
37894
37895
37896
37897 interface VcsDriverInterface
37898 {
37899
37900
37901
37902 public function initialize();
37903
37904
37905
37906
37907
37908
37909
37910 public function getComposerInformation($identifier);
37911
37912
37913
37914
37915
37916
37917
37918
37919 public function getFileContent($file, $identifier);
37920
37921
37922
37923
37924
37925
37926
37927 public function getChangeDate($identifier);
37928
37929
37930
37931
37932
37933
37934 public function getRootIdentifier();
37935
37936
37937
37938
37939
37940
37941 public function getBranches();
37942
37943
37944
37945
37946
37947
37948 public function getTags();
37949
37950
37951
37952
37953
37954 public function getDist($identifier);
37955
37956
37957
37958
37959
37960 public function getSource($identifier);
37961
37962
37963
37964
37965
37966
37967 public function getUrl();
37968
37969
37970
37971
37972
37973
37974
37975
37976 public function hasComposerFile($identifier);
37977
37978
37979
37980
37981 public function cleanup();
37982
37983
37984
37985
37986
37987
37988
37989
37990
37991
37992 public static function supports(IOInterface $io, Config $config, $url, $deep = false);
37993 }
37994 <?php
37995
37996
37997
37998
37999
38000
38001
38002
38003
38004
38005
38006 namespace Composer\Repository;
38007
38008 use Composer\Downloader\TransportException;
38009 use Composer\Repository\Vcs\VcsDriverInterface;
38010 use Composer\Package\Version\VersionParser;
38011 use Composer\Package\Loader\ArrayLoader;
38012 use Composer\Package\Loader\ValidatingArrayLoader;
38013 use Composer\Package\Loader\InvalidPackageException;
38014 use Composer\Package\Loader\LoaderInterface;
38015 use Composer\EventDispatcher\EventDispatcher;
38016 use Composer\IO\IOInterface;
38017 use Composer\Config;
38018
38019
38020
38021
38022 class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInterface
38023 {
38024 protected $url;
38025 protected $packageName;
38026 protected $verbose;
38027 protected $io;
38028 protected $config;
38029 protected $versionParser;
38030 protected $type;
38031 protected $loader;
38032 protected $repoConfig;
38033 protected $branchErrorOccurred = false;
38034 private $drivers;
38035
38036 private $driver;
38037
38038 public function __construct(array $repoConfig, IOInterface $io, Config $config, EventDispatcher $dispatcher = null, array $drivers = null)
38039 {
38040 parent::__construct();
38041 $this->drivers = $drivers ?: array(
38042 'github' => 'Composer\Repository\Vcs\GitHubDriver',
38043 'gitlab' => 'Composer\Repository\Vcs\GitLabDriver',
38044 'git-bitbucket' => 'Composer\Repository\Vcs\GitBitbucketDriver',
38045 'git' => 'Composer\Repository\Vcs\GitDriver',
38046 'hg-bitbucket' => 'Composer\Repository\Vcs\HgBitbucketDriver',
38047 'hg' => 'Composer\Repository\Vcs\HgDriver',
38048 'perforce' => 'Composer\Repository\Vcs\PerforceDriver',
38049 'fossil' => 'Composer\Repository\Vcs\FossilDriver',
38050
38051  'svn' => 'Composer\Repository\Vcs\SvnDriver',
38052 );
38053
38054 $this->url = $repoConfig['url'];
38055 $this->io = $io;
38056 $this->type = isset($repoConfig['type']) ? $repoConfig['type'] : 'vcs';
38057 $this->verbose = $io->isVeryVerbose();
38058 $this->config = $config;
38059 $this->repoConfig = $repoConfig;
38060 }
38061
38062 public function getRepoConfig()
38063 {
38064 return $this->repoConfig;
38065 }
38066
38067 public function setLoader(LoaderInterface $loader)
38068 {
38069 $this->loader = $loader;
38070 }
38071
38072 public function getDriver()
38073 {
38074 if ($this->driver) {
38075 return $this->driver;
38076 }
38077
38078 if (isset($this->drivers[$this->type])) {
38079 $class = $this->drivers[$this->type];
38080 $this->driver = new $class($this->repoConfig, $this->io, $this->config);
38081 $this->driver->initialize();
38082
38083 return $this->driver;
38084 }
38085
38086 foreach ($this->drivers as $driver) {
38087 if ($driver::supports($this->io, $this->config, $this->url)) {
38088 $this->driver = new $driver($this->repoConfig, $this->io, $this->config);
38089 $this->driver->initialize();
38090
38091 return $this->driver;
38092 }
38093 }
38094
38095 foreach ($this->drivers as $driver) {
38096 if ($driver::supports($this->io, $this->config, $this->url, true)) {
38097 $this->driver = new $driver($this->repoConfig, $this->io, $this->config);
38098 $this->driver->initialize();
38099
38100 return $this->driver;
38101 }
38102 }
38103 }
38104
38105 public function hadInvalidBranches()
38106 {
38107 return $this->branchErrorOccurred;
38108 }
38109
38110 protected function initialize()
38111 {
38112 parent::initialize();
38113
38114 $verbose = $this->verbose;
38115
38116 $driver = $this->getDriver();
38117 if (!$driver) {
38118 throw new \InvalidArgumentException('No driver found to handle VCS repository '.$this->url);
38119 }
38120
38121 $this->versionParser = new VersionParser;
38122 if (!$this->loader) {
38123 $this->loader = new ArrayLoader($this->versionParser);
38124 }
38125
38126 try {
38127 if ($driver->hasComposerFile($driver->getRootIdentifier())) {
38128 $data = $driver->getComposerInformation($driver->getRootIdentifier());
38129 $this->packageName = !empty($data['name']) ? $data['name'] : null;
38130 }
38131 } catch (\Exception $e) {
38132 if ($verbose) {
38133 $this->io->writeError('<error>Skipped parsing '.$driver->getRootIdentifier().', '.$e->getMessage().'</error>');
38134 }
38135 }
38136
38137 foreach ($driver->getTags() as $tag => $identifier) {
38138 $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $tag . '</comment>)';
38139 if ($verbose) {
38140 $this->io->writeError($msg);
38141 } else {
38142 $this->io->overwriteError($msg, false);
38143 }
38144
38145
38146  $tag = str_replace('release-', '', $tag);
38147
38148 if (!$parsedTag = $this->validateTag($tag)) {
38149 if ($verbose) {
38150 $this->io->writeError('<warning>Skipped tag '.$tag.', invalid tag name</warning>');
38151 }
38152 continue;
38153 }
38154
38155 try {
38156 if (!$data = $driver->getComposerInformation($identifier)) {
38157 if ($verbose) {
38158 $this->io->writeError('<warning>Skipped tag '.$tag.', no composer file</warning>');
38159 }
38160 continue;
38161 }
38162
38163
38164  if (isset($data['version'])) {
38165 $data['version_normalized'] = $this->versionParser->normalize($data['version']);
38166 } else {
38167
38168  $data['version'] = $tag;
38169 $data['version_normalized'] = $parsedTag;
38170 }
38171
38172
38173  $data['version'] = preg_replace('{[.-]?dev$}i', '', $data['version']);
38174 $data['version_normalized'] = preg_replace('{(^dev-|[.-]?dev$)}i', '', $data['version_normalized']);
38175
38176
38177  if ($data['version_normalized'] !== $parsedTag) {
38178 if ($verbose) {
38179 $this->io->writeError('<warning>Skipped tag '.$tag.', tag ('.$parsedTag.') does not match version ('.$data['version_normalized'].') in composer.json</warning>');
38180 }
38181 continue;
38182 }
38183
38184 if ($verbose) {
38185 $this->io->writeError('Importing tag '.$tag.' ('.$data['version_normalized'].')');
38186 }
38187
38188 $this->addPackage($this->loader->load($this->preProcess($driver, $data, $identifier)));
38189 } catch (\Exception $e) {
38190 if ($verbose) {
38191 $this->io->writeError('<warning>Skipped tag '.$tag.', '.($e instanceof TransportException ? 'no composer file was found' : $e->getMessage()).'</warning>');
38192 }
38193 continue;
38194 }
38195 }
38196
38197 if (!$verbose) {
38198 $this->io->overwriteError('', false);
38199 }
38200
38201 foreach ($driver->getBranches() as $branch => $identifier) {
38202 $msg = 'Reading composer.json of <info>' . ($this->packageName ?: $this->url) . '</info> (<comment>' . $branch . '</comment>)';
38203 if ($verbose) {
38204 $this->io->writeError($msg);
38205 } else {
38206 $this->io->overwriteError($msg, false);
38207 }
38208
38209 if (!$parsedBranch = $this->validateBranch($branch)) {
38210 if ($verbose) {
38211 $this->io->writeError('<warning>Skipped branch '.$branch.', invalid name</warning>');
38212 }
38213 continue;
38214 }
38215
38216 try {
38217 if (!$data = $driver->getComposerInformation($identifier)) {
38218 if ($verbose) {
38219 $this->io->writeError('<warning>Skipped branch '.$branch.', no composer file</warning>');
38220 }
38221 continue;
38222 }
38223
38224
38225  $data['version'] = $branch;
38226 $data['version_normalized'] = $parsedBranch;
38227
38228
38229  if ('dev-' === substr($parsedBranch, 0, 4) || '9999999-dev' === $parsedBranch) {
38230 $data['version'] = 'dev-' . $data['version'];
38231 } else {
38232 $prefix = substr($branch, 0, 1) === 'v' ? 'v' : '';
38233 $data['version'] = $prefix . preg_replace('{(\.9{7})+}', '.x', $parsedBranch);
38234 }
38235
38236 if ($verbose) {
38237 $this->io->writeError('Importing branch '.$branch.' ('.$data['version'].')');
38238 }
38239
38240 $packageData = $this->preProcess($driver, $data, $identifier);
38241 $package = $this->loader->load($packageData);
38242 if ($this->loader instanceof ValidatingArrayLoader && $this->loader->getWarnings()) {
38243 throw new InvalidPackageException($this->loader->getErrors(), $this->loader->getWarnings(), $packageData);
38244 }
38245 $this->addPackage($package);
38246 } catch (TransportException $e) {
38247 if ($verbose) {
38248 $this->io->writeError('<warning>Skipped branch '.$branch.', no composer file was found</warning>');
38249 }
38250 continue;
38251 } catch (\Exception $e) {
38252 if (!$verbose) {
38253 $this->io->writeError('');
38254 }
38255 $this->branchErrorOccurred = true;
38256 $this->io->writeError('<error>Skipped branch '.$branch.', '.$e->getMessage().'</error>');
38257 $this->io->writeError('');
38258 continue;
38259 }
38260 }
38261 $driver->cleanup();
38262
38263 if (!$verbose) {
38264 $this->io->overwriteError('', false);
38265 }
38266
38267 if (!$this->getPackages()) {
38268 throw new InvalidRepositoryException('No valid composer.json was found in any branch or tag of '.$this->url.', could not load a package from it.');
38269 }
38270 }
38271
38272 protected function preProcess(VcsDriverInterface $driver, array $data, $identifier)
38273 {
38274
38275  $data['name'] = $this->packageName ?: $data['name'];
38276
38277 if (!isset($data['dist'])) {
38278 $data['dist'] = $driver->getDist($identifier);
38279 }
38280 if (!isset($data['source'])) {
38281 $data['source'] = $driver->getSource($identifier);
38282 }
38283
38284 return $data;
38285 }
38286
38287 private function validateBranch($branch)
38288 {
38289 try {
38290 return $this->versionParser->normalizeBranch($branch);
38291 } catch (\Exception $e) {
38292 }
38293
38294 return false;
38295 }
38296
38297 private function validateTag($version)
38298 {
38299 try {
38300 return $this->versionParser->normalize($version);
38301 } catch (\Exception $e) {
38302 }
38303
38304 return false;
38305 }
38306 }
38307 <?php
38308
38309
38310
38311
38312
38313
38314
38315
38316
38317
38318
38319 namespace Composer\Repository;
38320
38321 use Composer\Package\AliasPackage;
38322
38323
38324
38325
38326
38327
38328 class WritableArrayRepository extends ArrayRepository implements WritableRepositoryInterface
38329 {
38330
38331
38332
38333 public function write()
38334 {
38335 }
38336
38337
38338
38339
38340 public function reload()
38341 {
38342 }
38343
38344
38345
38346
38347 public function getCanonicalPackages()
38348 {
38349 $packages = $this->getPackages();
38350
38351
38352  $packagesByName = array();
38353 foreach ($packages as $package) {
38354 if (!isset($packagesByName[$package->getName()]) || $packagesByName[$package->getName()] instanceof AliasPackage) {
38355 $packagesByName[$package->getName()] = $package;
38356 }
38357 }
38358
38359 $canonicalPackages = array();
38360
38361
38362  foreach ($packagesByName as $package) {
38363 while ($package instanceof AliasPackage) {
38364 $package = $package->getAliasOf();
38365 }
38366
38367 $canonicalPackages[] = $package;
38368 }
38369
38370 return $canonicalPackages;
38371 }
38372 }
38373 <?php
38374
38375
38376
38377
38378
38379
38380
38381
38382
38383
38384
38385 namespace Composer\Repository;
38386
38387 use Composer\Package\PackageInterface;
38388
38389
38390
38391
38392
38393
38394 interface WritableRepositoryInterface extends RepositoryInterface
38395 {
38396
38397
38398
38399 public function write();
38400
38401
38402
38403
38404
38405
38406 public function addPackage(PackageInterface $package);
38407
38408
38409
38410
38411
38412
38413 public function removePackage(PackageInterface $package);
38414
38415
38416
38417
38418
38419
38420 public function getCanonicalPackages();
38421
38422
38423
38424
38425 public function reload();
38426 }
38427 <?php
38428
38429
38430
38431
38432
38433
38434
38435
38436
38437
38438
38439 namespace Composer\Script;
38440
38441
38442
38443
38444
38445
38446 class CommandEvent extends Event
38447 {
38448 }
38449 <?php
38450
38451
38452
38453
38454
38455
38456
38457
38458
38459
38460
38461 namespace Composer\Script;
38462
38463 use Composer\Composer;
38464 use Composer\IO\IOInterface;
38465 use Composer\EventDispatcher\Event as BaseEvent;
38466
38467
38468
38469
38470
38471
38472
38473 class Event extends BaseEvent
38474 {
38475
38476
38477
38478 private $composer;
38479
38480
38481
38482
38483 private $io;
38484
38485
38486
38487
38488 private $devMode;
38489
38490
38491
38492
38493
38494
38495
38496
38497
38498
38499
38500 public function __construct($name, Composer $composer, IOInterface $io, $devMode = false, array $args = array(), array $flags = array())
38501 {
38502 parent::__construct($name, $args, $flags);
38503 $this->composer = $composer;
38504 $this->io = $io;
38505 $this->devMode = $devMode;
38506 }
38507
38508
38509
38510
38511
38512
38513 public function getComposer()
38514 {
38515 return $this->composer;
38516 }
38517
38518
38519
38520
38521
38522
38523 public function getIO()
38524 {
38525 return $this->io;
38526 }
38527
38528
38529
38530
38531
38532
38533 public function isDevMode()
38534 {
38535 return $this->devMode;
38536 }
38537 }
38538 <?php
38539
38540
38541
38542
38543
38544
38545
38546
38547
38548
38549
38550 namespace Composer\Script;
38551
38552 use Composer\Installer\PackageEvent as BasePackageEvent;
38553
38554
38555
38556
38557
38558
38559 class PackageEvent extends BasePackageEvent
38560 {
38561 }
38562 <?php
38563
38564
38565
38566
38567
38568
38569
38570
38571
38572
38573
38574 namespace Composer\Script;
38575
38576
38577
38578
38579
38580
38581
38582 class ScriptEvents
38583 {
38584
38585
38586
38587
38588
38589
38590
38591 const PRE_INSTALL_CMD = 'pre-install-cmd';
38592
38593
38594
38595
38596
38597
38598
38599
38600 const POST_INSTALL_CMD = 'post-install-cmd';
38601
38602
38603
38604
38605
38606
38607
38608
38609 const PRE_UPDATE_CMD = 'pre-update-cmd';
38610
38611
38612
38613
38614
38615
38616
38617
38618 const POST_UPDATE_CMD = 'post-update-cmd';
38619
38620
38621
38622
38623
38624
38625
38626
38627 const PRE_STATUS_CMD = 'pre-status-cmd';
38628
38629
38630
38631
38632
38633
38634
38635
38636 const POST_STATUS_CMD = 'post-status-cmd';
38637
38638
38639
38640
38641
38642
38643
38644
38645 const PRE_AUTOLOAD_DUMP = 'pre-autoload-dump';
38646
38647
38648
38649
38650
38651
38652
38653
38654 const POST_AUTOLOAD_DUMP = 'post-autoload-dump';
38655
38656
38657
38658
38659
38660
38661
38662
38663 const POST_ROOT_PACKAGE_INSTALL = 'post-root-package-install';
38664
38665
38666
38667
38668
38669
38670
38671
38672
38673 const POST_CREATE_PROJECT_CMD = 'post-create-project-cmd';
38674
38675
38676
38677
38678
38679
38680
38681
38682 const PRE_ARCHIVE_CMD = 'pre-archive-cmd';
38683
38684
38685
38686
38687
38688
38689
38690
38691 const POST_ARCHIVE_CMD = 'post-archive-cmd';
38692
38693
38694
38695
38696
38697
38698
38699
38700
38701
38702
38703 const PRE_PACKAGE_INSTALL = 'pre-package-install';
38704
38705
38706
38707
38708
38709
38710
38711
38712
38713 const POST_PACKAGE_INSTALL = 'post-package-install';
38714
38715
38716
38717
38718
38719
38720
38721
38722
38723 const PRE_PACKAGE_UPDATE = 'pre-package-update';
38724
38725
38726
38727
38728
38729
38730
38731
38732
38733 const POST_PACKAGE_UPDATE = 'post-package-update';
38734
38735
38736
38737
38738
38739
38740
38741
38742
38743 const PRE_PACKAGE_UNINSTALL = 'pre-package-uninstall';
38744
38745
38746
38747
38748
38749
38750
38751
38752
38753 const POST_PACKAGE_UNINSTALL = 'post-package-uninstall';
38754 }
38755 <?php
38756
38757
38758
38759
38760
38761
38762
38763
38764
38765
38766
38767 namespace Composer\SelfUpdate;
38768
38769
38770
38771
38772 class Keys
38773 {
38774 public static function fingerprint($path)
38775 {
38776 $hash = strtoupper(hash('sha256', preg_replace('{\s}', '', file_get_contents($path))));
38777
38778 return implode(' ', array(
38779 substr($hash, 0, 8),
38780 substr($hash, 8, 8),
38781 substr($hash, 16, 8),
38782 substr($hash, 24, 8),
38783 '', 
38784  substr($hash, 32, 8),
38785 substr($hash, 40, 8),
38786 substr($hash, 48, 8),
38787 substr($hash, 56, 8),
38788 ));
38789 }
38790 }
38791 <?php
38792
38793
38794
38795
38796
38797
38798
38799
38800
38801
38802
38803 namespace Composer\SelfUpdate;
38804
38805 use Composer\Util\RemoteFilesystem;
38806 use Composer\Config;
38807 use Composer\Json\JsonFile;
38808
38809
38810
38811
38812 class Versions
38813 {
38814 private $rfs;
38815 private $config;
38816 private $channel;
38817
38818 public function __construct(Config $config, RemoteFilesystem $rfs)
38819 {
38820 $this->rfs = $rfs;
38821 $this->config = $config;
38822 }
38823
38824 public function getChannel()
38825 {
38826 if ($this->channel) {
38827 return $this->channel;
38828 }
38829
38830 $channelFile = $this->config->get('home').'/update-channel';
38831 if (file_exists($channelFile)) {
38832 $channel = trim(file_get_contents($channelFile));
38833 if (in_array($channel, array('stable', 'preview', 'snapshot'), true)) {
38834 return $this->channel = $channel;
38835 }
38836 }
38837
38838 return $this->channel = 'stable';
38839 }
38840
38841 public function setChannel($channel)
38842 {
38843 if (!in_array($channel, array('stable', 'preview', 'snapshot'), true)) {
38844 throw new \InvalidArgumentException('Invalid channel '.$channel.', must be one of: stable, preview, snapshot');
38845 }
38846
38847 $channelFile = $this->config->get('home').'/update-channel';
38848 $this->channel = $channel;
38849 file_put_contents($channelFile, $channel.PHP_EOL);
38850 }
38851
38852 public function getLatest()
38853 {
38854 $protocol = extension_loaded('openssl') ? 'https' : 'http';
38855 $versions = JsonFile::parseJson($this->rfs->getContents('getcomposer.org', $protocol . '://getcomposer.org/versions', false));
38856
38857 foreach ($versions[$this->getChannel()] as $version) {
38858 if ($version['min-php'] <= PHP_VERSION_ID) {
38859 return $version;
38860 }
38861 }
38862
38863 throw new \LogicException('There is no version of Composer available for your PHP version ('.PHP_VERSION.')');
38864 }
38865 }
38866 <?php
38867
38868
38869
38870
38871
38872
38873
38874
38875
38876
38877
38878 namespace Composer\Util;
38879
38880 use Composer\Config;
38881 use Composer\IO\IOInterface;
38882
38883
38884
38885
38886 class AuthHelper
38887 {
38888 protected $io;
38889 protected $config;
38890
38891 public function __construct(IOInterface $io, Config $config)
38892 {
38893 $this->io = $io;
38894 $this->config = $config;
38895 }
38896
38897 public function storeAuth($originUrl, $storeAuth)
38898 {
38899 $store = false;
38900 $configSource = $this->config->getAuthConfigSource();
38901 if ($storeAuth === true) {
38902 $store = $configSource;
38903 } elseif ($storeAuth === 'prompt') {
38904 $answer = $this->io->askAndValidate(
38905 'Do you want to store credentials for '.$originUrl.' in '.$configSource->getName().' ? [Yn] ',
38906 function ($value) {
38907 $input = strtolower(substr(trim($value), 0, 1));
38908 if (in_array($input, array('y','n'))) {
38909 return $input;
38910 }
38911 throw new \RuntimeException('Please answer (y)es or (n)o');
38912 },
38913 null,
38914 'y'
38915 );
38916
38917 if ($answer === 'y') {
38918 $store = $configSource;
38919 }
38920 }
38921 if ($store) {
38922 $store->addConfigSetting(
38923 'http-basic.'.$originUrl,
38924 $this->io->getAuthentication($originUrl)
38925 );
38926 }
38927 }
38928 }
38929 <?php
38930
38931
38932
38933
38934
38935
38936
38937
38938
38939
38940
38941 namespace Composer\Util;
38942
38943 use Composer\Factory;
38944 use Composer\IO\IOInterface;
38945 use Composer\Config;
38946 use Composer\Downloader\TransportException;
38947
38948
38949
38950
38951 class Bitbucket
38952 {
38953 private $io;
38954 private $config;
38955 private $process;
38956 private $remoteFilesystem;
38957 private $token = array();
38958 private $time;
38959
38960 const OAUTH2_ACCESS_TOKEN_URL = 'https://bitbucket.org/site/oauth2/access_token';
38961
38962
38963
38964
38965
38966
38967
38968
38969
38970
38971 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null, $time = null)
38972 {
38973 $this->io = $io;
38974 $this->config = $config;
38975 $this->process = $process ?: new ProcessExecutor;
38976 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
38977 $this->time = $time;
38978 }
38979
38980
38981
38982
38983 public function getToken()
38984 {
38985 if (!isset($this->token['access_token'])) {
38986 return '';
38987 }
38988
38989 return $this->token['access_token'];
38990 }
38991
38992
38993
38994
38995
38996
38997
38998 public function authorizeOAuth($originUrl)
38999 {
39000 if ($originUrl !== 'bitbucket.org') {
39001 return false;
39002 }
39003
39004
39005  if (0 === $this->process->execute('git config bitbucket.accesstoken', $output)) {
39006 $this->io->setAuthentication($originUrl, 'x-token-auth', trim($output));
39007
39008 return true;
39009 }
39010
39011 return false;
39012 }
39013
39014
39015
39016
39017
39018 private function requestAccessToken($originUrl)
39019 {
39020 try {
39021 $json = $this->remoteFilesystem->getContents($originUrl, self::OAUTH2_ACCESS_TOKEN_URL, false, array(
39022 'retry-auth-failure' => false,
39023 'http' => array(
39024 'method' => 'POST',
39025 'content' => 'grant_type=client_credentials',
39026 ),
39027 ));
39028
39029 $this->token = json_decode($json, true);
39030 } catch (TransportException $e) {
39031 if ($e->getCode() === 400) {
39032 $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
39033 $this->io->writeError('This can have two reasons:');
39034 $this->io->writeError('1. You are authenticating with a bitbucket username/password combination');
39035 $this->io->writeError('2. You are using an OAuth consumer, but didn\'t configure a (dummy) callback url');
39036
39037 return false;
39038 } elseif (in_array($e->getCode(), array(403, 401))) {
39039 $this->io->writeError('<error>Invalid OAuth consumer provided.</error>');
39040 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
39041
39042 return false;
39043 }
39044
39045 throw $e;
39046 }
39047
39048 return true;
39049 }
39050
39051
39052
39053
39054
39055
39056
39057
39058
39059
39060 public function authorizeOAuthInteractively($originUrl, $message = null)
39061 {
39062 if ($message) {
39063 $this->io->writeError($message);
39064 }
39065
39066 $url = 'https://confluence.atlassian.com/bitbucket/oauth-on-bitbucket-cloud-238027431.html';
39067 $this->io->writeError(sprintf('Follow the instructions on %s', $url));
39068 $this->io->writeError(sprintf('to create a consumer. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
39069 $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)');
39070
39071 $consumerKey = trim($this->io->askAndHideAnswer('Consumer Key (hidden): '));
39072
39073 if (!$consumerKey) {
39074 $this->io->writeError('<warning>No consumer key given, aborting.</warning>');
39075 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
39076
39077 return false;
39078 }
39079
39080 $consumerSecret = trim($this->io->askAndHideAnswer('Consumer Secret (hidden): '));
39081
39082 if (!$consumerSecret) {
39083 $this->io->writeError('<warning>No consumer secret given, aborting.</warning>');
39084 $this->io->writeError('You can also add it manually later by using "composer config --global --auth bitbucket-oauth.bitbucket.org <consumer-key> <consumer-secret>"');
39085
39086 return false;
39087 }
39088
39089 $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
39090
39091 if (!$this->requestAccessToken($originUrl)) {
39092 return false;
39093 }
39094
39095
39096  $this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);
39097
39098
39099  $this->config->getAuthConfigSource()->removeConfigSetting('http-basic.' . $originUrl);
39100
39101 $this->io->writeError('<info>Consumer stored successfully.</info>');
39102
39103 return true;
39104 }
39105
39106
39107
39108
39109
39110
39111
39112
39113
39114 public function requestToken($originUrl, $consumerKey, $consumerSecret)
39115 {
39116 if (!empty($this->token) || $this->getTokenFromConfig($originUrl)) {
39117 return $this->token['access_token'];
39118 }
39119
39120 $this->io->setAuthentication($originUrl, $consumerKey, $consumerSecret);
39121 if (!$this->requestAccessToken($originUrl)) {
39122 return '';
39123 }
39124
39125 $this->storeInAuthConfig($originUrl, $consumerKey, $consumerSecret);
39126
39127 return $this->token['access_token'];
39128 }
39129
39130
39131
39132
39133
39134
39135
39136 private function storeInAuthConfig($originUrl, $consumerKey, $consumerSecret)
39137 {
39138 $this->config->getConfigSource()->removeConfigSetting('bitbucket-oauth.'.$originUrl);
39139
39140 $time = null === $this->time ? time() : $this->time;
39141 $consumer = array(
39142 "consumer-key" => $consumerKey,
39143 "consumer-secret" => $consumerSecret,
39144 "access-token" => $this->token['access_token'],
39145 "access-token-expiration" => $time + $this->token['expires_in'],
39146 );
39147
39148 $this->config->getAuthConfigSource()->addConfigSetting('bitbucket-oauth.'.$originUrl, $consumer);
39149 }
39150
39151
39152
39153
39154
39155 private function getTokenFromConfig($originUrl)
39156 {
39157 $authConfig = $this->config->get('bitbucket-oauth');
39158
39159 if (
39160 !isset($authConfig[$originUrl]['access-token'])
39161 || !isset($authConfig[$originUrl]['access-token-expiration'])
39162 || time() > $authConfig[$originUrl]['access-token-expiration']
39163 ) {
39164 return false;
39165 }
39166
39167 $this->token = array(
39168 'access_token' => $authConfig[$originUrl]['access-token'],
39169 );
39170
39171 return true;
39172 }
39173 }
39174 <?php
39175
39176
39177
39178
39179
39180
39181
39182
39183
39184
39185
39186 namespace Composer\Util;
39187
39188
39189
39190
39191
39192
39193 class ComposerMirror
39194 {
39195 public static function processUrl($mirrorUrl, $packageName, $version, $reference, $type)
39196 {
39197 if ($reference) {
39198 $reference = preg_match('{^([a-f0-9]*|%reference%)$}', $reference) ? $reference : md5($reference);
39199 }
39200 $version = strpos($version, '/') === false ? $version : md5($version);
39201
39202 return str_replace(
39203 array('%package%', '%version%', '%reference%', '%type%'),
39204 array($packageName, $version, $reference, $type),
39205 $mirrorUrl
39206 );
39207 }
39208
39209 public static function processGitUrl($mirrorUrl, $packageName, $url, $type)
39210 {
39211 if (preg_match('#^(?:(?:https?|git)://github\.com/|git@github\.com:)([^/]+)/(.+?)(?:\.git)?$#', $url, $match)) {
39212 $url = 'gh-'.$match[1].'/'.$match[2];
39213 } elseif (preg_match('#^https://bitbucket\.org/([^/]+)/(.+?)(?:\.git)?/?$#', $url, $match)) {
39214 $url = 'bb-'.$match[1].'/'.$match[2];
39215 } else {
39216 $url = preg_replace('{[^a-z0-9_.-]}i', '-', trim($url, '/'));
39217 }
39218
39219 return str_replace(
39220 array('%package%', '%normalizedUrl%', '%type%'),
39221 array($packageName, $url, $type),
39222 $mirrorUrl
39223 );
39224 }
39225
39226 public static function processHgUrl($mirrorUrl, $packageName, $url, $type)
39227 {
39228 return self::processGitUrl($mirrorUrl, $packageName, $url, $type);
39229 }
39230 }
39231 <?php
39232
39233
39234
39235
39236
39237
39238
39239
39240
39241
39242
39243 namespace Composer\Util;
39244
39245 use Composer\Package\Loader\ArrayLoader;
39246 use Composer\Package\Loader\ValidatingArrayLoader;
39247 use Composer\Package\Loader\InvalidPackageException;
39248 use Composer\Json\JsonValidationException;
39249 use Composer\IO\IOInterface;
39250 use Composer\Json\JsonFile;
39251 use Composer\Spdx\SpdxLicenses;
39252
39253
39254
39255
39256
39257
39258
39259 class ConfigValidator
39260 {
39261 private $io;
39262
39263 public function __construct(IOInterface $io)
39264 {
39265 $this->io = $io;
39266 }
39267
39268
39269
39270
39271
39272
39273
39274
39275
39276 public function validate($file, $arrayLoaderValidationFlags = ValidatingArrayLoader::CHECK_ALL)
39277 {
39278 $errors = array();
39279 $publishErrors = array();
39280 $warnings = array();
39281
39282
39283  $laxValid = false;
39284 try {
39285 $json = new JsonFile($file, null, $this->io);
39286 $manifest = $json->read();
39287
39288 $json->validateSchema(JsonFile::LAX_SCHEMA);
39289 $laxValid = true;
39290 $json->validateSchema();
39291 } catch (JsonValidationException $e) {
39292 foreach ($e->getErrors() as $message) {
39293 if ($laxValid) {
39294 $publishErrors[] = $message;
39295 } else {
39296 $errors[] = $message;
39297 }
39298 }
39299 } catch (\Exception $e) {
39300 $errors[] = $e->getMessage();
39301
39302 return array($errors, $publishErrors, $warnings);
39303 }
39304
39305
39306  if (!empty($manifest['license'])) {
39307
39308  if (is_array($manifest['license'])) {
39309 foreach ($manifest['license'] as $key => $license) {
39310 if ('proprietary' === $license) {
39311 unset($manifest['license'][$key]);
39312 }
39313 }
39314 }
39315
39316 $licenseValidator = new SpdxLicenses();
39317 if ('proprietary' !== $manifest['license'] && array() !== $manifest['license'] && !$licenseValidator->validate($manifest['license']) && $licenseValidator->validate(trim($manifest['license']))) {
39318 $warnings[] = sprintf(
39319 'License %s must not contain extra spaces, make sure to trim it.',
39320 json_encode($manifest['license'])
39321 );
39322 } elseif ('proprietary' !== $manifest['license'] && array() !== $manifest['license'] && !$licenseValidator->validate($manifest['license'])) {
39323 $warnings[] = sprintf(
39324 'License %s is not a valid SPDX license identifier, see https://spdx.org/licenses/ if you use an open license.'
39325 . PHP_EOL .
39326 'If the software is closed-source, you may use "proprietary" as license.',
39327 json_encode($manifest['license'])
39328 );
39329 }
39330 } else {
39331 $warnings[] = 'No license specified, it is recommended to do so. For closed-source software you may use "proprietary" as license.';
39332 }
39333
39334 if (isset($manifest['version'])) {
39335 $warnings[] = 'The version field is present, it is recommended to leave it out if the package is published on Packagist.';
39336 }
39337
39338 if (!empty($manifest['name']) && preg_match('{[A-Z]}', $manifest['name'])) {
39339 $suggestName = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $manifest['name']);
39340 $suggestName = strtolower($suggestName);
39341
39342 $publishErrors[] = sprintf(
39343 '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.',
39344 $manifest['name'],
39345 $suggestName
39346 );
39347 }
39348
39349 if (!empty($manifest['type']) && $manifest['type'] == 'composer-installer') {
39350 $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.";
39351 }
39352
39353
39354  if (isset($manifest['require']) && isset($manifest['require-dev'])) {
39355 $requireOverrides = array_intersect_key($manifest['require'], $manifest['require-dev']);
39356
39357 if (!empty($requireOverrides)) {
39358 $plural = (count($requireOverrides) > 1) ? 'are' : 'is';
39359 $warnings[] = implode(', ', array_keys($requireOverrides)). " {$plural} required both in require and require-dev, this can lead to unexpected behavior";
39360 }
39361 }
39362
39363
39364  $require = isset($manifest['require']) ? $manifest['require'] : array();
39365 $requireDev = isset($manifest['require-dev']) ? $manifest['require-dev'] : array();
39366 $packages = array_merge($require, $requireDev);
39367 foreach ($packages as $package => $version) {
39368 if (preg_match('/#/', $version) === 1) {
39369 $warnings[] = sprintf(
39370 'The package "%s" is pointing to a commit-ref, this is bad practice and can cause unforeseen issues.',
39371 $package
39372 );
39373 }
39374 }
39375
39376
39377  if (isset($manifest['autoload']['psr-0'][''])) {
39378 $warnings[] = "Defining autoload.psr-0 with an empty namespace prefix is a bad idea for performance";
39379 }
39380 if (isset($manifest['autoload']['psr-4'][''])) {
39381 $warnings[] = "Defining autoload.psr-4 with an empty namespace prefix is a bad idea for performance";
39382 }
39383
39384 try {
39385 $loader = new ValidatingArrayLoader(new ArrayLoader(), true, null, $arrayLoaderValidationFlags);
39386 if (!isset($manifest['version'])) {
39387 $manifest['version'] = '1.0.0';
39388 }
39389 if (!isset($manifest['name'])) {
39390 $manifest['name'] = 'dummy/dummy';
39391 }
39392 $loader->load($manifest);
39393 } catch (InvalidPackageException $e) {
39394 $errors = array_merge($errors, $e->getErrors());
39395 }
39396
39397 $warnings = array_merge($warnings, $loader->getWarnings());
39398
39399 return array($errors, $publishErrors, $warnings);
39400 }
39401 }
39402 <?php
39403
39404
39405
39406
39407
39408
39409
39410
39411
39412
39413
39414 namespace Composer\Util;
39415
39416 use Composer\IO\IOInterface;
39417
39418
39419
39420
39421
39422
39423 class ErrorHandler
39424 {
39425 private static $io;
39426
39427
39428
39429
39430
39431
39432
39433
39434
39435
39436
39437
39438 public static function handle($level, $message, $file, $line)
39439 {
39440
39441  if (!(error_reporting() & $level)) {
39442 return;
39443 }
39444
39445 if (ini_get('xdebug.scream')) {
39446 $message .= "\n\nWarning: You have xdebug.scream enabled, the warning above may be".
39447 "\na legitimately suppressed error that you were not supposed to see.";
39448 }
39449
39450 if ($level !== E_DEPRECATED && $level !== E_USER_DEPRECATED) {
39451 throw new \ErrorException($message, 0, $level, $file, $line);
39452 }
39453
39454 if (self::$io) {
39455 self::$io->writeError('<warning>Deprecation Notice: '.$message.' in '.$file.':'.$line.'</warning>');
39456 if (self::$io->isVerbose()) {
39457 self::$io->writeError('<warning>Stack trace:</warning>');
39458 self::$io->writeError(array_filter(array_map(function ($a) {
39459 if (isset($a['line'], $a['file'])) {
39460 return '<warning> '.$a['file'].':'.$a['line'].'</warning>';
39461 }
39462
39463 return null;
39464 }, array_slice(debug_backtrace(), 2))));
39465 }
39466 }
39467 }
39468
39469
39470
39471
39472
39473
39474 public static function register(IOInterface $io = null)
39475 {
39476 set_error_handler(array(__CLASS__, 'handle'));
39477 error_reporting(E_ALL | E_STRICT);
39478 self::$io = $io;
39479 }
39480 }
39481 <?php
39482
39483
39484
39485
39486
39487
39488
39489
39490
39491
39492
39493 namespace Composer\Util;
39494
39495 use RecursiveDirectoryIterator;
39496 use RecursiveIteratorIterator;
39497 use Symfony\Component\Filesystem\Exception\IOException;
39498 use Symfony\Component\Finder\Finder;
39499
39500
39501
39502
39503
39504 class Filesystem
39505 {
39506 private $processExecutor;
39507
39508 public function __construct(ProcessExecutor $executor = null)
39509 {
39510 $this->processExecutor = $executor ?: new ProcessExecutor();
39511 }
39512
39513 public function remove($file)
39514 {
39515 if (is_dir($file)) {
39516 return $this->removeDirectory($file);
39517 }
39518
39519 if (file_exists($file)) {
39520 return $this->unlink($file);
39521 }
39522
39523 return false;
39524 }
39525
39526
39527
39528
39529
39530
39531
39532 public function isDirEmpty($dir)
39533 {
39534 $finder = Finder::create()
39535 ->ignoreVCS(false)
39536 ->ignoreDotFiles(false)
39537 ->depth(0)
39538 ->in($dir);
39539
39540 return count($finder) === 0;
39541 }
39542
39543 public function emptyDirectory($dir, $ensureDirectoryExists = true)
39544 {
39545 if (file_exists($dir) && is_link($dir)) {
39546 $this->unlink($dir);
39547 }
39548
39549 if ($ensureDirectoryExists) {
39550 $this->ensureDirectoryExists($dir);
39551 }
39552
39553 if (is_dir($dir)) {
39554 $finder = Finder::create()
39555 ->ignoreVCS(false)
39556 ->ignoreDotFiles(false)
39557 ->depth(0)
39558 ->in($dir);
39559
39560 foreach ($finder as $path) {
39561 $this->remove((string) $path);
39562 }
39563 }
39564 }
39565
39566
39567
39568
39569
39570
39571
39572
39573
39574
39575
39576 public function removeDirectory($directory)
39577 {
39578 if ($this->isSymlinkedDirectory($directory)) {
39579 return $this->unlinkSymlinkedDirectory($directory);
39580 }
39581
39582 if ($this->isJunction($directory)) {
39583 return $this->removeJunction($directory);
39584 }
39585
39586 if (!file_exists($directory) || !is_dir($directory)) {
39587 return true;
39588 }
39589
39590 if (preg_match('{^(?:[a-z]:)?[/\\\\]+$}i', $directory)) {
39591 throw new \RuntimeException('Aborting an attempted deletion of '.$directory.', this was probably not intended, if it is a real use case please report it.');
39592 }
39593
39594 if (!function_exists('proc_open')) {
39595 return $this->removeDirectoryPhp($directory);
39596 }
39597
39598 if (Platform::isWindows()) {
39599 $cmd = sprintf('rmdir /S /Q %s', ProcessExecutor::escape(realpath($directory)));
39600 } else {
39601 $cmd = sprintf('rm -rf %s', ProcessExecutor::escape($directory));
39602 }
39603
39604 $result = $this->getProcess()->execute($cmd, $output) === 0;
39605
39606
39607  clearstatcache();
39608
39609 if ($result && !file_exists($directory)) {
39610 return true;
39611 }
39612
39613 return $this->removeDirectoryPhp($directory);
39614 }
39615
39616
39617
39618
39619
39620
39621
39622
39623
39624
39625
39626 public function removeDirectoryPhp($directory)
39627 {
39628 try {
39629 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
39630 } catch (\UnexpectedValueException $e) {
39631
39632  
39633  clearstatcache();
39634 usleep(100000);
39635 if (!is_dir($directory)) {
39636 return true;
39637 }
39638 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
39639 }
39640 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
39641
39642 foreach ($ri as $file) {
39643 if ($file->isDir()) {
39644 $this->rmdir($file->getPathname());
39645 } else {
39646 $this->unlink($file->getPathname());
39647 }
39648 }
39649
39650 return $this->rmdir($directory);
39651 }
39652
39653 public function ensureDirectoryExists($directory)
39654 {
39655 if (!is_dir($directory)) {
39656 if (file_exists($directory)) {
39657 throw new \RuntimeException(
39658 $directory.' exists and is not a directory.'
39659 );
39660 }
39661 if (!@mkdir($directory, 0777, true)) {
39662 throw new \RuntimeException(
39663 $directory.' does not exist and could not be created.'
39664 );
39665 }
39666 }
39667 }
39668
39669
39670
39671
39672
39673
39674
39675
39676 public function unlink($path)
39677 {
39678 if (!@$this->unlinkImplementation($path)) {
39679
39680  if (!Platform::isWindows() || (usleep(350000) && !@$this->unlinkImplementation($path))) {
39681 $error = error_get_last();
39682 $message = 'Could not delete '.$path.': ' . @$error['message'];
39683 if (Platform::isWindows()) {
39684 $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
39685 }
39686
39687 throw new \RuntimeException($message);
39688 }
39689 }
39690
39691 return true;
39692 }
39693
39694
39695
39696
39697
39698
39699
39700
39701 public function rmdir($path)
39702 {
39703 if (!@rmdir($path)) {
39704
39705  if (!Platform::isWindows() || (usleep(350000) && !@rmdir($path))) {
39706 $error = error_get_last();
39707 $message = 'Could not delete '.$path.': ' . @$error['message'];
39708 if (Platform::isWindows()) {
39709 $message .= "\nThis can be due to an antivirus or the Windows Search Indexer locking the file while they are analyzed";
39710 }
39711
39712 throw new \RuntimeException($message);
39713 }
39714 }
39715
39716 return true;
39717 }
39718
39719
39720
39721
39722
39723
39724
39725
39726
39727
39728 public function copyThenRemove($source, $target)
39729 {
39730 if (!is_dir($source)) {
39731 copy($source, $target);
39732 $this->unlink($source);
39733
39734 return;
39735 }
39736
39737 $it = new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS);
39738 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::SELF_FIRST);
39739 $this->ensureDirectoryExists($target);
39740
39741 foreach ($ri as $file) {
39742 $targetPath = $target . DIRECTORY_SEPARATOR . $ri->getSubPathName();
39743 if ($file->isDir()) {
39744 $this->ensureDirectoryExists($targetPath);
39745 } else {
39746 copy($file->getPathname(), $targetPath);
39747 }
39748 }
39749
39750 $this->removeDirectoryPhp($source);
39751 }
39752
39753 public function rename($source, $target)
39754 {
39755 if (true === @rename($source, $target)) {
39756 return;
39757 }
39758
39759 if (!function_exists('proc_open')) {
39760 return $this->copyThenRemove($source, $target);
39761 }
39762
39763 if (Platform::isWindows()) {
39764
39765  $command = sprintf('xcopy %s %s /E /I /Q /Y', ProcessExecutor::escape($source), ProcessExecutor::escape($target));
39766 $result = $this->processExecutor->execute($command, $output);
39767
39768
39769  clearstatcache();
39770
39771 if (0 === $result) {
39772 $this->remove($source);
39773
39774 return;
39775 }
39776 } else {
39777
39778  
39779  $command = sprintf('mv %s %s', ProcessExecutor::escape($source), ProcessExecutor::escape($target));
39780 $result = $this->processExecutor->execute($command, $output);
39781
39782
39783  clearstatcache();
39784
39785 if (0 === $result) {
39786 return;
39787 }
39788 }
39789
39790 return $this->copyThenRemove($source, $target);
39791 }
39792
39793
39794
39795
39796
39797
39798
39799
39800
39801
39802 public function findShortestPath($from, $to, $directories = false)
39803 {
39804 if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
39805 throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
39806 }
39807
39808 $from = lcfirst($this->normalizePath($from));
39809 $to = lcfirst($this->normalizePath($to));
39810
39811 if ($directories) {
39812 $from = rtrim($from, '/') . '/dummy_file';
39813 }
39814
39815 if (dirname($from) === dirname($to)) {
39816 return './'.basename($to);
39817 }
39818
39819 $commonPath = $to;
39820 while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath)) {
39821 $commonPath = strtr(dirname($commonPath), '\\', '/');
39822 }
39823
39824 if (0 !== strpos($from, $commonPath) || '/' === $commonPath) {
39825 return $to;
39826 }
39827
39828 $commonPath = rtrim($commonPath, '/') . '/';
39829 $sourcePathDepth = substr_count(substr($from, strlen($commonPath)), '/');
39830 $commonPathCode = str_repeat('../', $sourcePathDepth);
39831
39832 return ($commonPathCode . substr($to, strlen($commonPath))) ?: './';
39833 }
39834
39835
39836
39837
39838
39839
39840
39841
39842
39843
39844
39845 public function findShortestPathCode($from, $to, $directories = false, $staticCode = false)
39846 {
39847 if (!$this->isAbsolutePath($from) || !$this->isAbsolutePath($to)) {
39848 throw new \InvalidArgumentException(sprintf('$from (%s) and $to (%s) must be absolute paths.', $from, $to));
39849 }
39850
39851 $from = lcfirst($this->normalizePath($from));
39852 $to = lcfirst($this->normalizePath($to));
39853
39854 if ($from === $to) {
39855 return $directories ? '__DIR__' : '__FILE__';
39856 }
39857
39858 $commonPath = $to;
39859 while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath) && '.' !== $commonPath) {
39860 $commonPath = strtr(dirname($commonPath), '\\', '/');
39861 }
39862
39863 if (0 !== strpos($from, $commonPath) || '/' === $commonPath || '.' === $commonPath) {
39864 return var_export($to, true);
39865 }
39866
39867 $commonPath = rtrim($commonPath, '/') . '/';
39868 if (strpos($to, $from.'/') === 0) {
39869 return '__DIR__ . '.var_export(substr($to, strlen($from)), true);
39870 }
39871 $sourcePathDepth = substr_count(substr($from, strlen($commonPath)), '/') + $directories;
39872 if ($staticCode) {
39873 $commonPathCode = "__DIR__ . '".str_repeat('/..', $sourcePathDepth)."'";
39874 } else {
39875 $commonPathCode = str_repeat('dirname(', $sourcePathDepth).'__DIR__'.str_repeat(')', $sourcePathDepth);
39876 }
39877 $relTarget = substr($to, strlen($commonPath));
39878
39879 return $commonPathCode . (strlen($relTarget) ? '.' . var_export('/' . $relTarget, true) : '');
39880 }
39881
39882
39883
39884
39885
39886
39887
39888 public function isAbsolutePath($path)
39889 {
39890 return substr($path, 0, 1) === '/' || substr($path, 1, 1) === ':';
39891 }
39892
39893
39894
39895
39896
39897
39898
39899
39900
39901 public function size($path)
39902 {
39903 if (!file_exists($path)) {
39904 throw new \RuntimeException("$path does not exist.");
39905 }
39906 if (is_dir($path)) {
39907 return $this->directorySize($path);
39908 }
39909
39910 return filesize($path);
39911 }
39912
39913
39914
39915
39916
39917
39918
39919
39920 public function normalizePath($path)
39921 {
39922 $parts = array();
39923 $path = strtr($path, '\\', '/');
39924 $prefix = '';
39925 $absolute = false;
39926
39927
39928  if (preg_match('{^( [0-9a-z]{2,}+: (?: // (?: [a-z]: )? )? | [a-z]: )}ix', $path, $match)) {
39929 $prefix = $match[1];
39930 $path = substr($path, strlen($prefix));
39931 }
39932
39933 if (substr($path, 0, 1) === '/') {
39934 $absolute = true;
39935 $path = substr($path, 1);
39936 }
39937
39938 $up = false;
39939 foreach (explode('/', $path) as $chunk) {
39940 if ('..' === $chunk && ($absolute || $up)) {
39941 array_pop($parts);
39942 $up = !(empty($parts) || '..' === end($parts));
39943 } elseif ('.' !== $chunk && '' !== $chunk) {
39944 $parts[] = $chunk;
39945 $up = '..' !== $chunk;
39946 }
39947 }
39948
39949 return $prefix.($absolute ? '/' : '').implode('/', $parts);
39950 }
39951
39952
39953
39954
39955
39956
39957
39958 public static function isLocalPath($path)
39959 {
39960 return (bool) preg_match('{^(file://(?!//)|/(?!/)|/?[a-z]:[\\\\/]|\.\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i', $path);
39961 }
39962
39963 public static function getPlatformPath($path)
39964 {
39965 if (Platform::isWindows()) {
39966 $path = preg_replace('{^(?:file:///([a-z]):?/)}i', 'file://$1:/', $path);
39967 }
39968
39969 return preg_replace('{^file://}i', '', $path);
39970 }
39971
39972 protected function directorySize($directory)
39973 {
39974 $it = new RecursiveDirectoryIterator($directory, RecursiveDirectoryIterator::SKIP_DOTS);
39975 $ri = new RecursiveIteratorIterator($it, RecursiveIteratorIterator::CHILD_FIRST);
39976
39977 $size = 0;
39978 foreach ($ri as $file) {
39979 if ($file->isFile()) {
39980 $size += $file->getSize();
39981 }
39982 }
39983
39984 return $size;
39985 }
39986
39987 protected function getProcess()
39988 {
39989 return new ProcessExecutor;
39990 }
39991
39992
39993
39994
39995
39996
39997
39998
39999
40000
40001 private function unlinkImplementation($path)
40002 {
40003 if (Platform::isWindows() && is_dir($path) && is_link($path)) {
40004 return rmdir($path);
40005 }
40006
40007 return unlink($path);
40008 }
40009
40010
40011
40012
40013
40014
40015
40016
40017 public function relativeSymlink($target, $link)
40018 {
40019 $cwd = getcwd();
40020
40021 $relativePath = $this->findShortestPath($link, $target);
40022 chdir(dirname($link));
40023 $result = @symlink($relativePath, $link);
40024
40025 chdir($cwd);
40026
40027 return (bool) $result;
40028 }
40029
40030
40031
40032
40033
40034
40035
40036
40037 public function isSymlinkedDirectory($directory)
40038 {
40039 if (!is_dir($directory)) {
40040 return false;
40041 }
40042
40043 $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
40044
40045 return is_link($resolved);
40046 }
40047
40048
40049
40050
40051
40052
40053 private function unlinkSymlinkedDirectory($directory)
40054 {
40055 $resolved = $this->resolveSymlinkedDirectorySymlink($directory);
40056
40057 return $this->unlink($resolved);
40058 }
40059
40060
40061
40062
40063
40064
40065
40066
40067 private function resolveSymlinkedDirectorySymlink($pathname)
40068 {
40069 if (!is_dir($pathname)) {
40070 return $pathname;
40071 }
40072
40073 $resolved = rtrim($pathname, '/');
40074
40075 if (!strlen($resolved)) {
40076 return $pathname;
40077 }
40078
40079 return $resolved;
40080 }
40081
40082
40083
40084
40085
40086
40087
40088 public function junction($target, $junction)
40089 {
40090 if (!Platform::isWindows()) {
40091 throw new \LogicException(sprintf('Function %s is not available on non-Windows platform', __CLASS__));
40092 }
40093 if (!is_dir($target)) {
40094 throw new IOException(sprintf('Cannot junction to "%s" as it is not a directory.', $target), 0, null, $target);
40095 }
40096 $cmd = sprintf('mklink /J %s %s',
40097 ProcessExecutor::escape(str_replace('/', DIRECTORY_SEPARATOR, $junction)),
40098 ProcessExecutor::escape(realpath($target)));
40099 if ($this->getProcess()->execute($cmd, $output) !== 0) {
40100 throw new IOException(sprintf('Failed to create junction to "%s" at "%s".', $target, $junction), 0, null, $target);
40101 }
40102 clearstatcache(true, $junction);
40103 }
40104
40105
40106
40107
40108
40109
40110
40111 public function isJunction($junction)
40112 {
40113 if (!Platform::isWindows()) {
40114 return false;
40115 }
40116 if (!is_dir($junction) || is_link($junction)) {
40117 return false;
40118 }
40119
40120
40121
40122
40123
40124
40125
40126
40127
40128
40129
40130 clearstatcache(true, $junction);
40131 $stat = lstat($junction);
40132
40133 return !($stat['mode'] & 0xC000);
40134 }
40135
40136
40137
40138
40139
40140
40141
40142 public function removeJunction($junction)
40143 {
40144 if (!Platform::isWindows()) {
40145 return false;
40146 }
40147 $junction = rtrim(str_replace('/', DIRECTORY_SEPARATOR, $junction), DIRECTORY_SEPARATOR);
40148 if (!$this->isJunction($junction)) {
40149 throw new IOException(sprintf('%s is not a junction and thus cannot be removed as one', $junction));
40150 }
40151 $cmd = sprintf('rmdir /S /Q %s', ProcessExecutor::escape($junction));
40152 clearstatcache(true, $junction);
40153
40154 return ($this->getProcess()->execute($cmd, $output) === 0);
40155 }
40156 }
40157 <?php
40158
40159
40160
40161
40162
40163
40164
40165
40166
40167
40168
40169 namespace Composer\Util;
40170
40171 use Composer\Config;
40172 use Composer\IO\IOInterface;
40173
40174
40175
40176
40177 class Git
40178 {
40179 private static $version;
40180
40181
40182 protected $io;
40183
40184 protected $config;
40185
40186 protected $process;
40187
40188 protected $filesystem;
40189
40190 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process, Filesystem $fs)
40191 {
40192 $this->io = $io;
40193 $this->config = $config;
40194 $this->process = $process;
40195 $this->filesystem = $fs;
40196 }
40197
40198 public function runCommand($commandCallable, $url, $cwd, $initialClone = false)
40199 {
40200
40201  $this->config->prohibitUrlByConfig($url, $this->io);
40202
40203 if ($initialClone) {
40204 $origCwd = $cwd;
40205 $cwd = null;
40206 }
40207
40208 if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $url)) {
40209 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.');
40210 }
40211
40212 if (!$initialClone) {
40213
40214  $this->process->execute('git remote -v', $output, $cwd);
40215 if (preg_match('{^(?:composer|origin)\s+https?://(.+):(.+)@([^/]+)}im', $output, $match)) {
40216 $this->io->setAuthentication($match[3], urldecode($match[1]), urldecode($match[2]));
40217 }
40218 }
40219
40220 $protocols = $this->config->get('github-protocols');
40221 if (!is_array($protocols)) {
40222 throw new \RuntimeException('Config value "github-protocols" must be an array, got ' . gettype($protocols));
40223 }
40224
40225  if (preg_match('{^(?:https?|git)://' . self::getGitHubDomainsRegex($this->config) . '/(.*)}', $url, $match)) {
40226 $messages = array();
40227 foreach ($protocols as $protocol) {
40228 if ('ssh' === $protocol) {
40229 $protoUrl = "git@" . $match[1] . ":" . $match[2];
40230 } else {
40231 $protoUrl = $protocol . "://" . $match[1] . "/" . $match[2];
40232 }
40233
40234 if (0 === $this->process->execute(call_user_func($commandCallable, $protoUrl), $ignoredOutput, $cwd)) {
40235 return;
40236 }
40237 $messages[] = '- ' . $protoUrl . "\n" . preg_replace('#^#m', '  ', $this->process->getErrorOutput());
40238 if ($initialClone) {
40239 $this->filesystem->removeDirectory($origCwd);
40240 }
40241 }
40242
40243
40244  $this->throwException('Failed to clone ' . $url . ' via ' . implode(', ', $protocols) . ' protocols, aborting.' . "\n\n" . implode("\n", $messages), $url);
40245 }
40246
40247
40248  $bypassSshForGitHub = preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url) && !in_array('ssh', $protocols, true);
40249
40250 $command = call_user_func($commandCallable, $url);
40251
40252 $auth = null;
40253 if ($bypassSshForGitHub || 0 !== $this->process->execute($command, $ignoredOutput, $cwd)) {
40254
40255  if (preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url, $match)) {
40256 if (!$this->io->hasAuthentication($match[1])) {
40257 $gitHubUtil = new GitHub($this->io, $this->config, $this->process);
40258 $message = 'Cloning failed using an ssh key for authentication, enter your GitHub credentials to access private repos';
40259
40260 if (!$gitHubUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
40261 $gitHubUtil->authorizeOAuthInteractively($match[1], $message);
40262 }
40263 }
40264
40265 if ($this->io->hasAuthentication($match[1])) {
40266 $auth = $this->io->getAuthentication($match[1]);
40267 $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git';
40268 $command = call_user_func($commandCallable, $authUrl);
40269 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
40270 return;
40271 }
40272 }
40273 } elseif (preg_match('{^https://(bitbucket\.org)/(.*)(\.git)?$}U', $url, $match)) { 
40274  $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process);
40275
40276 if (!$this->io->hasAuthentication($match[1])) {
40277 $message = 'Enter your Bitbucket credentials to access private repos';
40278
40279 if (!$bitbucketUtil->authorizeOAuth($match[1]) && $this->io->isInteractive()) {
40280 $bitbucketUtil->authorizeOAuthInteractively($match[1], $message);
40281 $accessToken = $bitbucketUtil->getToken();
40282 $this->io->setAuthentication($match[1], 'x-token-auth', $accessToken);
40283 }
40284 } else { 
40285  $auth = $this->io->getAuthentication($match[1]);
40286
40287
40288  if ($auth['username'] !== 'x-token-auth') {
40289 $accessToken = $bitbucketUtil->requestToken($match[1], $auth['username'], $auth['password']);
40290 if (! empty($accessToken)) {
40291 $this->io->setAuthentication($match[1], 'x-token-auth', $accessToken);
40292 }
40293 }
40294 }
40295
40296 if ($this->io->hasAuthentication($match[1])) {
40297 $auth = $this->io->getAuthentication($match[1]);
40298 $authUrl = 'https://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[1] . '/' . $match[2] . '.git';
40299
40300 $command = call_user_func($commandCallable, $authUrl);
40301 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
40302 return;
40303 }
40304 } else { 
40305  $sshUrl = 'git@bitbucket.org:' . $match[2] . '.git';
40306 $this->io->writeError('    No bitbucket authentication configured. Falling back to ssh.');
40307 $command = call_user_func($commandCallable, $sshUrl);
40308 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
40309 return;
40310 }
40311 }
40312 } elseif ($this->isAuthenticationFailure($url, $match)) { 
40313  if (strpos($match[2], '@')) {
40314 list($authParts, $match[2]) = explode('@', $match[2], 2);
40315 }
40316
40317 $storeAuth = false;
40318 if ($this->io->hasAuthentication($match[2])) {
40319 $auth = $this->io->getAuthentication($match[2]);
40320 } elseif ($this->io->isInteractive()) {
40321 $defaultUsername = null;
40322 if (isset($authParts) && $authParts) {
40323 if (false !== strpos($authParts, ':')) {
40324 list($defaultUsername, ) = explode(':', $authParts, 2);
40325 } else {
40326 $defaultUsername = $authParts;
40327 }
40328 }
40329
40330 $this->io->writeError('    Authentication required (<info>' . parse_url($url, PHP_URL_HOST) . '</info>):');
40331 $auth = array(
40332 'username' => $this->io->ask('      Username: ', $defaultUsername),
40333 'password' => $this->io->askAndHideAnswer('      Password: '),
40334 );
40335 $storeAuth = $this->config->get('store-auths');
40336 }
40337
40338 if ($auth) {
40339 $authUrl = $match[1] . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[2] . $match[3];
40340
40341 $command = call_user_func($commandCallable, $authUrl);
40342 if (0 === $this->process->execute($command, $ignoredOutput, $cwd)) {
40343 $this->io->setAuthentication($match[2], $auth['username'], $auth['password']);
40344 $authHelper = new AuthHelper($this->io, $this->config);
40345 $authHelper->storeAuth($match[2], $storeAuth);
40346
40347 return;
40348 }
40349 }
40350 }
40351
40352 if ($initialClone) {
40353 $this->filesystem->removeDirectory($origCwd);
40354 }
40355 $this->throwException('Failed to execute ' . $command . "\n\n" . $this->process->getErrorOutput(), $url);
40356 }
40357 }
40358
40359 public function syncMirror($url, $dir)
40360 {
40361
40362  if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') {
40363 try {
40364 $commandCallable = function ($url) {
40365 return sprintf('git remote set-url origin %s && git remote update --prune origin', ProcessExecutor::escape($url));
40366 };
40367 $this->runCommand($commandCallable, $url, $dir);
40368 } catch (\Exception $e) {
40369 return false;
40370 }
40371
40372 return true;
40373 }
40374
40375
40376  $this->filesystem->removeDirectory($dir);
40377
40378 $commandCallable = function ($url) use ($dir) {
40379 return sprintf('git clone --mirror %s %s', ProcessExecutor::escape($url), ProcessExecutor::escape($dir));
40380 };
40381
40382 $this->runCommand($commandCallable, $url, $dir, true);
40383
40384 return true;
40385 }
40386
40387 private function isAuthenticationFailure($url, &$match)
40388 {
40389 if (!preg_match('{(https?://)([^/]+)(.*)$}i', $url, $match)) {
40390 return false;
40391 }
40392
40393 $authFailures = array(
40394 'fatal: Authentication failed',
40395 'remote error: Invalid username or password.',
40396 'error: 401 Unauthorized',
40397 'fatal: unable to access',
40398 );
40399
40400 foreach ($authFailures as $authFailure) {
40401 if (strpos($this->process->getErrorOutput(), $authFailure) !== false) {
40402 return true;
40403 }
40404 }
40405
40406 return false;
40407 }
40408
40409 public static function cleanEnv()
40410 {
40411 if (PHP_VERSION_ID < 50400 && ini_get('safe_mode') && false === strpos(ini_get('safe_mode_allowed_env_vars'), 'GIT_ASKPASS')) {
40412 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');
40413 }
40414
40415
40416  if (getenv('GIT_ASKPASS') !== 'echo') {
40417 putenv('GIT_ASKPASS=echo');
40418 unset($_SERVER['GIT_ASKPASS']);
40419 }
40420
40421
40422  if (getenv('GIT_DIR')) {
40423 putenv('GIT_DIR');
40424 unset($_SERVER['GIT_DIR']);
40425 }
40426 if (getenv('GIT_WORK_TREE')) {
40427 putenv('GIT_WORK_TREE');
40428 unset($_SERVER['GIT_WORK_TREE']);
40429 }
40430
40431
40432  if (getenv('LANGUAGE') !== 'C') {
40433 putenv('LANGUAGE=C');
40434 }
40435
40436
40437  putenv("DYLD_LIBRARY_PATH");
40438 unset($_SERVER['DYLD_LIBRARY_PATH']);
40439 }
40440
40441 public static function getGitHubDomainsRegex(Config $config)
40442 {
40443 return '(' . implode('|', array_map('preg_quote', $config->get('github-domains'))) . ')';
40444 }
40445
40446 public static function sanitizeUrl($message)
40447 {
40448 return preg_replace_callback('{://(?P<user>[^@]+?):(?P<password>.+?)@}', function ($m) {
40449 if (preg_match('{^[a-f0-9]{12,}$}', $m[1])) {
40450 return '://***:***@';
40451 }
40452
40453 return '://' . $m[1] . ':***@';
40454 }, $message);
40455 }
40456
40457 private function throwException($message, $url)
40458 {
40459
40460  clearstatcache();
40461
40462 if (0 !== $this->process->execute('git --version', $ignoredOutput)) {
40463 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()));
40464 }
40465
40466 throw new \RuntimeException(self::sanitizeUrl($message));
40467 }
40468
40469
40470
40471
40472
40473
40474 public function getVersion()
40475 {
40476 if (isset(self::$version)) {
40477 return self::$version;
40478 }
40479 if (0 !== $this->process->execute('git --version', $output)) {
40480 return;
40481 }
40482 if (preg_match('/^git version (\d+(?:\.\d+)+)/m', $output, $matches)) {
40483 return self::$version = $matches[1];
40484 }
40485 }
40486 }
40487 <?php
40488
40489
40490
40491
40492
40493
40494
40495
40496
40497
40498
40499 namespace Composer\Util;
40500
40501 use Composer\Factory;
40502 use Composer\IO\IOInterface;
40503 use Composer\Config;
40504 use Composer\Downloader\TransportException;
40505
40506
40507
40508
40509 class GitHub
40510 {
40511 protected $io;
40512 protected $config;
40513 protected $process;
40514 protected $remoteFilesystem;
40515
40516
40517
40518
40519
40520
40521
40522
40523
40524 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
40525 {
40526 $this->io = $io;
40527 $this->config = $config;
40528 $this->process = $process ?: new ProcessExecutor;
40529 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
40530 }
40531
40532
40533
40534
40535
40536
40537
40538 public function authorizeOAuth($originUrl)
40539 {
40540 if (!in_array($originUrl, $this->config->get('github-domains'))) {
40541 return false;
40542 }
40543
40544
40545  if (0 === $this->process->execute('git config github.accesstoken', $output)) {
40546 $this->io->setAuthentication($originUrl, trim($output), 'x-oauth-basic');
40547
40548 return true;
40549 }
40550
40551 return false;
40552 }
40553
40554
40555
40556
40557
40558
40559
40560
40561
40562
40563 public function authorizeOAuthInteractively($originUrl, $message = null)
40564 {
40565 if ($message) {
40566 $this->io->writeError($message);
40567 }
40568
40569 $note = 'Composer';
40570 if ($this->config->get('github-expose-hostname') === true && 0 === $this->process->execute('hostname', $output)) {
40571 $note .= ' on ' . trim($output);
40572 }
40573 $note .= ' ' . date('Y-m-d Hi');
40574
40575 $url = 'https://'.$originUrl.'/settings/tokens/new?scopes=repo&description=' . str_replace('%20', '+', rawurlencode($note));
40576 $this->io->writeError(sprintf('Head to %s', $url));
40577 $this->io->writeError(sprintf('to retrieve a token. It will be stored in "%s" for future use by Composer.', $this->config->getAuthConfigSource()->getName()));
40578
40579 $token = trim($this->io->askAndHideAnswer('Token (hidden): '));
40580
40581 if (!$token) {
40582 $this->io->writeError('<warning>No token given, aborting.</warning>');
40583 $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com <token>"');
40584
40585 return false;
40586 }
40587
40588 $this->io->setAuthentication($originUrl, $token, 'x-oauth-basic');
40589
40590 try {
40591 $apiUrl = ('github.com' === $originUrl) ? 'api.github.com/' : $originUrl . '/api/v3/';
40592
40593 $this->remoteFilesystem->getContents($originUrl, 'https://'. $apiUrl, false, array(
40594 'retry-auth-failure' => false,
40595 ));
40596 } catch (TransportException $e) {
40597 if (in_array($e->getCode(), array(403, 401))) {
40598 $this->io->writeError('<error>Invalid token provided.</error>');
40599 $this->io->writeError('You can also add it manually later by using "composer config --global --auth github-oauth.github.com <token>"');
40600
40601 return false;
40602 }
40603
40604 throw $e;
40605 }
40606
40607
40608  $this->config->getConfigSource()->removeConfigSetting('github-oauth.'.$originUrl);
40609 $this->config->getAuthConfigSource()->addConfigSetting('github-oauth.'.$originUrl, $token);
40610
40611 $this->io->writeError('<info>Token stored successfully.</info>');
40612
40613 return true;
40614 }
40615 }
40616 <?php
40617
40618
40619
40620
40621
40622
40623
40624
40625
40626
40627
40628 namespace Composer\Util;
40629
40630 use Composer\IO\IOInterface;
40631 use Composer\Config;
40632 use Composer\Factory;
40633 use Composer\Downloader\TransportException;
40634 use Composer\Json\JsonFile;
40635
40636
40637
40638
40639 class GitLab
40640 {
40641 protected $io;
40642 protected $config;
40643 protected $process;
40644 protected $remoteFilesystem;
40645
40646
40647
40648
40649
40650
40651
40652
40653
40654 public function __construct(IOInterface $io, Config $config, ProcessExecutor $process = null, RemoteFilesystem $remoteFilesystem = null)
40655 {
40656 $this->io = $io;
40657 $this->config = $config;
40658 $this->process = $process ?: new ProcessExecutor();
40659 $this->remoteFilesystem = $remoteFilesystem ?: Factory::createRemoteFilesystem($this->io, $config);
40660 }
40661
40662
40663
40664
40665
40666
40667
40668
40669 public function authorizeOAuth($originUrl)
40670 {
40671 if (!in_array($originUrl, $this->config->get('gitlab-domains'), true)) {
40672 return false;
40673 }
40674
40675
40676  if (0 === $this->process->execute('git config gitlab.accesstoken', $output)) {
40677 $this->io->setAuthentication($originUrl, trim($output), 'oauth2');
40678
40679 return true;
40680 }
40681
40682
40683  $authTokens = $this->config->get('gitlab-token');
40684
40685 if (isset($authTokens[$originUrl])) {
40686 $this->io->setAuthentication($originUrl, $authTokens[$originUrl], 'private-token');
40687
40688 return true;
40689 }
40690
40691 return false;
40692 }
40693
40694
40695
40696
40697
40698
40699
40700
40701
40702
40703
40704
40705
40706 public function authorizeOAuthInteractively($scheme, $originUrl, $message = null)
40707 {
40708 if ($message) {
40709 $this->io->writeError($message);
40710 }
40711
40712 $this->io->writeError(sprintf('A token will be created and stored in "%s", your password will never be stored', $this->config->getAuthConfigSource()->getName()));
40713 $this->io->writeError('To revoke access to this token you can visit '.$originUrl.'/profile/applications');
40714
40715 $attemptCounter = 0;
40716
40717 while ($attemptCounter++ < 5) {
40718 try {
40719 $response = $this->createToken($scheme, $originUrl);
40720 } catch (TransportException $e) {
40721
40722  
40723  if (in_array($e->getCode(), array(403, 401))) {
40724 if (401 === $e->getCode()) {
40725 $this->io->writeError('Bad credentials.');
40726 } else {
40727 $this->io->writeError('Maximum number of login attempts exceeded. Please try again later.');
40728 }
40729
40730 $this->io->writeError('You can also manually create a personal token at '.$scheme.'://'.$originUrl.'/profile/personal_access_tokens');
40731 $this->io->writeError('Add it using "composer config --global --auth gitlab-token.'.$originUrl.' <token>"');
40732
40733 continue;
40734 }
40735
40736 throw $e;
40737 }
40738
40739 $this->io->setAuthentication($originUrl, $response['access_token'], 'oauth2');
40740
40741
40742  $this->config->getAuthConfigSource()->addConfigSetting('gitlab-oauth.'.$originUrl, $response['access_token']);
40743
40744 return true;
40745 }
40746
40747 throw new \RuntimeException('Invalid GitLab credentials 5 times in a row, aborting.');
40748 }
40749
40750 private function createToken($scheme, $originUrl)
40751 {
40752 $username = $this->io->ask('Username: ');
40753 $password = $this->io->askAndHideAnswer('Password: ');
40754
40755 $headers = array('Content-Type: application/x-www-form-urlencoded');
40756
40757 $apiUrl = $originUrl;
40758 $data = http_build_query(array(
40759 'username' => $username,
40760 'password' => $password,
40761 'grant_type' => 'password',
40762 ), null, '&');
40763 $options = array(
40764 'retry-auth-failure' => false,
40765 'http' => array(
40766 'method' => 'POST',
40767 'header' => $headers,
40768 'content' => $data,
40769 ),
40770 );
40771
40772 $json = $this->remoteFilesystem->getContents($originUrl, $scheme.'://'.$apiUrl.'/oauth/token', false, $options);
40773
40774 $this->io->writeError('Token successfully created');
40775
40776 return JsonFile::parseJson($json);
40777 }
40778 }
40779 <?php
40780
40781
40782
40783
40784
40785
40786
40787
40788
40789
40790
40791 namespace Composer\Util;
40792
40793
40794
40795
40796
40797
40798
40799
40800 class IniHelper
40801 {
40802 const ENV_ORIGINAL = 'COMPOSER_ORIGINAL_INIS';
40803
40804
40805
40806
40807
40808
40809
40810
40811
40812 public static function getAll()
40813 {
40814 if ($env = strval(getenv(self::ENV_ORIGINAL))) {
40815 return explode(PATH_SEPARATOR, $env);
40816 }
40817
40818 $paths = array(strval(php_ini_loaded_file()));
40819
40820 if ($scanned = php_ini_scanned_files()) {
40821 $paths = array_merge($paths, array_map('trim', explode(',', $scanned)));
40822 }
40823
40824 return $paths;
40825 }
40826
40827
40828
40829
40830
40831
40832 public static function getMessage()
40833 {
40834 $paths = self::getAll();
40835
40836 if (empty($paths[0])) {
40837 return 'A php.ini file does not exist. You will have to create one.';
40838 }
40839
40840 return 'The php.ini used by your command-line PHP is: '.$paths[0];
40841 }
40842 }
40843 <?php
40844
40845
40846
40847
40848
40849
40850
40851
40852
40853
40854
40855 namespace Composer\Util;
40856
40857
40858
40859
40860 class NoProxyPattern
40861 {
40862
40863
40864
40865 protected $rules = array();
40866
40867
40868
40869
40870 public function __construct($pattern)
40871 {
40872 $this->rules = preg_split("/[\s,]+/", $pattern);
40873 }
40874
40875
40876
40877
40878
40879
40880
40881
40882 public function test($url)
40883 {
40884 $host = parse_url($url, PHP_URL_HOST);
40885 $port = parse_url($url, PHP_URL_PORT);
40886
40887 if (empty($port)) {
40888 switch (parse_url($url, PHP_URL_SCHEME)) {
40889 case 'http':
40890 $port = 80;
40891 break;
40892 case 'https':
40893 $port = 443;
40894 break;
40895 }
40896 }
40897
40898 foreach ($this->rules as $rule) {
40899 if ($rule == '*') {
40900 return true;
40901 }
40902
40903 $match = false;
40904
40905 list($ruleHost) = explode(':', $rule);
40906 list($base) = explode('/', $ruleHost);
40907
40908 if (filter_var($base, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
40909
40910
40911 if (!isset($ip)) {
40912 $ip = gethostbyname($host);
40913 }
40914
40915 if (strpos($ruleHost, '/') === false) {
40916 $match = $ip === $ruleHost;
40917 } else {
40918
40919  
40920  if ($ip === $host) {
40921 $match = false;
40922 } else {
40923
40924  $match = self::inCIDRBlock($ruleHost, $ip);
40925 }
40926 }
40927 } else {
40928
40929
40930 $haystack = '.' . trim($host, '.') . '.';
40931 $needle = '.'. trim($ruleHost, '.') .'.';
40932 $match = stripos(strrev($haystack), strrev($needle)) === 0;
40933 }
40934
40935
40936  if ($match && strpos($rule, ':') !== false) {
40937 list(, $rulePort) = explode(':', $rule);
40938 if (!empty($rulePort) && $port != $rulePort) {
40939 $match = false;
40940 }
40941 }
40942
40943 if ($match) {
40944 return true;
40945 }
40946 }
40947
40948 return false;
40949 }
40950
40951
40952
40953
40954
40955
40956
40957
40958
40959
40960
40961 private static function inCIDRBlock($cidr, $ip)
40962 {
40963
40964  list($base, $bits) = explode('/', $cidr);
40965
40966
40967  list($a, $b, $c, $d) = explode('.', $base);
40968
40969
40970  $i = ($a << 24) + ($b << 16) + ($c << 8) + $d;
40971 $mask = $bits == 0 ? 0 : (~0 << (32 - $bits));
40972
40973
40974  $low = $i & $mask;
40975
40976
40977  $high = $i | (~$mask & 0xFFFFFFFF);
40978
40979
40980  list($a, $b, $c, $d) = explode('.', $ip);
40981
40982
40983  $check = ($a << 24) + ($b << 16) + ($c << 8) + $d;
40984
40985
40986  
40987  return $check >= $low && $check <= $high;
40988 }
40989 }
40990 <?php
40991
40992
40993
40994
40995
40996
40997
40998
40999
41000
41001
41002 namespace Composer\Util;
41003
41004 use Composer\IO\IOInterface;
41005 use Symfony\Component\Process\Process;
41006
41007
41008
41009
41010 class Perforce
41011 {
41012 protected $path;
41013 protected $p4Depot;
41014 protected $p4Client;
41015 protected $p4User;
41016 protected $p4Password;
41017 protected $p4Port;
41018 protected $p4Stream;
41019 protected $p4ClientSpec;
41020 protected $p4DepotType;
41021 protected $p4Branch;
41022 protected $process;
41023 protected $uniquePerforceClientName;
41024 protected $windowsFlag;
41025 protected $commandResult;
41026
41027 protected $io;
41028
41029 protected $filesystem;
41030
41031 public function __construct($repoConfig, $port, $path, ProcessExecutor $process, $isWindows, IOInterface $io)
41032 {
41033 $this->windowsFlag = $isWindows;
41034 $this->p4Port = $port;
41035 $this->initializePath($path);
41036 $this->process = $process;
41037 $this->initialize($repoConfig);
41038 $this->io = $io;
41039 }
41040
41041 public static function create($repoConfig, $port, $path, ProcessExecutor $process, IOInterface $io)
41042 {
41043 return new Perforce($repoConfig, $port, $path, $process, Platform::isWindows(), $io);
41044 }
41045
41046 public static function checkServerExists($url, ProcessExecutor $processExecutor)
41047 {
41048 $output = null;
41049
41050 return 0 === $processExecutor->execute('p4 -p ' . $url . ' info -s', $output);
41051 }
41052
41053 public function initialize($repoConfig)
41054 {
41055 $this->uniquePerforceClientName = $this->generateUniquePerforceClientName();
41056 if (!$repoConfig) {
41057 return;
41058 }
41059 if (isset($repoConfig['unique_perforce_client_name'])) {
41060 $this->uniquePerforceClientName = $repoConfig['unique_perforce_client_name'];
41061 }
41062
41063 if (isset($repoConfig['depot'])) {
41064 $this->p4Depot = $repoConfig['depot'];
41065 }
41066 if (isset($repoConfig['branch'])) {
41067 $this->p4Branch = $repoConfig['branch'];
41068 }
41069 if (isset($repoConfig['p4user'])) {
41070 $this->p4User = $repoConfig['p4user'];
41071 } else {
41072 $this->p4User = $this->getP4variable('P4USER');
41073 }
41074 if (isset($repoConfig['p4password'])) {
41075 $this->p4Password = $repoConfig['p4password'];
41076 }
41077 }
41078
41079 public function initializeDepotAndBranch($depot, $branch)
41080 {
41081 if (isset($depot)) {
41082 $this->p4Depot = $depot;
41083 }
41084 if (isset($branch)) {
41085 $this->p4Branch = $branch;
41086 }
41087 }
41088
41089 public function generateUniquePerforceClientName()
41090 {
41091 return gethostname() . "_" . time();
41092 }
41093
41094 public function cleanupClientSpec()
41095 {
41096 $client = $this->getClient();
41097 $task = 'client -d ' . $client;
41098 $useP4Client = false;
41099 $command = $this->generateP4Command($task, $useP4Client);
41100 $this->executeCommand($command);
41101 $clientSpec = $this->getP4ClientSpec();
41102 $fileSystem = $this->getFilesystem();
41103 $fileSystem->remove($clientSpec);
41104 }
41105
41106 protected function executeCommand($command)
41107 {
41108 $this->commandResult = "";
41109 $exit_code = $this->process->execute($command, $this->commandResult);
41110
41111 return $exit_code;
41112 }
41113
41114 public function getClient()
41115 {
41116 if (!isset($this->p4Client)) {
41117 $cleanStreamName = str_replace('@', '', str_replace('/', '_', str_replace('//', '', $this->getStream())));
41118 $this->p4Client = 'composer_perforce_' . $this->uniquePerforceClientName . '_' . $cleanStreamName;
41119 }
41120
41121 return $this->p4Client;
41122 }
41123
41124 protected function getPath()
41125 {
41126 return $this->path;
41127 }
41128
41129 public function initializePath($path)
41130 {
41131 $this->path = $path;
41132 $fs = $this->getFilesystem();
41133 $fs->ensureDirectoryExists($path);
41134 }
41135
41136 protected function getPort()
41137 {
41138 return $this->p4Port;
41139 }
41140
41141 public function setStream($stream)
41142 {
41143 $this->p4Stream = $stream;
41144 $index = strrpos($stream, '/');
41145
41146  if ($index > 2) {
41147 $this->p4DepotType = 'stream';
41148 }
41149 }
41150
41151 public function isStream()
41152 {
41153 return (strcmp($this->p4DepotType, 'stream') === 0);
41154 }
41155
41156 public function getStream()
41157 {
41158 if (!isset($this->p4Stream)) {
41159 if ($this->isStream()) {
41160 $this->p4Stream = '//' . $this->p4Depot . '/' . $this->p4Branch;
41161 } else {
41162 $this->p4Stream = '//' . $this->p4Depot;
41163 }
41164 }
41165
41166 return $this->p4Stream;
41167 }
41168
41169 public function getStreamWithoutLabel($stream)
41170 {
41171 $index = strpos($stream, '@');
41172 if ($index === false) {
41173 return $stream;
41174 }
41175
41176 return substr($stream, 0, $index);
41177 }
41178
41179 public function getP4ClientSpec()
41180 {
41181 $p4clientSpec = $this->path . '/' . $this->getClient() . '.p4.spec';
41182
41183 return $p4clientSpec;
41184 }
41185
41186 public function getUser()
41187 {
41188 return $this->p4User;
41189 }
41190
41191 public function setUser($user)
41192 {
41193 $this->p4User = $user;
41194 }
41195
41196 public function queryP4User()
41197 {
41198 $this->getUser();
41199 if (strlen($this->p4User) > 0) {
41200 return;
41201 }
41202 $this->p4User = $this->getP4variable('P4USER');
41203 if (strlen($this->p4User) > 0) {
41204 return;
41205 }
41206 $this->p4User = $this->io->ask('Enter P4 User:');
41207 if ($this->windowsFlag) {
41208 $command = 'p4 set P4USER=' . $this->p4User;
41209 } else {
41210 $command = 'export P4USER=' . $this->p4User;
41211 }
41212 $this->executeCommand($command);
41213 }
41214
41215 protected function getP4variable($name)
41216 {
41217 if ($this->windowsFlag) {
41218 $command = 'p4 set';
41219 $this->executeCommand($command);
41220 $result = trim($this->commandResult);
41221 $resArray = explode(PHP_EOL, $result);
41222 foreach ($resArray as $line) {
41223 $fields = explode('=', $line);
41224 if (strcmp($name, $fields[0]) == 0) {
41225 $index = strpos($fields[1], ' ');
41226 if ($index === false) {
41227 $value = $fields[1];
41228 } else {
41229 $value = substr($fields[1], 0, $index);
41230 }
41231 $value = trim($value);
41232
41233 return $value;
41234 }
41235 }
41236
41237 return null;
41238 } else {
41239 $command = 'echo $' . $name;
41240 $this->executeCommand($command);
41241 $result = trim($this->commandResult);
41242
41243 return $result;
41244 }
41245 }
41246
41247 public function queryP4Password()
41248 {
41249 if (isset($this->p4Password)) {
41250 return $this->p4Password;
41251 }
41252 $password = $this->getP4variable('P4PASSWD');
41253 if (strlen($password) <= 0) {
41254 $password = $this->io->askAndHideAnswer('Enter password for Perforce user ' . $this->getUser() . ': ');
41255 }
41256 $this->p4Password = $password;
41257
41258 return $password;
41259 }
41260
41261 public function generateP4Command($command, $useClient = true)
41262 {
41263 $p4Command = 'p4 ';
41264 $p4Command = $p4Command . '-u ' . $this->getUser() . ' ';
41265 if ($useClient) {
41266 $p4Command = $p4Command . '-c ' . $this->getClient() . ' ';
41267 }
41268 $p4Command = $p4Command . '-p ' . $this->getPort() . ' ';
41269 $p4Command = $p4Command . $command;
41270
41271 return $p4Command;
41272 }
41273
41274 public function isLoggedIn()
41275 {
41276 $command = $this->generateP4Command('login -s', false);
41277 $exitCode = $this->executeCommand($command);
41278 if ($exitCode) {
41279 $errorOutput = $this->process->getErrorOutput();
41280 $index = strpos($errorOutput, $this->getUser());
41281 if ($index === false) {
41282 $index = strpos($errorOutput, 'p4');
41283 if ($index === false) {
41284 return false;
41285 }
41286 throw new \Exception('p4 command not found in path: ' . $errorOutput);
41287 }
41288 throw new \Exception('Invalid user name: ' . $this->getUser());
41289 }
41290
41291 return true;
41292 }
41293
41294 public function connectClient()
41295 {
41296 $p4CreateClientCommand = $this->generateP4Command(
41297 'client -i < ' . str_replace(" ", "\\ ", $this->getP4ClientSpec())
41298 );
41299 $this->executeCommand($p4CreateClientCommand);
41300 }
41301
41302 public function syncCodeBase($sourceReference)
41303 {
41304 $prevDir = getcwd();
41305 chdir($this->path);
41306 $p4SyncCommand = $this->generateP4Command('sync -f ');
41307 if (null !== $sourceReference) {
41308 $p4SyncCommand = $p4SyncCommand . '@' . $sourceReference;
41309 }
41310 $this->executeCommand($p4SyncCommand);
41311 chdir($prevDir);
41312 }
41313
41314 public function writeClientSpecToFile($spec)
41315 {
41316 fwrite($spec, 'Client: ' . $this->getClient() . PHP_EOL . PHP_EOL);
41317 fwrite($spec, 'Update: ' . date('Y/m/d H:i:s') . PHP_EOL . PHP_EOL);
41318 fwrite($spec, 'Access: ' . date('Y/m/d H:i:s') . PHP_EOL);
41319 fwrite($spec, 'Owner:  ' . $this->getUser() . PHP_EOL . PHP_EOL);
41320 fwrite($spec, 'Description:' . PHP_EOL);
41321 fwrite($spec, '  Created by ' . $this->getUser() . ' from composer.' . PHP_EOL . PHP_EOL);
41322 fwrite($spec, 'Root: ' . $this->getPath() . PHP_EOL . PHP_EOL);
41323 fwrite($spec, 'Options:  noallwrite noclobber nocompress unlocked modtime rmdir' . PHP_EOL . PHP_EOL);
41324 fwrite($spec, 'SubmitOptions:  revertunchanged' . PHP_EOL . PHP_EOL);
41325 fwrite($spec, 'LineEnd:  local' . PHP_EOL . PHP_EOL);
41326 if ($this->isStream()) {
41327 fwrite($spec, 'Stream:' . PHP_EOL);
41328 fwrite($spec, '  ' . $this->getStreamWithoutLabel($this->p4Stream) . PHP_EOL);
41329 } else {
41330 fwrite(
41331 $spec,
41332 'View:  ' . $this->getStream() . '/...  //' . $this->getClient() . '/... ' . PHP_EOL
41333 );
41334 }
41335 }
41336
41337 public function writeP4ClientSpec()
41338 {
41339 $clientSpec = $this->getP4ClientSpec();
41340 $spec = fopen($clientSpec, 'w');
41341 try {
41342 $this->writeClientSpecToFile($spec);
41343 } catch (\Exception $e) {
41344 fclose($spec);
41345 throw $e;
41346 }
41347 fclose($spec);
41348 }
41349
41350 protected function read($pipe, $name)
41351 {
41352 if (feof($pipe)) {
41353 return;
41354 }
41355 $line = fgets($pipe);
41356 while ($line !== false) {
41357 $line = fgets($pipe);
41358 }
41359
41360 return;
41361 }
41362
41363 public function windowsLogin($password)
41364 {
41365 $command = $this->generateP4Command(' login -a');
41366 $process = new Process($command, null, null, $password);
41367
41368 return $process->run();
41369 }
41370
41371 public function p4Login()
41372 {
41373 $this->queryP4User();
41374 if (!$this->isLoggedIn()) {
41375 $password = $this->queryP4Password();
41376 if ($this->windowsFlag) {
41377 $this->windowsLogin($password);
41378 } else {
41379 $command = 'echo ' . $password . ' | ' . $this->generateP4Command(' login -a', false);
41380 $exitCode = $this->executeCommand($command);
41381 $result = trim($this->commandResult);
41382 if ($exitCode) {
41383 throw new \Exception("Error logging in:" . $this->process->getErrorOutput());
41384 }
41385 }
41386 }
41387 }
41388
41389 public function getComposerInformation($identifier)
41390 {
41391 $composerFileContent = $this->getFileContent('composer.json', $identifier);
41392
41393 if (!$composerFileContent) {
41394 return;
41395 }
41396
41397 return json_decode($composerFileContent, true);
41398 }
41399
41400 public function getFileContent($file, $identifier)
41401 {
41402 $path = $this->getFilePath($file, $identifier);
41403
41404 $command = $this->generateP4Command(' print ' . $path);
41405 $this->executeCommand($command);
41406 $result = $this->commandResult;
41407
41408 if (!trim($result)) {
41409 return null;
41410 }
41411
41412 return $result;
41413 }
41414
41415 public function getFilePath($file, $identifier)
41416 {
41417 $index = strpos($identifier, '@');
41418 if ($index === false) {
41419 $path = $identifier. '/' . $file;
41420
41421 return $path;
41422 } else {
41423 $path = substr($identifier, 0, $index) . '/' . $file . substr($identifier, $index);
41424 $command = $this->generateP4Command(' files ' . $path, false);
41425 $this->executeCommand($command);
41426 $result = $this->commandResult;
41427 $index2 = strpos($result, 'no such file(s).');
41428 if ($index2 === false) {
41429 $index3 = strpos($result, 'change');
41430 if ($index3 !== false) {
41431 $phrase = trim(substr($result, $index3));
41432 $fields = explode(' ', $phrase);
41433
41434 return substr($identifier, 0, $index) . '/' . $file . '@' . $fields[1];
41435 }
41436 }
41437 }
41438
41439 return null;
41440 }
41441
41442 public function getBranches()
41443 {
41444 $possibleBranches = array();
41445 if (!$this->isStream()) {
41446 $possibleBranches[$this->p4Branch] = $this->getStream();
41447 } else {
41448 $command = $this->generateP4Command('streams //' . $this->p4Depot . '/...');
41449 $this->executeCommand($command);
41450 $result = $this->commandResult;
41451 $resArray = explode(PHP_EOL, $result);
41452 foreach ($resArray as $line) {
41453 $resBits = explode(' ', $line);
41454 if (count($resBits) > 4) {
41455 $branch = preg_replace('/[^A-Za-z0-9 ]/', '', $resBits[4]);
41456 $possibleBranches[$branch] = $resBits[1];
41457 }
41458 }
41459 }
41460 $command = $this->generateP4Command('changes '. $this->getStream() . '/...', false);
41461 $this->executeCommand($command);
41462 $result = $this->commandResult;
41463 $resArray = explode(PHP_EOL, $result);
41464 $lastCommit = $resArray[0];
41465 $lastCommitArr = explode(' ', $lastCommit);
41466 $lastCommitNum = $lastCommitArr[1];
41467
41468 $branches = array('master' => $possibleBranches[$this->p4Branch] . '@'. $lastCommitNum);
41469
41470 return $branches;
41471 }
41472
41473 public function getTags()
41474 {
41475 $command = $this->generateP4Command('labels');
41476 $this->executeCommand($command);
41477 $result = $this->commandResult;
41478 $resArray = explode(PHP_EOL, $result);
41479 $tags = array();
41480 foreach ($resArray as $line) {
41481 $index = strpos($line, 'Label');
41482 if (!($index === false)) {
41483 $fields = explode(' ', $line);
41484 $tags[$fields[1]] = $this->getStream() . '@' . $fields[1];
41485 }
41486 }
41487
41488 return $tags;
41489 }
41490
41491 public function checkStream()
41492 {
41493 $command = $this->generateP4Command('depots', false);
41494 $this->executeCommand($command);
41495 $result = $this->commandResult;
41496 $resArray = explode(PHP_EOL, $result);
41497 foreach ($resArray as $line) {
41498 $index = strpos($line, 'Depot');
41499 if (!($index === false)) {
41500 $fields = explode(' ', $line);
41501 if (strcmp($this->p4Depot, $fields[1]) === 0) {
41502 $this->p4DepotType = $fields[3];
41503
41504 return $this->isStream();
41505 }
41506 }
41507 }
41508
41509 return false;
41510 }
41511
41512
41513
41514
41515
41516 protected function getChangeList($reference)
41517 {
41518 $index = strpos($reference, '@');
41519 if ($index === false) {
41520 return null;
41521 }
41522 $label = substr($reference, $index);
41523 $command = $this->generateP4Command(' changes -m1 ' . $label);
41524 $this->executeCommand($command);
41525 $changes = $this->commandResult;
41526 if (strpos($changes, 'Change') !== 0) {
41527 return null;
41528 }
41529 $fields = explode(' ', $changes);
41530 $changeList = $fields[1];
41531
41532 return $changeList;
41533 }
41534
41535
41536
41537
41538
41539
41540 public function getCommitLogs($fromReference, $toReference)
41541 {
41542 $fromChangeList = $this->getChangeList($fromReference);
41543 if ($fromChangeList === null) {
41544 return null;
41545 }
41546 $toChangeList = $this->getChangeList($toReference);
41547 if ($toChangeList === null) {
41548 return null;
41549 }
41550 $index = strpos($fromReference, '@');
41551 $main = substr($fromReference, 0, $index) . '/...';
41552 $command = $this->generateP4Command('filelog ' . $main . '@' . $fromChangeList. ',' . $toChangeList);
41553 $this->executeCommand($command);
41554 $result = $this->commandResult;
41555
41556 return $result;
41557 }
41558
41559 public function getFilesystem()
41560 {
41561 if (empty($this->filesystem)) {
41562 $this->filesystem = new Filesystem($this->process);
41563 }
41564
41565 return $this->filesystem;
41566 }
41567
41568 public function setFilesystem(Filesystem $fs)
41569 {
41570 $this->filesystem = $fs;
41571 }
41572 }
41573 <?php
41574
41575
41576
41577
41578
41579
41580
41581
41582
41583
41584
41585 namespace Composer\Util;
41586
41587
41588
41589
41590
41591
41592 class Platform
41593 {
41594
41595
41596
41597
41598
41599
41600 public static function expandPath($path)
41601 {
41602 if (preg_match('#^~[\\/]#', $path)) {
41603 return self::getUserDirectory() . substr($path, 1);
41604 }
41605
41606 return preg_replace_callback('#^(\$|(?P<percent>%))(?P<var>\w++)(?(percent)%)(?P<path>.*)#', function ($matches) {
41607
41608  if (Platform::isWindows() && $matches['var'] == 'HOME') {
41609 return (getenv('HOME') ?: getenv('USERPROFILE')) . $matches['path'];
41610 }
41611
41612 return getenv($matches['var']) . $matches['path'];
41613 }, $path);
41614 }
41615
41616
41617
41618
41619
41620 public static function getUserDirectory()
41621 {
41622 if (false !== ($home = getenv('HOME'))) {
41623 return $home;
41624 }
41625
41626 if (self::isWindows() && false !== ($home = getenv('USERPROFILE'))) {
41627 return $home;
41628 }
41629
41630 if (function_exists('posix_getuid') && function_exists('posix_getpwuid')) {
41631 $info = posix_getpwuid(posix_getuid());
41632
41633 return $info['dir'];
41634 }
41635
41636 throw new \RuntimeException('Could not determine user directory');
41637 }
41638
41639
41640
41641
41642 public static function isWindows()
41643 {
41644 return defined('PHP_WINDOWS_VERSION_BUILD');
41645 }
41646
41647
41648
41649
41650
41651 public static function strlen($str)
41652 {
41653 static $useMbString = null;
41654 if (null === $useMbString) {
41655 $useMbString = function_exists('mb_strlen') && ini_get('mbstring.func_overload');
41656 }
41657
41658 if ($useMbString) {
41659 return mb_strlen($str, '8bit');
41660 }
41661
41662 return strlen($str);
41663 }
41664 }
41665 <?php
41666
41667
41668
41669
41670
41671
41672
41673
41674
41675
41676
41677 namespace Composer\Util;
41678
41679 use Symfony\Component\Process\Process;
41680 use Symfony\Component\Process\ProcessUtils;
41681 use Composer\IO\IOInterface;
41682
41683
41684
41685
41686 class ProcessExecutor
41687 {
41688 protected static $timeout = 300;
41689
41690 protected $captureOutput;
41691 protected $errorOutput;
41692 protected $io;
41693
41694 public function __construct(IOInterface $io = null)
41695 {
41696 $this->io = $io;
41697 }
41698
41699
41700
41701
41702
41703
41704
41705
41706
41707
41708 public function execute($command, &$output = null, $cwd = null)
41709 {
41710 if ($this->io && $this->io->isDebug()) {
41711 $safeCommand = preg_replace_callback('{://(?P<user>[^:/\s]+):(?P<password>[^@\s/]+)@}i', function ($m) {
41712 if (preg_match('{^[a-f0-9]{12,}$}', $m['user'])) {
41713 return '://***:***@';
41714 }
41715
41716 return '://'.$m['user'].':***@';
41717 }, $command);
41718 $this->io->writeError('Executing command ('.($cwd ?: 'CWD').'): '.$safeCommand);
41719 }
41720
41721
41722  
41723  if (null === $cwd && Platform::isWindows() && false !== strpos($command, 'git') && getcwd()) {
41724 $cwd = realpath(getcwd());
41725 }
41726
41727 $this->captureOutput = count(func_get_args()) > 1;
41728 $this->errorOutput = null;
41729 $process = new Process($command, $cwd, null, null, static::getTimeout());
41730
41731 $callback = is_callable($output) ? $output : array($this, 'outputHandler');
41732 $process->run($callback);
41733
41734 if ($this->captureOutput && !is_callable($output)) {
41735 $output = $process->getOutput();
41736 }
41737
41738 $this->errorOutput = $process->getErrorOutput();
41739
41740 return $process->getExitCode();
41741 }
41742
41743 public function splitLines($output)
41744 {
41745 $output = trim($output);
41746
41747 return ((string) $output === '') ? array() : preg_split('{\r?\n}', $output);
41748 }
41749
41750
41751
41752
41753
41754
41755 public function getErrorOutput()
41756 {
41757 return $this->errorOutput;
41758 }
41759
41760 public function outputHandler($type, $buffer)
41761 {
41762 if ($this->captureOutput) {
41763 return;
41764 }
41765
41766 if (null === $this->io) {
41767 echo $buffer;
41768
41769 return;
41770 }
41771
41772 if (Process::ERR === $type) {
41773 $this->io->writeError($buffer, false);
41774 } else {
41775 $this->io->write($buffer, false);
41776 }
41777 }
41778
41779 public static function getTimeout()
41780 {
41781 return static::$timeout;
41782 }
41783
41784 public static function setTimeout($timeout)
41785 {
41786 static::$timeout = $timeout;
41787 }
41788
41789
41790
41791
41792
41793
41794
41795
41796 public static function escape($argument)
41797 {
41798 return ProcessUtils::escapeArgument($argument);
41799 }
41800 }
41801 <?php
41802
41803
41804
41805
41806
41807
41808
41809
41810
41811
41812
41813 namespace Composer\Util;
41814
41815 use Composer\Config;
41816 use Composer\IO\IOInterface;
41817 use Composer\Downloader\TransportException;
41818 use Composer\CaBundle\CaBundle;
41819 use Psr\Log\LoggerInterface;
41820
41821
41822
41823
41824
41825
41826 class RemoteFilesystem
41827 {
41828 private $io;
41829 private $config;
41830 private $scheme;
41831 private $bytesMax;
41832 private $originUrl;
41833 private $fileUrl;
41834 private $fileName;
41835 private $retry;
41836 private $progress;
41837 private $lastProgress;
41838 private $options = array();
41839 private $peerCertificateMap = array();
41840 private $disableTls = false;
41841 private $retryAuthFailure;
41842 private $lastHeaders;
41843 private $storeAuth;
41844 private $degradedMode = false;
41845 private $redirects;
41846 private $maxRedirects = 20;
41847
41848
41849
41850
41851
41852
41853
41854
41855
41856 public function __construct(IOInterface $io, Config $config = null, array $options = array(), $disableTls = false)
41857 {
41858 $this->io = $io;
41859
41860
41861  
41862  if ($disableTls === false) {
41863 $this->options = $this->getTlsDefaults($options);
41864 } else {
41865 $this->disableTls = true;
41866 }
41867
41868
41869  $this->options = array_replace_recursive($this->options, $options);
41870 $this->config = $config;
41871 }
41872
41873
41874
41875
41876
41877
41878
41879
41880
41881
41882
41883
41884 public function copy($originUrl, $fileUrl, $fileName, $progress = true, $options = array())
41885 {
41886 return $this->get($originUrl, $fileUrl, $options, $fileName, $progress);
41887 }
41888
41889
41890
41891
41892
41893
41894
41895
41896
41897
41898
41899 public function getContents($originUrl, $fileUrl, $progress = true, $options = array())
41900 {
41901 return $this->get($originUrl, $fileUrl, $options, null, $progress);
41902 }
41903
41904
41905
41906
41907
41908
41909 public function getOptions()
41910 {
41911 return $this->options;
41912 }
41913
41914
41915
41916
41917
41918
41919 public function setOptions(array $options)
41920 {
41921 $this->options = array_replace_recursive($this->options, $options);
41922 }
41923
41924 public function isTlsDisabled()
41925 {
41926 return $this->disableTls === true;
41927 }
41928
41929
41930
41931
41932
41933
41934 public function getLastHeaders()
41935 {
41936 return $this->lastHeaders;
41937 }
41938
41939
41940
41941
41942
41943
41944 public function findHeaderValue(array $headers, $name)
41945 {
41946 $value = null;
41947 foreach ($headers as $header) {
41948 if (preg_match('{^'.$name.':\s*(.+?)\s*$}i', $header, $match)) {
41949 $value = $match[1];
41950 } elseif (preg_match('{^HTTP/}i', $header)) {
41951
41952  
41953  $value = null;
41954 }
41955 }
41956
41957 return $value;
41958 }
41959
41960
41961
41962
41963
41964 public function findStatusCode(array $headers)
41965 {
41966 $value = null;
41967 foreach ($headers as $header) {
41968 if (preg_match('{^HTTP/\S+ (\d+)}i', $header, $match)) {
41969
41970  
41971  $value = (int) $match[1];
41972 }
41973 }
41974
41975 return $value;
41976 }
41977
41978
41979
41980
41981
41982
41983
41984
41985
41986
41987
41988
41989
41990
41991
41992 protected function get($originUrl, $fileUrl, $additionalOptions = array(), $fileName = null, $progress = true)
41993 {
41994 if (strpos($originUrl, '.github.com') === (strlen($originUrl) - 11)) {
41995 $originUrl = 'github.com';
41996 }
41997
41998 $this->scheme = parse_url($fileUrl, PHP_URL_SCHEME);
41999 $this->bytesMax = 0;
42000 $this->originUrl = $originUrl;
42001 $this->fileUrl = $fileUrl;
42002 $this->fileName = $fileName;
42003 $this->progress = $progress;
42004 $this->lastProgress = null;
42005 $this->retryAuthFailure = true;
42006 $this->lastHeaders = array();
42007 $this->redirects = 1; 
42008
42009
42010  if (preg_match('{^https?://(.+):(.+)@([^/]+)}i', $fileUrl, $match)) {
42011 $this->io->setAuthentication($originUrl, urldecode($match[1]), urldecode($match[2]));
42012 }
42013
42014 $tempAdditionalOptions = $additionalOptions;
42015 if (isset($tempAdditionalOptions['retry-auth-failure'])) {
42016 $this->retryAuthFailure = (bool) $tempAdditionalOptions['retry-auth-failure'];
42017
42018 unset($tempAdditionalOptions['retry-auth-failure']);
42019 }
42020
42021 $isRedirect = false;
42022 if (isset($tempAdditionalOptions['redirects'])) {
42023 $this->redirects = $tempAdditionalOptions['redirects'];
42024 $isRedirect = true;
42025
42026 unset($tempAdditionalOptions['redirects']);
42027 }
42028
42029 $options = $this->getOptionsForUrl($originUrl, $tempAdditionalOptions);
42030 unset($tempAdditionalOptions);
42031 $userlandFollow = isset($options['http']['follow_location']) && !$options['http']['follow_location'];
42032
42033 $origFileUrl = $fileUrl;
42034
42035 if (isset($options['github-token'])) {
42036
42037  if (preg_match('{^https?://([a-z0-9-]+\.)*github\.com/}', $fileUrl)) {
42038 $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token='.$options['github-token'];
42039 }
42040 unset($options['github-token']);
42041 }
42042
42043 if (isset($options['gitlab-token'])) {
42044 $fileUrl .= (false === strpos($fileUrl, '?') ? '?' : '&') . 'access_token='.$options['gitlab-token'];
42045 unset($options['gitlab-token']);
42046 }
42047
42048 if (isset($options['http'])) {
42049 $options['http']['ignore_errors'] = true;
42050 }
42051
42052 if ($this->degradedMode && substr($fileUrl, 0, 21) === 'http://packagist.org/') {
42053
42054  $fileUrl = 'http://' . gethostbyname('packagist.org') . substr($fileUrl, 20);
42055 $degradedPackagist = true;
42056 }
42057
42058 $ctx = StreamContextFactory::getContext($fileUrl, $options, array('notification' => array($this, 'callbackGet')));
42059
42060 $actualContextOptions = stream_context_get_options($ctx);
42061 $usingProxy = !empty($actualContextOptions['http']['proxy']) ? ' using proxy ' . $actualContextOptions['http']['proxy'] : '';
42062 $this->io->writeError((substr($origFileUrl, 0, 4) === 'http' ? 'Downloading ' : 'Reading ') . $origFileUrl . $usingProxy, true, IOInterface::DEBUG);
42063 unset($origFileUrl, $actualContextOptions);
42064
42065
42066  if ((substr($fileUrl, 0, 23) !== 'http://packagist.org/p/' || (false === strpos($fileUrl, '$') && false === strpos($fileUrl, '%24'))) && empty($degradedPackagist) && $this->config) {
42067 $this->config->prohibitUrlByConfig($fileUrl, $this->io);
42068 }
42069
42070 if ($this->progress && !$isRedirect) {
42071 $this->io->writeError("Downloading (<comment>connecting...</comment>)", false);
42072 }
42073
42074 $errorMessage = '';
42075 $errorCode = 0;
42076 $result = false;
42077 set_error_handler(function ($code, $msg) use (&$errorMessage) {
42078 if ($errorMessage) {
42079 $errorMessage .= "\n";
42080 }
42081 $errorMessage .= preg_replace('{^file_get_contents\(.*?\): }', '', $msg);
42082 });
42083 try {
42084 $result = file_get_contents($fileUrl, false, $ctx);
42085
42086 $contentLength = !empty($http_response_header[0]) ? $this->findHeaderValue($http_response_header, 'content-length') : null;
42087 if ($contentLength && Platform::strlen($result) < $contentLength) {
42088
42089  $e = new TransportException('Content-Length mismatch, received '.Platform::strlen($result).' bytes out of the expected '.$contentLength);
42090 $e->setHeaders($http_response_header);
42091 $e->setStatusCode($this->findStatusCode($http_response_header));
42092 $e->setResponse($result);
42093 $this->io->writeError('Content-Length mismatch, received '.Platform::strlen($result).' out of '.$contentLength.' bytes: (' . base64_encode($result).')', true, IOInterface::DEBUG);
42094
42095 throw $e;
42096 }
42097
42098 if (PHP_VERSION_ID < 50600 && !empty($options['ssl']['peer_fingerprint'])) {
42099
42100  $params = stream_context_get_params($ctx);
42101 $expectedPeerFingerprint = $options['ssl']['peer_fingerprint'];
42102 $peerFingerprint = TlsHelper::getCertificateFingerprint($params['options']['ssl']['peer_certificate']);
42103
42104
42105  if ($expectedPeerFingerprint !== $peerFingerprint) {
42106 throw new TransportException('Peer fingerprint did not match');
42107 }
42108 }
42109 } catch (\Exception $e) {
42110 if ($e instanceof TransportException && !empty($http_response_header[0])) {
42111 $e->setHeaders($http_response_header);
42112 $e->setStatusCode($this->findStatusCode($http_response_header));
42113 }
42114 if ($e instanceof TransportException && $result !== false) {
42115 $e->setResponse($result);
42116 }
42117 $result = false;
42118 }
42119 if ($errorMessage && !ini_get('allow_url_fopen')) {
42120 $errorMessage = 'allow_url_fopen must be enabled in php.ini ('.$errorMessage.')';
42121 }
42122 restore_error_handler();
42123 if (isset($e) && !$this->retry) {
42124 if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
42125 $this->degradedMode = true;
42126 $this->io->writeError('');
42127 $this->io->writeError(array(
42128 '<error>'.$e->getMessage().'</error>',
42129 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
42130 ));
42131
42132 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
42133 }
42134
42135 throw $e;
42136 }
42137
42138 $statusCode = null;
42139 $contentType = null;
42140 if (!empty($http_response_header[0])) {
42141 $statusCode = $this->findStatusCode($http_response_header);
42142 $contentType = $this->findHeaderValue($http_response_header, 'content-type');
42143 }
42144
42145
42146  if ($originUrl === 'bitbucket.org'
42147 && !$this->isPublicBitBucketDownload($fileUrl)
42148 && substr($fileUrl, -4) === '.zip'
42149 && $contentType && preg_match('{^text/html\b}i', $contentType)
42150 ) {
42151 $result = false;
42152 if ($this->retryAuthFailure) {
42153 $this->promptAuthAndRetry(401);
42154 }
42155 }
42156
42157
42158  if ($statusCode === 404
42159 && $this->config && in_array($originUrl, $this->config->get('gitlab-domains'), true)
42160 && false !== strpos($fileUrl, 'archive.zip')
42161 ) {
42162 $result = false;
42163 if ($this->retryAuthFailure) {
42164 $this->promptAuthAndRetry(401);
42165 }
42166 }
42167
42168
42169  $hasFollowedRedirect = false;
42170 if ($userlandFollow && $statusCode >= 300 && $statusCode <= 399 && $statusCode !== 304 && $this->redirects < $this->maxRedirects) {
42171 $hasFollowedRedirect = true;
42172 $result = $this->handleRedirect($http_response_header, $additionalOptions, $result);
42173 }
42174
42175
42176  if ($statusCode && $statusCode >= 400 && $statusCode <= 599) {
42177 if (!$this->retry) {
42178 if ($this->progress && !$this->retry && !$isRedirect) {
42179 $this->io->overwriteError("Downloading (<error>failed</error>)", false);
42180 }
42181
42182 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded ('.$http_response_header[0].')', $statusCode);
42183 $e->setHeaders($http_response_header);
42184 $e->setResponse($result);
42185 $e->setStatusCode($statusCode);
42186 throw $e;
42187 }
42188 $result = false;
42189 }
42190
42191 if ($this->progress && !$this->retry && !$isRedirect) {
42192 $this->io->overwriteError("Downloading (".($result === false ? '<error>failed</error>' : '<comment>100%</comment>').")", false);
42193 }
42194
42195
42196  if ($result && extension_loaded('zlib') && substr($fileUrl, 0, 4) === 'http' && !$hasFollowedRedirect) {
42197 $contentEncoding = $this->findHeaderValue($http_response_header, 'content-encoding');
42198 $decode = $contentEncoding && 'gzip' === strtolower($contentEncoding);
42199
42200 if ($decode) {
42201 try {
42202 if (PHP_VERSION_ID >= 50400) {
42203 $result = zlib_decode($result);
42204 } else {
42205
42206  $result = file_get_contents('compress.zlib://data:application/octet-stream;base64,'.base64_encode($result));
42207 }
42208
42209 if (!$result) {
42210 throw new TransportException('Failed to decode zlib stream');
42211 }
42212 } catch (\Exception $e) {
42213 if ($this->degradedMode) {
42214 throw $e;
42215 }
42216
42217 $this->degradedMode = true;
42218 $this->io->writeError(array(
42219 '',
42220 '<error>Failed to decode response: '.$e->getMessage().'</error>',
42221 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
42222 ));
42223
42224 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
42225 }
42226 }
42227 }
42228
42229
42230  if (false !== $result && null !== $fileName && !$isRedirect) {
42231 if ('' === $result) {
42232 throw new TransportException('"'.$this->fileUrl.'" appears broken, and returned an empty 200 response');
42233 }
42234
42235 $errorMessage = '';
42236 set_error_handler(function ($code, $msg) use (&$errorMessage) {
42237 if ($errorMessage) {
42238 $errorMessage .= "\n";
42239 }
42240 $errorMessage .= preg_replace('{^file_put_contents\(.*?\): }', '', $msg);
42241 });
42242 $result = (bool) file_put_contents($fileName, $result);
42243 restore_error_handler();
42244 if (false === $result) {
42245 throw new TransportException('The "'.$this->fileUrl.'" file could not be written to '.$fileName.': '.$errorMessage);
42246 }
42247 }
42248
42249
42250  if (false === $result && false !== strpos($errorMessage, 'Peer certificate') && PHP_VERSION_ID < 50600) {
42251
42252  
42253  
42254  
42255  
42256  
42257  
42258  
42259  
42260  
42261  
42262  
42263  
42264  
42265  
42266  
42267  if (CaBundle::isOpensslParseSafe()) {
42268 $certDetails = $this->getCertificateCnAndFp($this->fileUrl, $options);
42269
42270 if ($certDetails) {
42271 $this->peerCertificateMap[$this->getUrlAuthority($this->fileUrl)] = $certDetails;
42272
42273 $this->retry = true;
42274 }
42275 } else {
42276 $this->io->writeError('');
42277 $this->io->writeError(sprintf(
42278 '<error>Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.</error>',
42279 PHP_VERSION
42280 ));
42281 }
42282 }
42283
42284 if ($this->retry) {
42285 $this->retry = false;
42286
42287 $result = $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
42288
42289 if ($this->storeAuth && $this->config) {
42290 $authHelper = new AuthHelper($this->io, $this->config);
42291 $authHelper->storeAuth($this->originUrl, $this->storeAuth);
42292 $this->storeAuth = false;
42293 }
42294
42295 return $result;
42296 }
42297
42298 if (false === $result) {
42299 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded: '.$errorMessage, $errorCode);
42300 if (!empty($http_response_header[0])) {
42301 $e->setHeaders($http_response_header);
42302 }
42303
42304 if (!$this->degradedMode && false !== strpos($e->getMessage(), 'Operation timed out')) {
42305 $this->degradedMode = true;
42306 $this->io->writeError('');
42307 $this->io->writeError(array(
42308 '<error>'.$e->getMessage().'</error>',
42309 '<error>Retrying with degraded mode, check https://getcomposer.org/doc/articles/troubleshooting.md#degraded-mode for more info</error>',
42310 ));
42311
42312 return $this->get($this->originUrl, $this->fileUrl, $additionalOptions, $this->fileName, $this->progress);
42313 }
42314
42315 throw $e;
42316 }
42317
42318 if (!empty($http_response_header[0])) {
42319 $this->lastHeaders = $http_response_header;
42320 }
42321
42322 return $result;
42323 }
42324
42325
42326
42327
42328
42329
42330
42331
42332
42333
42334
42335
42336 protected function callbackGet($notificationCode, $severity, $message, $messageCode, $bytesTransferred, $bytesMax)
42337 {
42338 switch ($notificationCode) {
42339 case STREAM_NOTIFY_FAILURE:
42340 if (400 === $messageCode) {
42341
42342  
42343  throw new TransportException("The '" . $this->fileUrl . "' URL could not be accessed: " . $message, $messageCode);
42344 }
42345
42346  
42347
42348 case STREAM_NOTIFY_AUTH_REQUIRED:
42349 if (401 === $messageCode) {
42350
42351  if (!$this->retryAuthFailure) {
42352 break;
42353 }
42354
42355 $this->promptAuthAndRetry($messageCode);
42356 }
42357 break;
42358
42359 case STREAM_NOTIFY_AUTH_RESULT:
42360 if (403 === $messageCode) {
42361
42362  if (!$this->retryAuthFailure) {
42363 break;
42364 }
42365
42366 $this->promptAuthAndRetry($messageCode, $message);
42367 }
42368 break;
42369
42370 case STREAM_NOTIFY_FILE_SIZE_IS:
42371 $this->bytesMax = $bytesMax;
42372 break;
42373
42374 case STREAM_NOTIFY_PROGRESS:
42375 if ($this->bytesMax > 0 && $this->progress) {
42376 $progression = min(100, round($bytesTransferred / $this->bytesMax * 100));
42377
42378 if ((0 === $progression % 5) && 100 !== $progression && $progression !== $this->lastProgress) {
42379 $this->lastProgress = $progression;
42380 $this->io->overwriteError("Downloading (<comment>$progression%</comment>)", false);
42381 }
42382 }
42383 break;
42384
42385 default:
42386 break;
42387 }
42388 }
42389
42390 protected function promptAuthAndRetry($httpStatus, $reason = null)
42391 {
42392 if ($this->config && in_array($this->originUrl, $this->config->get('github-domains'), true)) {
42393 $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');
42394 $gitHubUtil = new GitHub($this->io, $this->config, null);
42395 if (!$gitHubUtil->authorizeOAuth($this->originUrl)
42396 && (!$this->io->isInteractive() || !$gitHubUtil->authorizeOAuthInteractively($this->originUrl, $message))
42397 ) {
42398 throw new TransportException('Could not authenticate against '.$this->originUrl, 401);
42399 }
42400 } elseif ($this->config && in_array($this->originUrl, $this->config->get('gitlab-domains'), true)) {
42401 $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');
42402 $gitLabUtil = new GitLab($this->io, $this->config, null);
42403
42404 if ($this->io->hasAuthentication($this->originUrl) && ($auth = $this->io->getAuthentication($this->originUrl)) && $auth['password'] === 'private-token') {
42405 throw new TransportException("Invalid credentials for '" . $this->fileUrl . "', aborting.", $httpStatus);
42406 }
42407
42408 if (!$gitLabUtil->authorizeOAuth($this->originUrl)
42409 && (!$this->io->isInteractive() || !$gitLabUtil->authorizeOAuthInteractively($this->scheme, $this->originUrl, $message))
42410 ) {
42411 throw new TransportException('Could not authenticate against '.$this->originUrl, 401);
42412 }
42413 } elseif ($this->config && $this->originUrl === 'bitbucket.org') {
42414 $askForOAuthToken = true;
42415 if ($this->io->hasAuthentication($this->originUrl)) {
42416 $auth = $this->io->getAuthentication($this->originUrl);
42417 if ($auth['username'] !== 'x-token-auth') {
42418 $bitbucketUtil = new Bitbucket($this->io, $this->config);
42419 $accessToken = $bitbucketUtil->requestToken($this->originUrl, $auth['username'], $auth['password']);
42420 if (!empty($accessToken)) {
42421 $this->io->setAuthentication($this->originUrl, 'x-token-auth', $accessToken);
42422 $askForOAuthToken = false;
42423 }
42424 } else {
42425 throw new TransportException('Could not authenticate against ' . $this->originUrl, 401);
42426 }
42427 }
42428
42429 if ($askForOAuthToken) {
42430 $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');
42431 $bitBucketUtil = new Bitbucket($this->io, $this->config);
42432 if (! $bitBucketUtil->authorizeOAuth($this->originUrl)
42433 && (! $this->io->isInteractive() || !$bitBucketUtil->authorizeOAuthInteractively($this->originUrl, $message))
42434 ) {
42435 throw new TransportException('Could not authenticate against ' . $this->originUrl, 401);
42436 }
42437 }
42438 } else {
42439
42440  if ($httpStatus === 404) {
42441 return;
42442 }
42443
42444
42445  if (!$this->io->isInteractive()) {
42446 if ($httpStatus === 401) {
42447 $message = "The '" . $this->fileUrl . "' URL required authentication.\nYou must be using the interactive console to authenticate";
42448 }
42449 if ($httpStatus === 403) {
42450 $message = "The '" . $this->fileUrl . "' URL could not be accessed: " . $reason;
42451 }
42452
42453 throw new TransportException($message, $httpStatus);
42454 }
42455
42456  if ($this->io->hasAuthentication($this->originUrl)) {
42457 throw new TransportException("Invalid credentials for '" . $this->fileUrl . "', aborting.", $httpStatus);
42458 }
42459
42460 $this->io->overwriteError('');
42461 $this->io->writeError('    Authentication required (<info>'.parse_url($this->fileUrl, PHP_URL_HOST).'</info>):');
42462 $username = $this->io->ask('      Username: ');
42463 $password = $this->io->askAndHideAnswer('      Password: ');
42464 $this->io->setAuthentication($this->originUrl, $username, $password);
42465 $this->storeAuth = $this->config->get('store-auths');
42466 }
42467
42468 $this->retry = true;
42469 throw new TransportException('RETRY');
42470 }
42471
42472 protected function getOptionsForUrl($originUrl, $additionalOptions)
42473 {
42474 $tlsOptions = array();
42475
42476
42477  if ($this->disableTls === false && PHP_VERSION_ID < 50600 && !stream_is_local($this->fileUrl)) {
42478 $host = parse_url($this->fileUrl, PHP_URL_HOST);
42479
42480 if (PHP_VERSION_ID >= 50304) {
42481
42482  
42483  $userlandFollow = true;
42484 } else {
42485
42486  
42487  
42488  
42489
42490 if ($host === 'github.com' || $host === 'api.github.com') {
42491 $host = '*.github.com';
42492 }
42493 }
42494
42495 $tlsOptions['ssl']['CN_match'] = $host;
42496 $tlsOptions['ssl']['SNI_server_name'] = $host;
42497
42498 $urlAuthority = $this->getUrlAuthority($this->fileUrl);
42499
42500 if (isset($this->peerCertificateMap[$urlAuthority])) {
42501
42502  $certMap = $this->peerCertificateMap[$urlAuthority];
42503
42504 $this->io->writeError('', true, IOInterface::DEBUG);
42505 $this->io->writeError(sprintf(
42506 'Using <info>%s</info> as CN for subjectAltName enabled host <info>%s</info>',
42507 $certMap['cn'],
42508 $urlAuthority
42509 ), true, IOInterface::DEBUG);
42510
42511 $tlsOptions['ssl']['CN_match'] = $certMap['cn'];
42512 $tlsOptions['ssl']['peer_fingerprint'] = $certMap['fp'];
42513 }
42514 }
42515
42516 $headers = array();
42517
42518 if (extension_loaded('zlib')) {
42519 $headers[] = 'Accept-Encoding: gzip';
42520 }
42521
42522 $options = array_replace_recursive($this->options, $tlsOptions, $additionalOptions);
42523 if (!$this->degradedMode) {
42524
42525  
42526  $options['http']['protocol_version'] = 1.1;
42527 $headers[] = 'Connection: close';
42528 }
42529
42530 if (isset($userlandFollow)) {
42531 $options['http']['follow_location'] = 0;
42532 }
42533
42534 if ($this->io->hasAuthentication($originUrl)) {
42535 $auth = $this->io->getAuthentication($originUrl);
42536 if ('github.com' === $originUrl && 'x-oauth-basic' === $auth['password']) {
42537 $options['github-token'] = $auth['username'];
42538 } elseif ($this->config && in_array($originUrl, $this->config->get('gitlab-domains'), true)) {
42539 if ($auth['password'] === 'oauth2') {
42540 $headers[] = 'Authorization: Bearer '.$auth['username'];
42541 } elseif ($auth['password'] === 'private-token') {
42542 $headers[] = 'PRIVATE-TOKEN: '.$auth['username'];
42543 }
42544 } elseif ('bitbucket.org' === $originUrl
42545 && $this->fileUrl !== Bitbucket::OAUTH2_ACCESS_TOKEN_URL && 'x-token-auth' === $auth['username']
42546 ) {
42547 if (!$this->isPublicBitBucketDownload($this->fileUrl)) {
42548 $headers[] = 'Authorization: Bearer ' . $auth['password'];
42549 }
42550 } else {
42551 $authStr = base64_encode($auth['username'] . ':' . $auth['password']);
42552 $headers[] = 'Authorization: Basic '.$authStr;
42553 }
42554 }
42555
42556 if (isset($options['http']['header']) && !is_array($options['http']['header'])) {
42557 $options['http']['header'] = explode("\r\n", trim($options['http']['header'], "\r\n"));
42558 }
42559 foreach ($headers as $header) {
42560 $options['http']['header'][] = $header;
42561 }
42562
42563 return $options;
42564 }
42565
42566 private function handleRedirect(array $http_response_header, array $additionalOptions, $result)
42567 {
42568 if ($locationHeader = $this->findHeaderValue($http_response_header, 'location')) {
42569 if (parse_url($locationHeader, PHP_URL_SCHEME)) {
42570
42571  $targetUrl = $locationHeader;
42572 } elseif (parse_url($locationHeader, PHP_URL_HOST)) {
42573
42574  $targetUrl = $this->scheme.':'.$locationHeader;
42575 } elseif ('/' === $locationHeader[0]) {
42576
42577  $urlHost = parse_url($this->fileUrl, PHP_URL_HOST);
42578
42579
42580  $targetUrl = preg_replace('{^(.+(?://|@)'.preg_quote($urlHost).'(?::\d+)?)(?:[/\?].*)?$}', '\1'.$locationHeader, $this->fileUrl);
42581 } else {
42582
42583  
42584  $targetUrl = preg_replace('{^(.+/)[^/?]*(?:\?.*)?$}', '\1'.$locationHeader, $this->fileUrl);
42585 }
42586 }
42587
42588 if (!empty($targetUrl)) {
42589 $this->redirects++;
42590
42591 $this->io->writeError('', true, IOInterface::DEBUG);
42592 $this->io->writeError(sprintf('Following redirect (%u) %s', $this->redirects, $targetUrl), true, IOInterface::DEBUG);
42593
42594 $additionalOptions['redirects'] = $this->redirects;
42595
42596 return $this->get($this->originUrl, $targetUrl, $additionalOptions, $this->fileName, $this->progress);
42597 }
42598
42599 if (!$this->retry) {
42600 $e = new TransportException('The "'.$this->fileUrl.'" file could not be downloaded, got redirect without Location ('.$http_response_header[0].')');
42601 $e->setHeaders($http_response_header);
42602 $e->setResponse($result);
42603
42604 throw $e;
42605 }
42606
42607 return false;
42608 }
42609
42610
42611
42612
42613
42614
42615 private function getTlsDefaults(array $options)
42616 {
42617 $ciphers = implode(':', array(
42618 'ECDHE-RSA-AES128-GCM-SHA256',
42619 'ECDHE-ECDSA-AES128-GCM-SHA256',
42620 'ECDHE-RSA-AES256-GCM-SHA384',
42621 'ECDHE-ECDSA-AES256-GCM-SHA384',
42622 'DHE-RSA-AES128-GCM-SHA256',
42623 'DHE-DSS-AES128-GCM-SHA256',
42624 'kEDH+AESGCM',
42625 'ECDHE-RSA-AES128-SHA256',
42626 'ECDHE-ECDSA-AES128-SHA256',
42627 'ECDHE-RSA-AES128-SHA',
42628 'ECDHE-ECDSA-AES128-SHA',
42629 'ECDHE-RSA-AES256-SHA384',
42630 'ECDHE-ECDSA-AES256-SHA384',
42631 'ECDHE-RSA-AES256-SHA',
42632 'ECDHE-ECDSA-AES256-SHA',
42633 'DHE-RSA-AES128-SHA256',
42634 'DHE-RSA-AES128-SHA',
42635 'DHE-DSS-AES128-SHA256',
42636 'DHE-RSA-AES256-SHA256',
42637 'DHE-DSS-AES256-SHA',
42638 'DHE-RSA-AES256-SHA',
42639 'AES128-GCM-SHA256',
42640 'AES256-GCM-SHA384',
42641 'AES128-SHA256',
42642 'AES256-SHA256',
42643 'AES128-SHA',
42644 'AES256-SHA',
42645 'AES',
42646 'CAMELLIA',
42647 'DES-CBC3-SHA',
42648 '!aNULL',
42649 '!eNULL',
42650 '!EXPORT',
42651 '!DES',
42652 '!RC4',
42653 '!MD5',
42654 '!PSK',
42655 '!aECDH',
42656 '!EDH-DSS-DES-CBC3-SHA',
42657 '!EDH-RSA-DES-CBC3-SHA',
42658 '!KRB5-DES-CBC3-SHA',
42659 ));
42660
42661
42662
42663
42664
42665
42666
42667 $defaults = array(
42668 'ssl' => array(
42669 'ciphers' => $ciphers,
42670 'verify_peer' => true,
42671 'verify_depth' => 7,
42672 'SNI_enabled' => true,
42673 'capture_peer_cert' => true,
42674 ),
42675 );
42676
42677 if (isset($options['ssl'])) {
42678 $defaults['ssl'] = array_replace_recursive($defaults['ssl'], $options['ssl']);
42679 }
42680
42681 $caBundleLogger = $this->io instanceof LoggerInterface ? $this->io : null;
42682
42683
42684
42685
42686
42687 if (!isset($defaults['ssl']['cafile']) && !isset($defaults['ssl']['capath'])) {
42688 $result = CaBundle::getSystemCaRootBundlePath($caBundleLogger);
42689
42690 if (preg_match('{^phar://}', $result)) {
42691 $hash = hash_file('sha256', $result);
42692 $targetPath = rtrim(sys_get_temp_dir(), '\\/') . '/composer-cacert-' . $hash . '.pem';
42693
42694 if (!file_exists($targetPath) || $hash !== hash_file('sha256', $targetPath)) {
42695 $this->streamCopy($result, $targetPath);
42696 chmod($targetPath, 0666);
42697 }
42698
42699 $defaults['ssl']['cafile'] = $targetPath;
42700 } elseif (is_dir($result)) {
42701 $defaults['ssl']['capath'] = $result;
42702 } else {
42703 $defaults['ssl']['cafile'] = $result;
42704 }
42705 }
42706
42707 if (isset($defaults['ssl']['cafile']) && (!is_readable($defaults['ssl']['cafile']) || !CaBundle::validateCaFile($defaults['ssl']['cafile'], $caBundleLogger))) {
42708 throw new TransportException('The configured cafile was not valid or could not be read.');
42709 }
42710
42711 if (isset($defaults['ssl']['capath']) && (!is_dir($defaults['ssl']['capath']) || !is_readable($defaults['ssl']['capath']))) {
42712 throw new TransportException('The configured capath was not valid or could not be read.');
42713 }
42714
42715
42716
42717
42718 if (PHP_VERSION_ID >= 50413) {
42719 $defaults['ssl']['disable_compression'] = true;
42720 }
42721
42722 return $defaults;
42723 }
42724
42725
42726
42727
42728
42729
42730
42731 private function streamCopy($source, $target)
42732 {
42733 $source = fopen($source, 'r');
42734 $target = fopen($target, 'w+');
42735
42736 stream_copy_to_stream($source, $target);
42737 fclose($source);
42738 fclose($target);
42739
42740 unset($source, $target);
42741 }
42742
42743
42744
42745
42746
42747
42748 private function getCertificateCnAndFp($url, $options)
42749 {
42750 if (PHP_VERSION_ID >= 50600) {
42751 throw new \BadMethodCallException(sprintf(
42752 '%s must not be used on PHP >= 5.6',
42753 __METHOD__
42754 ));
42755 }
42756
42757 $context = StreamContextFactory::getContext($url, $options, array('options' => array(
42758 'ssl' => array(
42759 'capture_peer_cert' => true,
42760 'verify_peer' => false, 
42761  ), ),
42762 ));
42763
42764
42765  
42766  if (false === $handle = @fopen($url, 'rb', false, $context)) {
42767 return;
42768 }
42769
42770
42771  fclose($handle);
42772 $handle = null;
42773
42774 $params = stream_context_get_params($context);
42775
42776 if (!empty($params['options']['ssl']['peer_certificate'])) {
42777 $peerCertificate = $params['options']['ssl']['peer_certificate'];
42778
42779 if (TlsHelper::checkCertificateHost($peerCertificate, parse_url($url, PHP_URL_HOST), $commonName)) {
42780 return array(
42781 'cn' => $commonName,
42782 'fp' => TlsHelper::getCertificateFingerprint($peerCertificate),
42783 );
42784 }
42785 }
42786 }
42787
42788 private function getUrlAuthority($url)
42789 {
42790 $defaultPorts = array(
42791 'ftp' => 21,
42792 'http' => 80,
42793 'https' => 443,
42794 'ssh2.sftp' => 22,
42795 'ssh2.scp' => 22,
42796 );
42797
42798 $scheme = parse_url($url, PHP_URL_SCHEME);
42799
42800 if (!isset($defaultPorts[$scheme])) {
42801 throw new \InvalidArgumentException(sprintf(
42802 'Could not get default port for unknown scheme: %s',
42803 $scheme
42804 ));
42805 }
42806
42807 $defaultPort = $defaultPorts[$scheme];
42808 $port = parse_url($url, PHP_URL_PORT) ?: $defaultPort;
42809
42810 return parse_url($url, PHP_URL_HOST).':'.$port;
42811 }
42812
42813
42814
42815
42816
42817
42818
42819
42820 private function isPublicBitBucketDownload($urlToBitBucketFile)
42821 {
42822 $domain = parse_url($urlToBitBucketFile, PHP_URL_HOST);
42823 if (strpos($domain, 'bitbucket.org') === false) {
42824
42825  
42826  return true;
42827 }
42828
42829 $path = parse_url($urlToBitBucketFile, PHP_URL_PATH);
42830
42831
42832  
42833  $pathParts = explode('/', $path);
42834 if (count($pathParts) >= 4 && $pathParts[3] == 'downloads') {
42835 return true;
42836 }
42837
42838 return false;
42839 }
42840 }
42841 <?php
42842
42843
42844
42845
42846
42847
42848
42849
42850
42851
42852
42853 namespace Composer\Util;
42854
42855
42856
42857
42858
42859
42860 class Silencer
42861 {
42862
42863
42864
42865 private static $stack = array();
42866
42867
42868
42869
42870
42871
42872
42873 public static function suppress($mask = null)
42874 {
42875 if (!isset($mask)) {
42876 $mask = E_WARNING | E_NOTICE | E_USER_WARNING | E_USER_NOTICE | E_DEPRECATED | E_USER_DEPRECATED | E_STRICT;
42877 }
42878 $old = error_reporting();
42879 array_push(self::$stack, $old);
42880 error_reporting($old & ~$mask);
42881
42882 return $old;
42883 }
42884
42885
42886
42887
42888 public static function restore()
42889 {
42890 if (!empty(self::$stack)) {
42891 error_reporting(array_pop(self::$stack));
42892 }
42893 }
42894
42895
42896
42897
42898
42899
42900
42901
42902
42903
42904 public static function call($callable )
42905 {
42906 try {
42907 self::suppress();
42908 $result = call_user_func_array($callable, array_slice(func_get_args(), 1));
42909 self::restore();
42910
42911 return $result;
42912 } catch (\Exception $e) {
42913
42914  self::restore();
42915 throw $e;
42916 }
42917 }
42918 }
42919 <?php
42920
42921
42922
42923
42924
42925
42926
42927
42928
42929
42930
42931 namespace Composer\Util;
42932
42933 use Composer\Spdx\SpdxLicenses;
42934
42935 trigger_error('The ' . __NAMESPACE__ . '\SpdxLicense class is deprecated, use Composer\Spdx\SpdxLicenses instead.', E_USER_DEPRECATED);
42936
42937
42938
42939
42940 class SpdxLicense extends SpdxLicenses
42941 {
42942 }
42943 <?php
42944
42945
42946
42947
42948
42949
42950
42951
42952
42953
42954
42955 namespace Composer\Util;
42956
42957 use Composer\Composer;
42958
42959
42960
42961
42962
42963
42964
42965 final class StreamContextFactory
42966 {
42967
42968
42969
42970
42971
42972
42973
42974
42975
42976 public static function getContext($url, array $defaultOptions = array(), array $defaultParams = array())
42977 {
42978 $options = array('http' => array(
42979
42980  'follow_location' => 1,
42981 'max_redirects' => 20,
42982 ));
42983
42984
42985  if (PHP_SAPI === 'cli' && (!empty($_SERVER['HTTP_PROXY']) || !empty($_SERVER['http_proxy']))) {
42986 $proxy = parse_url(!empty($_SERVER['http_proxy']) ? $_SERVER['http_proxy'] : $_SERVER['HTTP_PROXY']);
42987 }
42988
42989
42990  if (!empty($_SERVER['CGI_HTTP_PROXY'])) {
42991 $proxy = parse_url($_SERVER['CGI_HTTP_PROXY']);
42992 }
42993
42994
42995  if (preg_match('{^https://}i', $url) && (!empty($_SERVER['HTTPS_PROXY']) || !empty($_SERVER['https_proxy']))) {
42996 $proxy = parse_url(!empty($_SERVER['https_proxy']) ? $_SERVER['https_proxy'] : $_SERVER['HTTPS_PROXY']);
42997 }
42998
42999
43000  if (!empty($_SERVER['no_proxy']) && parse_url($url, PHP_URL_HOST)) {
43001 $pattern = new NoProxyPattern($_SERVER['no_proxy']);
43002 if ($pattern->test($url)) {
43003 unset($proxy);
43004 }
43005 }
43006
43007 if (!empty($proxy)) {
43008 $proxyURL = isset($proxy['scheme']) ? $proxy['scheme'] . '://' : '';
43009 $proxyURL .= isset($proxy['host']) ? $proxy['host'] : '';
43010
43011 if (isset($proxy['port'])) {
43012 $proxyURL .= ":" . $proxy['port'];
43013 } elseif ('http://' == substr($proxyURL, 0, 7)) {
43014 $proxyURL .= ":80";
43015 } elseif ('https://' == substr($proxyURL, 0, 8)) {
43016 $proxyURL .= ":443";
43017 }
43018
43019
43020  $proxyURL = str_replace(array('http://', 'https://'), array('tcp://', 'ssl://'), $proxyURL);
43021
43022 if (0 === strpos($proxyURL, 'ssl:') && !extension_loaded('openssl')) {
43023 throw new \RuntimeException('You must enable the openssl extension to use a proxy over https');
43024 }
43025
43026 $options['http']['proxy'] = $proxyURL;
43027
43028
43029  switch (parse_url($url, PHP_URL_SCHEME)) {
43030 case 'http': 
43031  $reqFullUriEnv = getenv('HTTP_PROXY_REQUEST_FULLURI');
43032 if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
43033 $options['http']['request_fulluri'] = true;
43034 }
43035 break;
43036 case 'https': 
43037  $reqFullUriEnv = getenv('HTTPS_PROXY_REQUEST_FULLURI');
43038 if ($reqFullUriEnv === false || $reqFullUriEnv === '' || (strtolower($reqFullUriEnv) !== 'false' && (bool) $reqFullUriEnv)) {
43039 $options['http']['request_fulluri'] = true;
43040 }
43041 break;
43042 }
43043
43044
43045  if ('https' === parse_url($url, PHP_URL_SCHEME)) {
43046 $options['ssl']['SNI_enabled'] = true;
43047 if (PHP_VERSION_ID < 50600) {
43048 $options['ssl']['SNI_server_name'] = parse_url($url, PHP_URL_HOST);
43049 }
43050 }
43051
43052
43053  if (isset($proxy['user'])) {
43054 $auth = urldecode($proxy['user']);
43055 if (isset($proxy['pass'])) {
43056 $auth .= ':' . urldecode($proxy['pass']);
43057 }
43058 $auth = base64_encode($auth);
43059
43060
43061  if (isset($defaultOptions['http']['header'])) {
43062 if (is_string($defaultOptions['http']['header'])) {
43063 $defaultOptions['http']['header'] = array($defaultOptions['http']['header']);
43064 }
43065 $defaultOptions['http']['header'][] = "Proxy-Authorization: Basic {$auth}";
43066 } else {
43067 $options['http']['header'] = array("Proxy-Authorization: Basic {$auth}");
43068 }
43069 }
43070 }
43071
43072 $options = array_replace_recursive($options, $defaultOptions);
43073
43074 if (isset($options['http']['header'])) {
43075 $options['http']['header'] = self::fixHttpHeaderField($options['http']['header']);
43076 }
43077
43078 if (defined('HHVM_VERSION')) {
43079 $phpVersion = 'HHVM ' . HHVM_VERSION;
43080 } else {
43081 $phpVersion = 'PHP ' . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION;
43082 }
43083
43084 if (!isset($options['http']['header']) || false === strpos(strtolower(implode('', $options['http']['header'])), 'user-agent')) {
43085 $options['http']['header'][] = sprintf(
43086 'User-Agent: Composer/%s (%s; %s; %s%s)',
43087 Composer::VERSION === '@package_version@' ? 'source' : Composer::VERSION,
43088 function_exists('php_uname') ? php_uname('s') : 'Unknown',
43089 function_exists('php_uname') ? php_uname('r') : 'Unknown',
43090 $phpVersion,
43091 getenv('CI') ? '; CI' : ''
43092 );
43093 }
43094
43095 return stream_context_create($options, $defaultParams);
43096 }
43097
43098
43099
43100
43101
43102
43103
43104
43105
43106
43107
43108 private static function fixHttpHeaderField($header)
43109 {
43110 if (!is_array($header)) {
43111 $header = explode("\r\n", $header);
43112 }
43113 uasort($header, function ($el) {
43114 return preg_match('{^content-type}i', $el) ? 1 : -1;
43115 });
43116
43117 return $header;
43118 }
43119 }
43120 <?php
43121
43122
43123
43124
43125
43126
43127
43128
43129
43130
43131
43132 namespace Composer\Util;
43133
43134 use Composer\Config;
43135 use Composer\IO\IOInterface;
43136
43137
43138
43139
43140
43141 class Svn
43142 {
43143 const MAX_QTY_AUTH_TRIES = 5;
43144
43145
43146
43147
43148 protected $credentials;
43149
43150
43151
43152
43153 protected $hasAuth;
43154
43155
43156
43157
43158 protected $io;
43159
43160
43161
43162
43163 protected $url;
43164
43165
43166
43167
43168 protected $cacheCredentials = true;
43169
43170
43171
43172
43173 protected $process;
43174
43175
43176
43177
43178 protected $qtyAuthTries = 0;
43179
43180
43181
43182
43183 protected $config;
43184
43185
43186
43187
43188
43189
43190
43191 public function __construct($url, IOInterface $io, Config $config, ProcessExecutor $process = null)
43192 {
43193 $this->url = $url;
43194 $this->io = $io;
43195 $this->config = $config;
43196 $this->process = $process ?: new ProcessExecutor;
43197 }
43198
43199 public static function cleanEnv()
43200 {
43201
43202  putenv("DYLD_LIBRARY_PATH");
43203 unset($_SERVER['DYLD_LIBRARY_PATH']);
43204 }
43205
43206
43207
43208
43209
43210
43211
43212
43213
43214
43215
43216
43217
43218
43219 public function execute($command, $url, $cwd = null, $path = null, $verbose = false)
43220 {
43221
43222  $this->config->prohibitUrlByConfig($url, $this->io);
43223
43224 $svnCommand = $this->getCommand($command, $url, $path);
43225 $output = null;
43226 $io = $this->io;
43227 $handler = function ($type, $buffer) use (&$output, $io, $verbose) {
43228 if ($type !== 'out') {
43229 return;
43230 }
43231 if ('Redirecting to URL ' === substr($buffer, 0, 19)) {
43232 return;
43233 }
43234 $output .= $buffer;
43235 if ($verbose) {
43236 $io->writeError($buffer, false);
43237 }
43238 };
43239 $status = $this->process->execute($svnCommand, $handler, $cwd);
43240 if (0 === $status) {
43241 return $output;
43242 }
43243
43244 $errorOutput = $this->process->getErrorOutput();
43245 $fullOutput = implode("\n", array($output, $errorOutput));
43246
43247
43248  if (false === stripos($fullOutput, 'Could not authenticate to server:')
43249 && false === stripos($fullOutput, 'authorization failed')
43250 && false === stripos($fullOutput, 'svn: E170001:')
43251 && false === stripos($fullOutput, 'svn: E215004:')) {
43252 throw new \RuntimeException($fullOutput);
43253 }
43254
43255 if (!$this->hasAuth()) {
43256 $this->doAuthDance();
43257 }
43258
43259
43260  if ($this->qtyAuthTries++ < self::MAX_QTY_AUTH_TRIES) {
43261
43262  return $this->execute($command, $url, $cwd, $path, $verbose);
43263 }
43264
43265 throw new \RuntimeException(
43266 'wrong credentials provided ('.$fullOutput.')'
43267 );
43268 }
43269
43270
43271
43272
43273 public function setCacheCredentials($cacheCredentials)
43274 {
43275 $this->cacheCredentials = $cacheCredentials;
43276 }
43277
43278
43279
43280
43281
43282
43283
43284 protected function doAuthDance()
43285 {
43286
43287  if (!$this->io->isInteractive()) {
43288 throw new \RuntimeException(
43289 'can not ask for authentication in non interactive mode'
43290 );
43291 }
43292
43293 $this->io->writeError("The Subversion server ({$this->url}) requested credentials:");
43294
43295 $this->hasAuth = true;
43296 $this->credentials['username'] = $this->io->ask("Username: ");
43297 $this->credentials['password'] = $this->io->askAndHideAnswer("Password: ");
43298
43299 $this->cacheCredentials = $this->io->askConfirmation("Should Subversion cache these credentials? (yes/no) ", true);
43300
43301 return $this;
43302 }
43303
43304
43305
43306
43307
43308
43309
43310
43311
43312
43313 protected function getCommand($cmd, $url, $path = null)
43314 {
43315 $cmd = sprintf('%s %s%s %s',
43316 $cmd,
43317 '--non-interactive ',
43318 $this->getCredentialString(),
43319 ProcessExecutor::escape($url)
43320 );
43321
43322 if ($path) {
43323 $cmd .= ' ' . ProcessExecutor::escape($path);
43324 }
43325
43326 return $cmd;
43327 }
43328
43329
43330
43331
43332
43333
43334
43335
43336 protected function getCredentialString()
43337 {
43338 if (!$this->hasAuth()) {
43339 return '';
43340 }
43341
43342 return sprintf(
43343 ' %s--username %s --password %s ',
43344 $this->getAuthCache(),
43345 ProcessExecutor::escape($this->getUsername()),
43346 ProcessExecutor::escape($this->getPassword())
43347 );
43348 }
43349
43350
43351
43352
43353
43354
43355
43356 protected function getPassword()
43357 {
43358 if ($this->credentials === null) {
43359 throw new \LogicException("No svn auth detected.");
43360 }
43361
43362 return isset($this->credentials['password']) ? $this->credentials['password'] : '';
43363 }
43364
43365
43366
43367
43368
43369
43370
43371 protected function getUsername()
43372 {
43373 if ($this->credentials === null) {
43374 throw new \LogicException("No svn auth detected.");
43375 }
43376
43377 return $this->credentials['username'];
43378 }
43379
43380
43381
43382
43383
43384
43385 protected function hasAuth()
43386 {
43387 if (null !== $this->hasAuth) {
43388 return $this->hasAuth;
43389 }
43390
43391 if (false === $this->createAuthFromConfig()) {
43392 $this->createAuthFromUrl();
43393 }
43394
43395 return $this->hasAuth;
43396 }
43397
43398
43399
43400
43401
43402
43403 protected function getAuthCache()
43404 {
43405 return $this->cacheCredentials ? '' : '--no-auth-cache ';
43406 }
43407
43408
43409
43410
43411
43412
43413 private function createAuthFromConfig()
43414 {
43415 if (!$this->config->has('http-basic')) {
43416 return $this->hasAuth = false;
43417 }
43418
43419 $authConfig = $this->config->get('http-basic');
43420
43421 $host = parse_url($this->url, PHP_URL_HOST);
43422 if (isset($authConfig[$host])) {
43423 $this->credentials['username'] = $authConfig[$host]['username'];
43424 $this->credentials['password'] = $authConfig[$host]['password'];
43425
43426 return $this->hasAuth = true;
43427 }
43428
43429 return $this->hasAuth = false;
43430 }
43431
43432
43433
43434
43435
43436
43437 private function createAuthFromUrl()
43438 {
43439 $uri = parse_url($this->url);
43440 if (empty($uri['user'])) {
43441 return $this->hasAuth = false;
43442 }
43443
43444 $this->credentials['username'] = $uri['user'];
43445 if (!empty($uri['pass'])) {
43446 $this->credentials['password'] = $uri['pass'];
43447 }
43448
43449 return $this->hasAuth = true;
43450 }
43451 }
43452 <?php
43453
43454
43455
43456
43457
43458
43459
43460
43461
43462
43463
43464 namespace Composer\Util;
43465
43466 use Composer\CaBundle\CaBundle;
43467
43468
43469
43470
43471 final class TlsHelper
43472 {
43473 private static $useOpensslParse;
43474
43475
43476
43477
43478
43479
43480
43481
43482
43483
43484 public static function checkCertificateHost($certificate, $hostname, &$cn = null)
43485 {
43486 $names = self::getCertificateNames($certificate);
43487
43488 if (empty($names)) {
43489 return false;
43490 }
43491
43492 $combinedNames = array_merge($names['san'], array($names['cn']));
43493 $hostname = strtolower($hostname);
43494
43495 foreach ($combinedNames as $certName) {
43496 $matcher = self::certNameMatcher($certName);
43497
43498 if ($matcher && $matcher($hostname)) {
43499 $cn = $names['cn'];
43500
43501 return true;
43502 }
43503 }
43504
43505 return false;
43506 }
43507
43508
43509
43510
43511
43512
43513
43514
43515 public static function getCertificateNames($certificate)
43516 {
43517 if (is_array($certificate)) {
43518 $info = $certificate;
43519 } elseif (CaBundle::isOpensslParseSafe()) {
43520 $info = openssl_x509_parse($certificate, false);
43521 }
43522
43523 if (!isset($info['subject']['commonName'])) {
43524 return null;
43525 }
43526
43527 $commonName = strtolower($info['subject']['commonName']);
43528 $subjectAltNames = array();
43529
43530 if (isset($info['extensions']['subjectAltName'])) {
43531 $subjectAltNames = preg_split('{\s*,\s*}', $info['extensions']['subjectAltName']);
43532 $subjectAltNames = array_filter(array_map(function ($name) {
43533 if (0 === strpos($name, 'DNS:')) {
43534 return strtolower(ltrim(substr($name, 4)));
43535 }
43536
43537 return null;
43538 }, $subjectAltNames));
43539 $subjectAltNames = array_values($subjectAltNames);
43540 }
43541
43542 return array(
43543 'cn' => $commonName,
43544 'san' => $subjectAltNames,
43545 );
43546 }
43547
43548
43549
43550
43551
43552
43553
43554
43555
43556
43557
43558
43559
43560
43561
43562
43563
43564
43565
43566
43567
43568
43569
43570
43571
43572
43573
43574
43575
43576
43577
43578
43579
43580
43581
43582
43583
43584
43585
43586
43587 public static function getCertificateFingerprint($certificate)
43588 {
43589 $pubkeydetails = openssl_pkey_get_details(openssl_get_publickey($certificate));
43590 $pubkeypem = $pubkeydetails['key'];
43591
43592  $start = '-----BEGIN PUBLIC KEY-----';
43593 $end = '-----END PUBLIC KEY-----';
43594 $pemtrim = substr($pubkeypem, (strpos($pubkeypem, $start) + strlen($start)), (strlen($pubkeypem) - strpos($pubkeypem, $end)) * (-1));
43595 $der = base64_decode($pemtrim);
43596
43597 return sha1($der);
43598 }
43599
43600
43601
43602
43603
43604
43605
43606
43607
43608 public static function isOpensslParseSafe()
43609 {
43610 return CaBundle::isOpensslParseSafe();
43611 }
43612
43613
43614
43615
43616
43617
43618
43619
43620 private static function certNameMatcher($certName)
43621 {
43622 $wildcards = substr_count($certName, '*');
43623
43624 if (0 === $wildcards) {
43625
43626  return function ($hostname) use ($certName) {
43627 return $hostname === $certName;
43628 };
43629 }
43630
43631 if (1 === $wildcards) {
43632 $components = explode('.', $certName);
43633
43634 if (3 > count($components)) {
43635
43636  return;
43637 }
43638
43639 $firstComponent = $components[0];
43640
43641
43642  if ('*' !== $firstComponent[strlen($firstComponent) - 1]) {
43643 return;
43644 }
43645
43646 $wildcardRegex = preg_quote($certName);
43647 $wildcardRegex = str_replace('\\*', '[a-z0-9-]+', $wildcardRegex);
43648 $wildcardRegex = "{^{$wildcardRegex}$}";
43649
43650 return function ($hostname) use ($wildcardRegex) {
43651 return 1 === preg_match($wildcardRegex, $hostname);
43652 };
43653 }
43654 }
43655 }
43656 <?php
43657
43658
43659
43660
43661
43662
43663
43664
43665
43666
43667
43668 namespace Composer;
43669
43670 use Composer\Util\IniHelper;
43671 use Symfony\Component\Console\Output\OutputInterface;
43672
43673
43674
43675
43676 class XdebugHandler
43677 {
43678 const ENV_ALLOW = 'COMPOSER_ALLOW_XDEBUG';
43679 const ENV_VERSION = 'COMPOSER_XDEBUG_VERSION';
43680 const RESTART_ID = 'internal';
43681
43682 private $output;
43683 private $loaded;
43684 private $envScanDir;
43685 private $version;
43686 private $tmpIni;
43687
43688
43689
43690
43691 public function __construct(OutputInterface $output)
43692 {
43693 $this->output = $output;
43694 $this->loaded = extension_loaded('xdebug');
43695 $this->envScanDir = getenv('PHP_INI_SCAN_DIR');
43696
43697 if ($this->loaded) {
43698 $ext = new \ReflectionExtension('xdebug');
43699 $this->version = strval($ext->getVersion());
43700 }
43701 }
43702
43703
43704
43705
43706
43707
43708
43709
43710
43711
43712
43713
43714
43715
43716 public function check()
43717 {
43718 $args = explode('|', strval(getenv(self::ENV_ALLOW)), 2);
43719
43720 if ($this->needsRestart($args[0])) {
43721 if ($this->prepareRestart()) {
43722 $command = $this->getCommand();
43723 $this->restart($command);
43724 }
43725
43726 return;
43727 }
43728
43729
43730  if (self::RESTART_ID === $args[0]) {
43731 putenv(self::ENV_ALLOW);
43732
43733 if (false !== $this->envScanDir) {
43734
43735  if (isset($args[1])) {
43736 putenv('PHP_INI_SCAN_DIR='.$args[1]);
43737 } else {
43738 putenv('PHP_INI_SCAN_DIR');
43739 }
43740 }
43741
43742
43743  if ($this->loaded) {
43744 putenv(self::ENV_VERSION);
43745 }
43746 }
43747 }
43748
43749
43750
43751
43752
43753
43754 protected function restart($command)
43755 {
43756 passthru($command, $exitCode);
43757
43758 if (!empty($this->tmpIni)) {
43759 @unlink($this->tmpIni);
43760 }
43761
43762 exit($exitCode);
43763 }
43764
43765
43766
43767
43768
43769
43770
43771
43772 private function needsRestart($allow)
43773 {
43774 if (PHP_SAPI !== 'cli' || !defined('PHP_BINARY')) {
43775 return false;
43776 }
43777
43778 return empty($allow) && $this->loaded;
43779 }
43780
43781
43782
43783
43784
43785
43786
43787
43788
43789
43790
43791 private function prepareRestart()
43792 {
43793 $this->tmpIni = '';
43794 $iniPaths = IniHelper::getAll();
43795 $additional = count($iniPaths) > 1;
43796
43797 if (empty($iniPaths[0])) {
43798
43799  array_shift($iniPaths);
43800 }
43801
43802 if ($this->writeTmpIni($iniPaths)) {
43803 return $this->setEnvironment($additional, $iniPaths);
43804 }
43805
43806 return false;
43807 }
43808
43809
43810
43811
43812
43813
43814
43815
43816
43817
43818 private function writeTmpIni(array $iniFiles)
43819 {
43820 if (!$this->tmpIni = tempnam(sys_get_temp_dir(), '')) {
43821 return false;
43822 }
43823
43824 $content = '';
43825 $regex = '/^\s*(zend_extension\s*=.*xdebug.*)$/mi';
43826
43827 foreach ($iniFiles as $file) {
43828 $data = preg_replace($regex, ';$1', file_get_contents($file));
43829 $content .= $data.PHP_EOL;
43830 }
43831
43832 $content .= 'allow_url_fopen='.ini_get('allow_url_fopen').PHP_EOL;
43833 $content .= 'disable_functions="'.ini_get('disable_functions').'"'.PHP_EOL;
43834 $content .= 'memory_limit='.ini_get('memory_limit').PHP_EOL;
43835
43836 if (defined('PHP_WINDOWS_VERSION_BUILD')) {
43837
43838  $content .= 'opcache.enable_cli=0'.PHP_EOL;
43839 }
43840
43841 return @file_put_contents($this->tmpIni, $content);
43842 }
43843
43844
43845
43846
43847
43848
43849 private function getCommand()
43850 {
43851 $phpArgs = array(PHP_BINARY, '-c', $this->tmpIni);
43852 $params = array_merge($phpArgs, $this->getScriptArgs($_SERVER['argv']));
43853
43854 return implode(' ', array_map(array($this, 'escape'), $params));
43855 }
43856
43857
43858
43859
43860
43861
43862
43863
43864
43865 private function setEnvironment($additional, array $iniPaths)
43866 {
43867
43868  if ($additional && !putenv('PHP_INI_SCAN_DIR=')) {
43869 return false;
43870 }
43871
43872
43873  if (!putenv(IniHelper::ENV_ORIGINAL.'='.implode(PATH_SEPARATOR, $iniPaths))) {
43874 return false;
43875 }
43876
43877
43878  if (!putenv(self::ENV_VERSION.'='.$this->version)) {
43879 return false;
43880 }
43881
43882
43883  $args = array(self::RESTART_ID);
43884
43885 if (false !== $this->envScanDir) {
43886
43887  $args[] = $this->envScanDir;
43888 }
43889
43890 return putenv(self::ENV_ALLOW.'='.implode('|', $args));
43891 }
43892
43893
43894
43895
43896
43897
43898
43899
43900
43901
43902
43903 private function getScriptArgs(array $args)
43904 {
43905 if (in_array('--no-ansi', $args) || in_array('--ansi', $args)) {
43906 return $args;
43907 }
43908
43909 if ($this->output->isDecorated()) {
43910 $offset = count($args) > 1 ? 2 : 1;
43911 array_splice($args, $offset, 0, '--ansi');
43912 }
43913
43914 return $args;
43915 }
43916
43917
43918
43919
43920
43921
43922
43923
43924
43925
43926
43927
43928 private function escape($arg, $meta = true)
43929 {
43930 if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
43931 return escapeshellarg($arg);
43932 }
43933
43934 $quote = strpbrk($arg, " \t") !== false || $arg === '';
43935 $arg = preg_replace('/(\\\\*)"/', '$1$1\\"', $arg, -1, $dquotes);
43936
43937 if ($meta) {
43938 $meta = $dquotes || preg_match('/%[^%]+%/', $arg);
43939
43940 if (!$meta && !$quote) {
43941 $quote = strpbrk($arg, '^&|<>()') !== false;
43942 }
43943 }
43944
43945 if ($quote) {
43946 $arg = preg_replace('/(\\\\*)$/', '$1$1', $arg);
43947 $arg = '"'.$arg.'"';
43948 }
43949
43950 if ($meta) {
43951 $arg = preg_replace('/(["^&|<>()%])/', '^$1', $arg);
43952 }
43953
43954 return $arg;
43955 }
43956 }
43957 <?php
43958
43959
43960
43961
43962
43963
43964
43965
43966
43967
43968
43969 function includeIfExists($file)
43970 {
43971 return file_exists($file) ? include $file : false;
43972 }
43973
43974 if ((!$loader = includeIfExists(__DIR__.'/../vendor/autoload.php')) && (!$loader = includeIfExists(__DIR__.'/../../../autoload.php'))) {
43975 echo 'You must set up the project dependencies using `composer install`'.PHP_EOL.
43976 'See https://getcomposer.org/download/ for instructions on installing Composer'.PHP_EOL;
43977 exit(1);
43978 }
43979
43980 return $loader;
43981 <?php
43982
43983 /*
43984  * This file is part of Composer.
43985  *
43986  * (c) Nils Adermann <naderman@naderman.de>
43987  *     Jordi Boggiano <j.boggiano@seld.be>
43988  *
43989  * For the full copyright and license information, please view the LICENSE
43990  * file that was distributed with this source code.
43991  */
43992
43993 namespace Composer\Autoload;
43994
43995 /**
43996  * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
43997  *
43998  *     $loader = new \Composer\Autoload\ClassLoader();
43999  *
44000  *     // register classes with namespaces
44001  *     $loader->add('Symfony\Component', __DIR__.'/component');
44002  *     $loader->add('Symfony',           __DIR__.'/framework');
44003  *
44004  *     // activate the autoloader
44005  *     $loader->register();
44006  *
44007  *     // to enable searching the include path (eg. for PEAR packages)
44008  *     $loader->setUseIncludePath(true);
44009  *
44010  * In this example, if you try to use a class in the Symfony\Component
44011  * namespace or one of its children (Symfony\Component\Console for instance),
44012  * the autoloader will first look for the class under the component/
44013  * directory, and it will then fallback to the framework/ directory if not
44014  * found before giving up.
44015  *
44016  * This class is loosely based on the Symfony UniversalClassLoader.
44017  *
44018  * @author Fabien Potencier <fabien@symfony.com>
44019  * @author Jordi Boggiano <j.boggiano@seld.be>
44020  * @see    http://www.php-fig.org/psr/psr-0/
44021  * @see    http://www.php-fig.org/psr/psr-4/
44022  */
44023 class ClassLoader
44024 {
44025     // PSR-4
44026     private $prefixLengthsPsr4 = array();
44027     private $prefixDirsPsr4 = array();
44028     private $fallbackDirsPsr4 = array();
44029
44030     // PSR-0
44031     private $prefixesPsr0 = array();
44032     private $fallbackDirsPsr0 = array();
44033
44034     private $useIncludePath = false;
44035     private $classMap = array();
44036     private $classMapAuthoritative = false;
44037     private $missingClasses = array();
44038     private $apcuPrefix;
44039
44040     public function getPrefixes()
44041     {
44042         if (!empty($this->prefixesPsr0)) {
44043             return call_user_func_array('array_merge', $this->prefixesPsr0);
44044         }
44045
44046         return array();
44047     }
44048
44049     public function getPrefixesPsr4()
44050     {
44051         return $this->prefixDirsPsr4;
44052     }
44053
44054     public function getFallbackDirs()
44055     {
44056         return $this->fallbackDirsPsr0;
44057     }
44058
44059     public function getFallbackDirsPsr4()
44060     {
44061         return $this->fallbackDirsPsr4;
44062     }
44063
44064     public function getClassMap()
44065     {
44066         return $this->classMap;
44067     }
44068
44069     /**
44070      * @param array $classMap Class to filename map
44071      */
44072     public function addClassMap(array $classMap)
44073     {
44074         if ($this->classMap) {
44075             $this->classMap = array_merge($this->classMap, $classMap);
44076         } else {
44077             $this->classMap = $classMap;
44078         }
44079     }
44080
44081     /**
44082      * Registers a set of PSR-0 directories for a given prefix, either
44083      * appending or prepending to the ones previously set for this prefix.
44084      *
44085      * @param string       $prefix  The prefix
44086      * @param array|string $paths   The PSR-0 root directories
44087      * @param bool         $prepend Whether to prepend the directories
44088      */
44089     public function add($prefix, $paths, $prepend = false)
44090     {
44091         if (!$prefix) {
44092             if ($prepend) {
44093                 $this->fallbackDirsPsr0 = array_merge(
44094                     (array) $paths,
44095                     $this->fallbackDirsPsr0
44096                 );
44097             } else {
44098                 $this->fallbackDirsPsr0 = array_merge(
44099                     $this->fallbackDirsPsr0,
44100                     (array) $paths
44101                 );
44102             }
44103
44104             return;
44105         }
44106
44107         $first = $prefix[0];
44108         if (!isset($this->prefixesPsr0[$first][$prefix])) {
44109             $this->prefixesPsr0[$first][$prefix] = (array) $paths;
44110
44111             return;
44112         }
44113         if ($prepend) {
44114             $this->prefixesPsr0[$first][$prefix] = array_merge(
44115                 (array) $paths,
44116                 $this->prefixesPsr0[$first][$prefix]
44117             );
44118         } else {
44119             $this->prefixesPsr0[$first][$prefix] = array_merge(
44120                 $this->prefixesPsr0[$first][$prefix],
44121                 (array) $paths
44122             );
44123         }
44124     }
44125
44126     /**
44127      * Registers a set of PSR-4 directories for a given namespace, either
44128      * appending or prepending to the ones previously set for this namespace.
44129      *
44130      * @param string       $prefix  The prefix/namespace, with trailing '\\'
44131      * @param array|string $paths   The PSR-4 base directories
44132      * @param bool         $prepend Whether to prepend the directories
44133      *
44134      * @throws \InvalidArgumentException
44135      */
44136     public function addPsr4($prefix, $paths, $prepend = false)
44137     {
44138         if (!$prefix) {
44139             // Register directories for the root namespace.
44140             if ($prepend) {
44141                 $this->fallbackDirsPsr4 = array_merge(
44142                     (array) $paths,
44143                     $this->fallbackDirsPsr4
44144                 );
44145             } else {
44146                 $this->fallbackDirsPsr4 = array_merge(
44147                     $this->fallbackDirsPsr4,
44148                     (array) $paths
44149                 );
44150             }
44151         } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
44152             // Register directories for a new namespace.
44153             $length = strlen($prefix);
44154             if ('\\' !== $prefix[$length - 1]) {
44155                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
44156             }
44157             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
44158             $this->prefixDirsPsr4[$prefix] = (array) $paths;
44159         } elseif ($prepend) {
44160             // Prepend directories for an already registered namespace.
44161             $this->prefixDirsPsr4[$prefix] = array_merge(
44162                 (array) $paths,
44163                 $this->prefixDirsPsr4[$prefix]
44164             );
44165         } else {
44166             // Append directories for an already registered namespace.
44167             $this->prefixDirsPsr4[$prefix] = array_merge(
44168                 $this->prefixDirsPsr4[$prefix],
44169                 (array) $paths
44170             );
44171         }
44172     }
44173
44174     /**
44175      * Registers a set of PSR-0 directories for a given prefix,
44176      * replacing any others previously set for this prefix.
44177      *
44178      * @param string       $prefix The prefix
44179      * @param array|string $paths  The PSR-0 base directories
44180      */
44181     public function set($prefix, $paths)
44182     {
44183         if (!$prefix) {
44184             $this->fallbackDirsPsr0 = (array) $paths;
44185         } else {
44186             $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
44187         }
44188     }
44189
44190     /**
44191      * Registers a set of PSR-4 directories for a given namespace,
44192      * replacing any others previously set for this namespace.
44193      *
44194      * @param string       $prefix The prefix/namespace, with trailing '\\'
44195      * @param array|string $paths  The PSR-4 base directories
44196      *
44197      * @throws \InvalidArgumentException
44198      */
44199     public function setPsr4($prefix, $paths)
44200     {
44201         if (!$prefix) {
44202             $this->fallbackDirsPsr4 = (array) $paths;
44203         } else {
44204             $length = strlen($prefix);
44205             if ('\\' !== $prefix[$length - 1]) {
44206                 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
44207             }
44208             $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
44209             $this->prefixDirsPsr4[$prefix] = (array) $paths;
44210         }
44211     }
44212
44213     /**
44214      * Turns on searching the include path for class files.
44215      *
44216      * @param bool $useIncludePath
44217      */
44218     public function setUseIncludePath($useIncludePath)
44219     {
44220         $this->useIncludePath = $useIncludePath;
44221     }
44222
44223     /**
44224      * Can be used to check if the autoloader uses the include path to check
44225      * for classes.
44226      *
44227      * @return bool
44228      */
44229     public function getUseIncludePath()
44230     {
44231         return $this->useIncludePath;
44232     }
44233
44234     /**
44235      * Turns off searching the prefix and fallback directories for classes
44236      * that have not been registered with the class map.
44237      *
44238      * @param bool $classMapAuthoritative
44239      */
44240     public function setClassMapAuthoritative($classMapAuthoritative)
44241     {
44242         $this->classMapAuthoritative = $classMapAuthoritative;
44243     }
44244
44245     /**
44246      * Should class lookup fail if not found in the current class map?
44247      *
44248      * @return bool
44249      */
44250     public function isClassMapAuthoritative()
44251     {
44252         return $this->classMapAuthoritative;
44253     }
44254
44255     /**
44256      * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
44257      *
44258      * @param string|null $apcuPrefix
44259      */
44260     public function setApcuPrefix($apcuPrefix)
44261     {
44262         $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
44263     }
44264
44265     /**
44266      * The APCu prefix in use, or null if APCu caching is not enabled.
44267      *
44268      * @return string|null
44269      */
44270     public function getApcuPrefix()
44271     {
44272         return $this->apcuPrefix;
44273     }
44274
44275     /**
44276      * Registers this instance as an autoloader.
44277      *
44278      * @param bool $prepend Whether to prepend the autoloader or not
44279      */
44280     public function register($prepend = false)
44281     {
44282         spl_autoload_register(array($this, 'loadClass'), true, $prepend);
44283     }
44284
44285     /**
44286      * Unregisters this instance as an autoloader.
44287      */
44288     public function unregister()
44289     {
44290         spl_autoload_unregister(array($this, 'loadClass'));
44291     }
44292
44293     /**
44294      * Loads the given class or interface.
44295      *
44296      * @param  string    $class The name of the class
44297      * @return bool|null True if loaded, null otherwise
44298      */
44299     public function loadClass($class)
44300     {
44301         if ($file = $this->findFile($class)) {
44302             includeFile($file);
44303
44304             return true;
44305         }
44306     }
44307
44308     /**
44309      * Finds the path to the file where the class is defined.
44310      *
44311      * @param string $class The name of the class
44312      *
44313      * @return string|false The path if found, false otherwise
44314      */
44315     public function findFile($class)
44316     {
44317         // class map lookup
44318         if (isset($this->classMap[$class])) {
44319             return $this->classMap[$class];
44320         }
44321         if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
44322             return false;
44323         }
44324         if (null !== $this->apcuPrefix) {
44325             $file = apcu_fetch($this->apcuPrefix.$class, $hit);
44326             if ($hit) {
44327                 return $file;
44328             }
44329         }
44330
44331         $file = $this->findFileWithExtension($class, '.php');
44332
44333         // Search for Hack files if we are running on HHVM
44334         if (false === $file && defined('HHVM_VERSION')) {
44335             $file = $this->findFileWithExtension($class, '.hh');
44336         }
44337
44338         if (null !== $this->apcuPrefix) {
44339             apcu_add($this->apcuPrefix.$class, $file);
44340         }
44341
44342         if (false === $file) {
44343             // Remember that this class does not exist.
44344             $this->missingClasses[$class] = true;
44345         }
44346
44347         return $file;
44348     }
44349
44350     private function findFileWithExtension($class, $ext)
44351     {
44352         // PSR-4 lookup
44353         $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
44354
44355         $first = $class[0];
44356         if (isset($this->prefixLengthsPsr4[$first])) {
44357             $subPath = $class;
44358             while (false !== $lastPos = strrpos($subPath, '\\')) {
44359                 $subPath = substr($subPath, 0, $lastPos);
44360                 $search = $subPath.'\\';
44361                 if (isset($this->prefixDirsPsr4[$search])) {
44362                     foreach ($this->prefixDirsPsr4[$search] as $dir) {
44363                         $length = $this->prefixLengthsPsr4[$first][$search];
44364                         if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
44365                             return $file;
44366                         }
44367                     }
44368                 }
44369             }
44370         }
44371
44372         // PSR-4 fallback dirs
44373         foreach ($this->fallbackDirsPsr4 as $dir) {
44374             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
44375                 return $file;
44376             }
44377         }
44378
44379         // PSR-0 lookup
44380         if (false !== $pos = strrpos($class, '\\')) {
44381             // namespaced class name
44382             $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
44383                 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
44384         } else {
44385             // PEAR-like class name
44386             $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
44387         }
44388
44389         if (isset($this->prefixesPsr0[$first])) {
44390             foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
44391                 if (0 === strpos($class, $prefix)) {
44392                     foreach ($dirs as $dir) {
44393                         if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
44394                             return $file;
44395                         }
44396                     }
44397                 }
44398             }
44399         }
44400
44401         // PSR-0 fallback dirs
44402         foreach ($this->fallbackDirsPsr0 as $dir) {
44403             if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
44404                 return $file;
44405             }
44406         }
44407
44408         // PSR-0 include paths.
44409         if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
44410             return $file;
44411         }
44412
44413         return false;
44414     }
44415 }
44416
44417 /**
44418  * Scope isolated include.
44419  *
44420  * Prevents access to $this/self from included files.
44421  */
44422 function includeFile($file)
44423 {
44424     include $file;
44425 }
44426 {
44427     "$schema": "http://json-schema.org/draft-04/schema#",
44428     "description": "A representation of packages metadata.",
44429     "type": "object",
44430     "oneOf": [
44431         { "required": [ "packages" ] },
44432         { "required": [ "providers" ] },
44433         { "required": [ "provider-includes", "providers-url" ] }
44434     ],
44435     "properties": {
44436         "packages": {
44437             "type": ["object", "array"],
44438             "description": "A hashmap of package names in the form of <vendor>/<name>.",
44439             "additionalProperties": { "$ref": "#/definitions/versions" }
44440         },
44441         "providers-url": {
44442             "type": "string",
44443             "description": "Endpoint to retrieve provider data from, e.g. '/p/%package%$%hash%.json'."
44444         },
44445         "provider-includes": {
44446             "type": "object",
44447             "description": "A hashmap of provider listings.",
44448             "additionalProperties": { "$ref": "#/definitions/provider" }
44449         },
44450         "providers": {
44451             "type": "object",
44452             "description": "A hashmap of package names in the form of <vendor>/<name>.",
44453             "additionalProperties": { "$ref": "#/definitions/provider" }
44454         },
44455         "notify-batch": {
44456             "type": "string",
44457             "description": "Endpoint to call after multiple packages have been installed, e.g. '/downloads/'."
44458         },
44459         "search": {
44460             "type": "string",
44461             "description": "Endpoint that provides search capabilities, e.g. '/search.json?q=%query%&type=%type%'."
44462         },
44463         "warning": {
44464             "type": "string",
44465             "description": "A message that will be output by Composer as a warning when this source is consulted."
44466         }
44467     },
44468     "definitions": {
44469         "versions": {
44470             "type": "object",
44471             "description": "A hashmap of versions and their metadata.",
44472             "additionalProperties": { "$ref": "#/definitions/version" }
44473         },
44474         "version": {
44475             "type": "object",
44476             "oneOf": [
44477                 { "$ref": "#/definitions/package" },
44478                 { "$ref": "#/definitions/metapackage" }
44479             ]
44480         },
44481         "package-base": {
44482             "properties": {
44483                 "name": { "type": "string" },
44484                 "type": { "type": "string" },
44485                 "version": { "type": "string" },
44486                 "version_normalized": {
44487                     "type": "string",
44488                     "description": "Normalized version, optional but can save computational time on client side."
44489                 },
44490                 "autoload": { "type": "object" },
44491                 "require": { "type": "object" },
44492                 "replace": { "type": "object" },
44493                 "conflict": { "type": "object" },
44494                 "provide": { "type": "object" },
44495                 "time": { "type": "string" }
44496             },
44497             "additionalProperties": true
44498         },
44499         "package": {
44500             "allOf": [
44501                 { "$ref": "#/definitions/package-base" },
44502                 {
44503                     "properties": {
44504                         "dist": { "type": "object" },
44505                         "source": { "type": "object" }
44506                     }
44507                 },
44508                 { "oneOf": [
44509                     { "required": [ "name", "version", "source" ] },
44510                     { "required": [ "name", "version", "dist" ] }
44511                 ] }
44512             ]
44513         },
44514         "metapackage": {
44515             "allOf": [
44516                 { "$ref": "#/definitions/package-base" },
44517                 {
44518                     "properties": {
44519                         "type": { "type": "string", "enum": [ "metapackage" ] }
44520                     },
44521                     "required": [ "name", "version", "type" ]
44522                 }
44523             ]
44524         },
44525         "provider": {
44526             "type": "object",
44527             "properties": {
44528                 "sha256": {
44529                     "type": "string",
44530                     "description": "Hash value that can be used to validate the resource."
44531                 }
44532             }
44533         }
44534     }
44535 }
44536 {
44537     "$schema": "http://json-schema.org/draft-04/schema#",
44538     "name": "Package",
44539     "type": "object",
44540     "additionalProperties": false,
44541     "required": [ "name", "description" ],
44542     "properties": {
44543         "name": {
44544             "type": "string",
44545             "description": "Package name, including 'vendor-name/' prefix."
44546         },
44547         "type": {
44548             "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.",
44549             "type": "string"
44550         },
44551         "target-dir": {
44552             "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.",
44553             "type": "string"
44554         },
44555         "description": {
44556             "type": "string",
44557             "description": "Short package description."
44558         },
44559         "keywords": {
44560             "type": "array",
44561             "items": {
44562                 "type": "string",
44563                 "description": "A tag/keyword that this package relates to."
44564             }
44565         },
44566         "homepage": {
44567             "type": "string",
44568             "description": "Homepage URL for the project.",
44569             "format": "uri"
44570         },
44571         "version": {
44572             "type": "string",
44573             "description": "Package version, see https://getcomposer.org/doc/04-schema.md#version for more info on valid schemes."
44574         },
44575         "time": {
44576             "type": "string",
44577             "description": "Package release date, in 'YYYY-MM-DD', 'YYYY-MM-DD HH:MM:SS' or 'YYYY-MM-DDTHH:MM:SSZ' format."
44578         },
44579         "license": {
44580             "type": ["string", "array"],
44581             "description": "License name. Or an array of license names."
44582         },
44583         "authors": {
44584             "$ref": "#/definitions/authors"
44585         },
44586         "require": {
44587             "type": "object",
44588             "description": "This is a hash of package name (keys) and version constraints (values) that are required to run this package.",
44589             "additionalProperties": {
44590                 "type": "string"
44591             }
44592         },
44593         "replace": {
44594             "type": "object",
44595             "description": "This is a hash of package name (keys) and version constraints (values) that can be replaced by this package.",
44596             "additionalProperties": {
44597                 "type": "string"
44598             }
44599         },
44600         "conflict": {
44601             "type": "object",
44602             "description": "This is a hash of package name (keys) and version constraints (values) that conflict with this package.",
44603             "additionalProperties": {
44604                 "type": "string"
44605             }
44606         },
44607         "provide": {
44608             "type": "object",
44609             "description": "This is a hash of package name (keys) and version constraints (values) that this package provides in addition to this package's name.",
44610             "additionalProperties": {
44611                 "type": "string"
44612             }
44613         },
44614         "require-dev": {
44615             "type": "object",
44616             "description": "This is a hash of package name (keys) and version constraints (values) that this package requires for developing it (testing tools and such).",
44617             "additionalProperties": {
44618                 "type": "string"
44619             }
44620         },
44621         "suggest": {
44622             "type": "object",
44623             "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).",
44624             "additionalProperties": {
44625                 "type": "string"
44626             }
44627         },
44628         "config": {
44629             "type": "object",
44630             "description": "Composer options.",
44631             "properties": {
44632                 "process-timeout": {
44633                     "type": "integer",
44634                     "description": "The timeout in seconds for process executions, defaults to 300 (5mins)."
44635                 },
44636                 "use-include-path": {
44637                     "type": "boolean",
44638                     "description": "If true, the Composer autoloader will also look for classes in the PHP include path."
44639                 },
44640                 "preferred-install": {
44641                     "type": ["string", "object"],
44642                     "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\"}."
44643                 },
44644                 "notify-on-install": {
44645                     "type": "boolean",
44646                     "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."
44647                 },
44648                 "github-protocols": {
44649                     "type": "array",
44650                     "description": "A list of protocols to use for github.com clones, in priority order, defaults to [\"git\", \"https\", \"http\"].",
44651                     "items": {
44652                         "type": "string"
44653                     }
44654                 },
44655                 "github-oauth": {
44656                     "type": "object",
44657                     "description": "A hash of domain name => github API oauth tokens, typically {\"github.com\":\"<token>\"}.",
44658                     "additionalProperties": {
44659                         "type": "string"
44660                     }
44661                 },
44662                 "gitlab-oauth": {
44663                     "type": "object",
44664                     "description": "A hash of domain name => gitlab API oauth tokens, typically {\"gitlab.com\":\"<token>\"}.",
44665                     "additionalProperties": {
44666                         "type": "string"
44667                     }
44668                 },
44669                 "gitlab-token": {
44670                     "type": "object",
44671                     "description": "A hash of domain name => gitlab private tokens, typically {\"gitlab.com\":\"<token>\"}.",
44672                     "additionalProperties": true
44673                 },
44674                 "disable-tls": {
44675                     "type": "boolean",
44676                     "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."
44677                 },
44678                 "secure-http": {
44679                     "type": "boolean",
44680                     "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."
44681                 },
44682                 "cafile": {
44683                     "type": "string",
44684                     "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."
44685                 },
44686                 "capath": {
44687                     "type": "string",
44688                     "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."
44689                 },
44690                 "http-basic": {
44691                     "type": "object",
44692                     "description": "A hash of domain name => {\"username\": \"...\", \"password\": \"...\"}.",
44693                     "additionalProperties": {
44694                         "type": "object",
44695                         "required": ["username", "password"],
44696                         "properties": {
44697                             "username": {
44698                                 "type": "string",
44699                                 "description": "The username used for HTTP Basic authentication"
44700                             },
44701                             "password": {
44702                                 "type": "string",
44703                                 "description": "The password used for HTTP Basic authentication"
44704                             }
44705                         }
44706                     }
44707                 },
44708                 "store-auths": {
44709                     "type": ["string", "boolean"],
44710                     "description": "What to do after prompting for authentication, one of: true (store), false (do not store) or \"prompt\" (ask every time), defaults to prompt."
44711                 },
44712                 "platform": {
44713                     "type": "object",
44714                     "description": "This is a hash of package name (keys) and version (values) that will be used to mock the platform packages on this machine.",
44715                     "additionalProperties": {
44716                         "type": "string"
44717                     }
44718                 },
44719                 "vendor-dir": {
44720                     "type": "string",
44721                     "description": "The location where all packages are installed, defaults to \"vendor\"."
44722                 },
44723                 "bin-dir": {
44724                     "type": "string",
44725                     "description": "The location where all binaries are linked, defaults to \"vendor/bin\"."
44726                 },
44727                 "data-dir": {
44728                     "type": "string",
44729                     "description": "The location where old phar files are stored, defaults to \"$home\" except on XDG Base Directory compliant unixes."
44730                 },
44731                 "cache-dir": {
44732                     "type": "string",
44733                     "description": "The location where all caches are located, defaults to \"~/.composer/cache\" on *nix and \"%LOCALAPPDATA%\\Composer\" on windows."
44734                 },
44735                 "cache-files-dir": {
44736                     "type": "string",
44737                     "description": "The location where files (zip downloads) are cached, defaults to \"{$cache-dir}/files\"."
44738                 },
44739                 "cache-repo-dir": {
44740                     "type": "string",
44741                     "description": "The location where repo (git/hg repo clones) are cached, defaults to \"{$cache-dir}/repo\"."
44742                 },
44743                 "cache-vcs-dir": {
44744                     "type": "string",
44745                     "description": "The location where vcs infos (git clones, github api calls, etc. when reading vcs repos) are cached, defaults to \"{$cache-dir}/vcs\"."
44746                 },
44747                 "cache-ttl": {
44748                     "type": "integer",
44749                     "description": "The default cache time-to-live, defaults to 15552000 (6 months)."
44750                 },
44751                 "cache-files-ttl": {
44752                     "type": "integer",
44753                     "description": "The cache time-to-live for files, defaults to the value of cache-ttl."
44754                 },
44755                 "cache-files-maxsize": {
44756                     "type": ["string", "integer"],
44757                     "description": "The cache max size for the files cache, defaults to \"300MiB\"."
44758                 },
44759                 "bin-compat": {
44760                     "enum": ["auto", "full"],
44761                     "description": "The compatibility of the binaries, defaults to \"auto\" (automatically guessed) and can be \"full\" (compatible with both Windows and Unix-based systems)."
44762                 },
44763                 "discard-changes": {
44764                     "type": ["string", "boolean"],
44765                     "description": "The default style of handling dirty updates, defaults to false and can be any of true, false or \"stash\"."
44766                 },
44767                 "autoloader-suffix": {
44768                     "type": "string",
44769                     "description": "Optional string to be used as a suffix for the generated Composer autoloader. When null a random one will be generated."
44770                 },
44771                 "optimize-autoloader": {
44772                     "type": "boolean",
44773                     "description": "Always optimize when dumping the autoloader."
44774                 },
44775                 "prepend-autoloader": {
44776                     "type": "boolean",
44777                     "description": "If false, the composer autoloader will not be prepended to existing autoloaders, defaults to true."
44778                 },
44779                 "classmap-authoritative": {
44780                     "type": "boolean",
44781                     "description": "If true, the composer autoloader will not scan the filesystem for classes that are not found in the class map, defaults to false."
44782                 },
44783                 "apcu-autoloader": {
44784                     "type": "boolean",
44785                     "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."
44786                 },
44787                 "github-domains": {
44788                     "type": "array",
44789                     "description": "A list of domains to use in github mode. This is used for GitHub Enterprise setups, defaults to [\"github.com\"].",
44790                     "items": {
44791                         "type": "string"
44792                     }
44793                 },
44794                 "github-expose-hostname": {
44795                     "type": "boolean",
44796                     "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."
44797                 },
44798                 "gitlab-domains": {
44799                     "type": "array",
44800                     "description": "A list of domains to use in gitlab mode. This is used for custom GitLab setups, defaults to [\"gitlab.com\"].",
44801                     "items": {
44802                         "type": "string"
44803                     }
44804                 },
44805                 "archive-format": {
44806                     "type": "string",
44807                     "description": "The default archiving format when not provided on cli, defaults to \"tar\"."
44808                 },
44809                 "archive-dir": {
44810                     "type": "string",
44811                     "description": "The default archive path when not provided on cli, defaults to \".\"."
44812                 },
44813                 "htaccess-protect": {
44814                     "type": "boolean",
44815                     "description": "Defaults to true. If set to false, Composer will not create .htaccess files in the composer home, cache, and data directories."
44816                 }
44817             }
44818         },
44819         "extra": {
44820             "type": ["object", "array"],
44821             "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.",
44822             "additionalProperties": true
44823         },
44824         "autoload": {
44825             "$ref": "#/definitions/autoload"
44826         },
44827         "autoload-dev": {
44828             "type": "object",
44829             "description": "Description of additional autoload rules for development purpose (eg. a test suite).",
44830             "properties": {
44831                 "psr-0": {
44832                     "type": "object",
44833                     "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.",
44834                     "additionalProperties": {
44835                         "type": ["string", "array"],
44836                         "items": {
44837                             "type": "string"
44838                         }
44839                     }
44840                 },
44841                 "psr-4": {
44842                     "type": "object",
44843                     "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.",
44844                     "additionalProperties": {
44845                         "type": ["string", "array"],
44846                         "items": {
44847                             "type": "string"
44848                         }
44849                     }
44850                 },
44851                 "classmap": {
44852                     "type": "array",
44853                     "description": "This is an array of directories that contain classes to be included in the class-map generation process."
44854                 },
44855                 "files": {
44856                     "type": "array",
44857                     "description": "This is an array of files that are always required on every request."
44858                 }
44859             }
44860         },
44861         "archive": {
44862             "type": ["object"],
44863             "description": "Options for creating package archives for distribution.",
44864             "properties": {
44865                 "exclude": {
44866                     "type": "array",
44867                     "description": "A list of patterns for paths to exclude or include if prefixed with an exclamation mark."
44868                 }
44869             }
44870         },
44871         "repositories": {
44872             "type": ["object", "array"],
44873             "description": "A set of additional repositories where packages can be found.",
44874             "additionalProperties": {
44875                 "oneOf": [
44876                     { "$ref": "#/definitions/repository" },
44877                     { "type": "boolean", "enum": [false] }
44878                 ]
44879             },
44880             "items": {
44881                 "oneOf": [
44882                     { "$ref": "#/definitions/repository" },
44883                     {
44884                         "type": "object",
44885                         "additionalProperties": { "type": "boolean", "enum": [false] },
44886                         "minProperties": 1,
44887                         "maxProperties": 1
44888                     }
44889                 ]
44890             }
44891         },
44892         "minimum-stability": {
44893             "type": ["string"],
44894             "description": "The minimum stability the packages must have to be install-able. Possible values are: dev, alpha, beta, RC, stable.",
44895             "pattern": "^dev|alpha|beta|rc|RC|stable$"
44896         },
44897         "prefer-stable": {
44898             "type": ["boolean"],
44899             "description": "If set to true, stable packages will be preferred to dev packages when possible, even if the minimum-stability allows unstable packages."
44900         },
44901         "bin": {
44902             "type": ["array"],
44903             "description": "A set of files that should be treated as binaries and symlinked into bin-dir (from config).",
44904             "items": {
44905                 "type": "string"
44906             }
44907         },
44908         "include-path": {
44909             "type": ["array"],
44910             "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.",
44911             "items": {
44912                 "type": "string"
44913             }
44914         },
44915         "scripts": {
44916             "type": ["object"],
44917             "description": "Scripts listeners that will be executed before/after some events.",
44918             "properties": {
44919                 "pre-install-cmd": {
44920                     "type": ["array", "string"],
44921                     "description": "Occurs before the install command is executed, contains one or more Class::method callables or shell commands."
44922                 },
44923                 "post-install-cmd": {
44924                     "type": ["array", "string"],
44925                     "description": "Occurs after the install command is executed, contains one or more Class::method callables or shell commands."
44926                 },
44927                 "pre-update-cmd": {
44928                     "type": ["array", "string"],
44929                     "description": "Occurs before the update command is executed, contains one or more Class::method callables or shell commands."
44930                 },
44931                 "post-update-cmd": {
44932                     "type": ["array", "string"],
44933                     "description": "Occurs after the update command is executed, contains one or more Class::method callables or shell commands."
44934                 },
44935                 "pre-status-cmd": {
44936                     "type": ["array", "string"],
44937                     "description": "Occurs before the status command is executed, contains one or more Class::method callables or shell commands."
44938                 },
44939                 "post-status-cmd": {
44940                     "type": ["array", "string"],
44941                     "description": "Occurs after the status command is executed, contains one or more Class::method callables or shell commands."
44942                 },
44943                 "pre-package-install": {
44944                     "type": ["array", "string"],
44945                     "description": "Occurs before a package is installed, contains one or more Class::method callables or shell commands."
44946                 },
44947                 "post-package-install": {
44948                     "type": ["array", "string"],
44949                     "description": "Occurs after a package is installed, contains one or more Class::method callables or shell commands."
44950                 },
44951                 "pre-package-update": {
44952                     "type": ["array", "string"],
44953                     "description": "Occurs before a package is updated, contains one or more Class::method callables or shell commands."
44954                 },
44955                 "post-package-update": {
44956                     "type": ["array", "string"],
44957                     "description": "Occurs after a package is updated, contains one or more Class::method callables or shell commands."
44958                 },
44959                 "pre-package-uninstall": {
44960                     "type": ["array", "string"],
44961                     "description": "Occurs before a package has been uninstalled, contains one or more Class::method callables or shell commands."
44962                 },
44963                 "post-package-uninstall": {
44964                     "type": ["array", "string"],
44965                     "description": "Occurs after a package has been uninstalled, contains one or more Class::method callables or shell commands."
44966                 },
44967                 "pre-autoload-dump": {
44968                     "type": ["array", "string"],
44969                     "description": "Occurs before the autoloader is dumped, contains one or more Class::method callables or shell commands."
44970                 },
44971                 "post-autoload-dump": {
44972                     "type": ["array", "string"],
44973                     "description": "Occurs after the autoloader is dumped, contains one or more Class::method callables or shell commands."
44974                 },
44975                 "post-root-package-install": {
44976                     "type": ["array", "string"],
44977                     "description": "Occurs after the root-package is installed, contains one or more Class::method callables or shell commands."
44978                 },
44979                 "post-create-project-cmd": {
44980                     "type": ["array", "string"],
44981                     "description": "Occurs after the create-project command is executed, contains one or more Class::method callables or shell commands."
44982                 }
44983             }
44984         },
44985         "support": {
44986             "type": "object",
44987             "properties": {
44988                 "email": {
44989                     "type": "string",
44990                     "description": "Email address for support.",
44991                     "format": "email"
44992                 },
44993                 "issues": {
44994                     "type": "string",
44995                     "description": "URL to the issue tracker.",
44996                     "format": "uri"
44997                 },
44998                 "forum": {
44999                     "type": "string",
45000                     "description": "URL to the forum.",
45001                     "format": "uri"
45002                 },
45003                 "wiki": {
45004                     "type": "string",
45005                     "description": "URL to the wiki.",
45006                     "format": "uri"
45007                 },
45008                 "irc": {
45009                     "type": "string",
45010                     "description": "IRC channel for support, as irc://server/channel.",
45011                     "format": "uri"
45012                 },
45013                 "source": {
45014                     "type": "string",
45015                     "description": "URL to browse or download the sources.",
45016                     "format": "uri"
45017                 },
45018                 "docs": {
45019                     "type": "string",
45020                     "description": "URL to the documentation.",
45021                     "format": "uri"
45022                 },
45023                 "rss": {
45024                     "type": "string",
45025                     "description": "URL to the RSS feed.",
45026                     "format": "uri"
45027                 }
45028             }
45029         },
45030         "non-feature-branches": {
45031             "type": ["array"],
45032             "description": "A set of string or regex patterns for non-numeric branch names that will not be handled as feature branches.",
45033             "items": {
45034                 "type": "string"
45035             }
45036         },
45037         "abandoned": {
45038             "type": ["boolean", "string"],
45039             "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."
45040         },
45041         "_comment": {
45042             "type": ["array", "string"],
45043             "description": "A key to store comments in"
45044         }
45045     },
45046     "definitions": {
45047         "authors": {
45048             "type": "array",
45049             "description": "List of authors that contributed to the package. This is typically the main maintainers, not the full list.",
45050             "items": {
45051                 "type": "object",
45052                 "additionalProperties": false,
45053                 "required": [ "name"],
45054                 "properties": {
45055                     "name": {
45056                         "type": "string",
45057                         "description": "Full name of the author."
45058                     },
45059                     "email": {
45060                         "type": "string",
45061                         "description": "Email address of the author.",
45062                         "format": "email"
45063                     },
45064                     "homepage": {
45065                         "type": "string",
45066                         "description": "Homepage URL for the author.",
45067                         "format": "uri"
45068                     },
45069                     "role": {
45070                         "type": "string",
45071                         "description": "Author's role in the project."
45072                     }
45073                 }
45074             }
45075         },
45076         "autoload": {
45077             "type": "object",
45078             "description": "Description of how the package can be autoloaded.",
45079             "properties": {
45080                 "psr-0": {
45081                     "type": "object",
45082                     "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.",
45083                     "additionalProperties": {
45084                         "type": ["string", "array"],
45085                         "items": {
45086                             "type": "string"
45087                         }
45088                     }
45089                 },
45090                 "psr-4": {
45091                     "type": "object",
45092                     "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.",
45093                     "additionalProperties": {
45094                         "type": ["string", "array"],
45095                         "items": {
45096                             "type": "string"
45097                         }
45098                     }
45099                 },
45100                 "classmap": {
45101                     "type": "array",
45102                     "description": "This is an array of directories that contain classes to be included in the class-map generation process."
45103                 },
45104                 "files": {
45105                     "type": "array",
45106                     "description": "This is an array of files that are always required on every request."
45107                 },
45108                 "exclude-from-classmap": {
45109                     "type": "array",
45110                     "description": "This is an array of patterns to exclude from autoload classmap generation. (e.g. \"exclude-from-classmap\": [\"/test/\", \"/tests/\", \"/Tests/\"]"
45111                 }
45112             }
45113         },
45114         "repository": {
45115             "type": "object",
45116             "oneOf": [
45117                 { "$ref": "#/definitions/composer-repository" },
45118                 { "$ref": "#/definitions/vcs-repository" },
45119                 { "$ref": "#/definitions/path-repository" },
45120                 { "$ref": "#/definitions/artifact-repository" },
45121                 { "$ref": "#/definitions/pear-repository" },
45122                 { "$ref": "#/definitions/package-repository" }
45123             ]
45124         },
45125         "composer-repository": {
45126             "type": "object",
45127             "required": ["type", "url"],
45128             "properties": {
45129                 "type": { "type": "string", "enum": ["composer"] },
45130                 "url": { "type": "string" },
45131                 "options": {
45132                     "type": "object",
45133                     "additionalProperties": true
45134                 },
45135                 "allow_ssl_downgrade": { "type": "boolean" },
45136                 "force-lazy-providers": { "type": "boolean" }
45137             }
45138         },
45139         "vcs-repository": {
45140             "type": "object",
45141             "required": ["type", "url"],
45142             "properties": {
45143                 "type": { "type": "string", "enum": ["vcs", "github", "git", "gitlab", "git-bitbucket", "hg", "hg-bitbucket", "fossil", "perforce", "svn"] },
45144                 "url": { "type": "string" },
45145                 "no-api": { "type": "boolean" },
45146                 "secure-http": { "type": "boolean" },
45147                 "svn-cache-credentials": { "type": "boolean" },
45148                 "trunk-path": { "type": ["string", "boolean"] },
45149                 "branches-path": { "type": ["string", "boolean"] },
45150                 "tags-path": { "type": ["string", "boolean"] },
45151                 "package-path": { "type": "string" },
45152                 "depot": { "type": "string" },
45153                 "branch": { "type": "string" },
45154                 "unique_perforce_client_name": { "type": "string" },
45155                 "p4user": { "type": "string" },
45156                 "p4password": { "type": "string" }
45157             }
45158         },
45159         "path-repository": {
45160             "type": "object",
45161             "required": ["type", "url"],
45162             "properties": {
45163                 "type": { "type": "string", "enum": ["path"] },
45164                 "url": { "type": "string" },
45165                 "options": {
45166                     "type": "object",
45167                     "properties": {
45168                         "symlink": { "type": ["boolean", "null"] }
45169                     },
45170                     "additionalProperties": true
45171                 }
45172             }
45173         },
45174         "artifact-repository": {
45175             "type": "object",
45176             "required": ["type", "url"],
45177             "properties": {
45178                 "type": { "type": "string", "enum": ["artifact"] },
45179                 "url": { "type": "string" }
45180             }
45181         },
45182         "pear-repository": {
45183             "type": "object",
45184             "required": ["type", "url"],
45185             "properties": {
45186                 "type": { "type": "string", "enum": ["pear"] },
45187                 "url": { "type": "string" },
45188                 "vendor-alias": { "type": "string" }
45189             }
45190         },
45191         "package-repository": {
45192             "type": "object",
45193             "required": ["type", "package"],
45194             "properties": {
45195                 "type": { "type": "string", "enum": ["package"] },
45196                 "package": {
45197                     "oneOf": [
45198                         { "$ref": "#/definitions/inline-package" },
45199                         {
45200                             "type": "array",
45201                             "items": {
45202                                 "type": { "$ref": "#/definitions/inline-package" }
45203                             }
45204                         }
45205                     ]
45206                 }
45207             }
45208         },
45209         "inline-package": {
45210             "required": ["name", "version"],
45211             "properties": {
45212                 "name": {
45213                     "type": "string",
45214                     "description": "Package name, including 'vendor-name/' prefix."
45215                 },
45216                 "type": {
45217                     "type": "string"
45218                 },
45219                 "target-dir": {
45220                     "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.",
45221                     "type": "string"
45222                 },
45223                 "description": {
45224                     "type": "string"
45225                 },
45226                 "keywords": {
45227                     "type": "array",
45228                     "items": {
45229                         "type": "string"
45230                     }
45231                 },
45232                 "homepage": {
45233                     "type": "string",
45234                     "format": "uri"
45235                 },
45236                 "version": {
45237                     "type": "string"
45238                 },
45239                 "time": {
45240                     "type": "string"
45241                 },
45242                 "license": {
45243                     "type": [
45244                         "string",
45245                         "array"
45246                     ]
45247                 },
45248                 "authors": {
45249                     "$ref": "#/definitions/authors"
45250                 },
45251                 "require": {
45252                     "type": "object",
45253                     "additionalProperties": {
45254                         "type": "string"
45255                     }
45256                 },
45257                 "replace": {
45258                     "type": "object",
45259                     "additionalProperties": {
45260                         "type": "string"
45261                     }
45262                 },
45263                 "conflict": {
45264                     "type": "object",
45265                     "additionalProperties": {
45266                         "type": "string"
45267                     }
45268                 },
45269                 "provide": {
45270                     "type": "object",
45271                     "additionalProperties": {
45272                         "type": "string"
45273                     }
45274                 },
45275                 "require-dev": {
45276                     "type": "object",
45277                     "additionalProperties": {
45278                         "type": "string"
45279                     }
45280                 },
45281                 "suggest": {
45282                     "type": "object",
45283                     "additionalProperties": {
45284                         "type": "string"
45285                     }
45286                 },
45287                 "extra": {
45288                     "type": ["object", "array"],
45289                     "additionalProperties": true
45290                 },
45291                 "autoload": {
45292                     "$ref": "#/definitions/autoload"
45293                 },
45294                 "archive": {
45295                     "type": ["object"],
45296                     "properties": {
45297                         "exclude": {
45298                             "type": "array"
45299                         }
45300                     }
45301                 },
45302                 "bin": {
45303                     "type": ["array"],
45304                     "description": "A set of files that should be treated as binaries and symlinked into bin-dir (from config).",
45305                     "items": {
45306                         "type": "string"
45307                     }
45308                 },
45309                 "include-path": {
45310                     "type": ["array"],
45311                     "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.",
45312                     "items": {
45313                         "type": "string"
45314                     }
45315                 },
45316                 "source": {
45317                     "type": "object",
45318                     "required": ["type", "url", "reference"],
45319                     "properties": {
45320                         "type": {
45321                             "type": "string"
45322                         },
45323                         "url": {
45324                             "type": "string"
45325                         },
45326                         "reference": {
45327                             "type": "string"
45328                         },
45329                         "mirrors": {
45330                             "type": "array"
45331                         }
45332                     }
45333                 },
45334                 "dist": {
45335                     "type": "object",
45336                     "required": ["type", "url"],
45337                     "properties": {
45338                         "type": {
45339                             "type": "string"
45340                         },
45341                         "url": {
45342                             "type": "string"
45343                         },
45344                         "reference": {
45345                             "type": "string"
45346                         },
45347                         "shasum": {
45348                             "type": "string"
45349                         },
45350                         "mirrors": {
45351                             "type": "array"
45352                         }
45353                     }
45354                 }
45355             },
45356             "additionalProperties": true
45357         }
45358     }
45359 }
45360 {
45361     "389-exception": [
45362         "389 Directory Server\nException"
45363     ],
45364     "Autoconf-exception-2.0": [
45365         "Autoconf exception 2.0"
45366     ],
45367     "Autoconf-exception-3.0": [
45368         "Autoconf exception 3.0"
45369     ],
45370     "Bison-exception-2.2": [
45371         "Bison exception 2.2"
45372     ],
45373     "Classpath-exception-2.0": [
45374         "Classpath exception 2.0"
45375     ],
45376     "CLISP-exception-2.0": [
45377         "CLISP exception 2.0"
45378     ],
45379     "DigiRule-FOSS-exception": [
45380         "DigiRule FOSS License Exception"
45381     ],
45382     "eCos-exception-2.0": [
45383         "eCos exception 2.0"
45384     ],
45385     "Fawkes-Runtime-exception": [
45386         "Fawkes Runtime Exception"
45387     ],
45388     "FLTK-exception": [
45389         "FLTK exception"
45390     ],
45391     "Font-exception-2.0": [
45392         "Font exception 2.0"
45393     ],
45394     "freertos-exception-2.0": [
45395         "FreeRTOS Exception 2.0"
45396     ],
45397     "GCC-exception-2.0": [
45398         "GCC Runtime Library exception 2.0"
45399     ],
45400     "GCC-exception-3.1": [
45401         "GCC Runtime Library exception 3.1"
45402     ],
45403     "gnu-javamail-exception": [
45404         "GNU JavaMail exception"
45405     ],
45406     "i2p-gpl-java-exception": [
45407         "i2p GPL+Java Exception"
45408     ],
45409     "Libtool-exception": [
45410         "Libtool Exception"
45411     ],
45412     "LZMA-exception": [
45413         "LZMA exception"
45414     ],
45415     "mif-exception": [
45416         "Macros and Inline Functions Exception"
45417     ],
45418     "Nokia-Qt-exception-1.1": [
45419         "Nokia Qt LGPL exception 1.1"
45420     ],
45421     "OCCT-exception-1.0": [
45422         "Open CASCADE Exception 1.0"
45423     ],
45424     "openvpn-openssl-exception": [
45425         "OpenVPN OpenSSL Exception"
45426     ],
45427     "Qwt-exception-1.0": [
45428         "Qwt exception 1.0"
45429     ],
45430     "u-boot-exception-2.0": [
45431         "U-Boot exception 2.0"
45432     ],
45433     "WxWindows-exception-3.1": [
45434         "WxWindows Library Exception 3.1"
45435     ]
45436 }{
45437     "0BSD": [
45438         "BSD Zero Clause License",
45439         true
45440     ],
45441     "AAL": [
45442         "Attribution Assurance License",
45443         true
45444     ],
45445     "Abstyles": [
45446         "Abstyles License",
45447         false
45448     ],
45449     "Adobe-2006": [
45450         "Adobe Systems Incorporated Source Code License Agreement",
45451         false
45452     ],
45453     "Adobe-Glyph": [
45454         "Adobe Glyph List License",
45455         false
45456     ],
45457     "ADSL": [
45458         "Amazon Digital Services License",
45459         false
45460     ],
45461     "AFL-1.1": [
45462         "Academic Free License v1.1",
45463         true
45464     ],
45465     "AFL-1.2": [
45466         "Academic Free License v1.2",
45467         true
45468     ],
45469     "AFL-2.0": [
45470         "Academic Free License v2.0",
45471         true
45472     ],
45473     "AFL-2.1": [
45474         "Academic Free License v2.1",
45475         true
45476     ],
45477     "AFL-3.0": [
45478         "Academic Free License v3.0",
45479         true
45480     ],
45481     "Afmparse": [
45482         "Afmparse License",
45483         false
45484     ],
45485     "AGPL-1.0": [
45486         "Affero General Public License v1.0",
45487         false
45488     ],
45489     "AGPL-3.0": [
45490         "GNU Affero General Public License v3.0",
45491         true
45492     ],
45493     "Aladdin": [
45494         "Aladdin Free Public License",
45495         false
45496     ],
45497     "AMDPLPA": [
45498         "AMD's plpa_map.c License",
45499         false
45500     ],
45501     "AML": [
45502         "Apple MIT License",
45503         false
45504     ],
45505     "AMPAS": [
45506         "Academy of Motion Picture Arts and Sciences BSD",
45507         false
45508     ],
45509     "ANTLR-PD": [
45510         "ANTLR Software Rights Notice",
45511         false
45512     ],
45513     "Apache-1.0": [
45514         "Apache License 1.0",
45515         false
45516     ],
45517     "Apache-1.1": [
45518         "Apache License 1.1",
45519         true
45520     ],
45521     "Apache-2.0": [
45522         "Apache License 2.0",
45523         true
45524     ],
45525     "APAFML": [
45526         "Adobe Postscript AFM License",
45527         false
45528     ],
45529     "APL-1.0": [
45530         "Adaptive Public License 1.0",
45531         true
45532     ],
45533     "APSL-1.0": [
45534         "Apple Public Source License 1.0",
45535         true
45536     ],
45537     "APSL-1.1": [
45538         "Apple Public Source License 1.1",
45539         true
45540     ],
45541     "APSL-1.2": [
45542         "Apple Public Source License 1.2",
45543         true
45544     ],
45545     "APSL-2.0": [
45546         "Apple Public Source License 2.0",
45547         true
45548     ],
45549     "Artistic-1.0": [
45550         "Artistic License 1.0",
45551         true
45552     ],
45553     "Artistic-1.0-cl8": [
45554         "Artistic License 1.0 w/clause 8",
45555         true
45556     ],
45557     "Artistic-1.0-Perl": [
45558         "Artistic License 1.0 (Perl)",
45559         true
45560     ],
45561     "Artistic-2.0": [
45562         "Artistic License 2.0",
45563         true
45564     ],
45565     "Bahyph": [
45566         "Bahyph License",
45567         false
45568     ],
45569     "Barr": [
45570         "Barr License",
45571         false
45572     ],
45573     "Beerware": [
45574         "Beerware License",
45575         false
45576     ],
45577     "BitTorrent-1.0": [
45578         "BitTorrent Open Source License v1.0",
45579         false
45580     ],
45581     "BitTorrent-1.1": [
45582         "BitTorrent Open Source License v1.1",
45583         false
45584     ],
45585     "Borceux": [
45586         "Borceux license",
45587         false
45588     ],
45589     "BSD-2-Clause": [
45590         "BSD 2-clause \"Simplified\" License",
45591         true
45592     ],
45593     "BSD-2-Clause-FreeBSD": [
45594         "BSD 2-clause FreeBSD License",
45595         false
45596     ],
45597     "BSD-2-Clause-NetBSD": [
45598         "BSD 2-clause NetBSD License",
45599         false
45600     ],
45601     "BSD-3-Clause": [
45602         "BSD 3-clause \"New\" or \"Revised\" License",
45603         true
45604     ],
45605     "BSD-3-Clause-Attribution": [
45606         "BSD with attribution",
45607         false
45608     ],
45609     "BSD-3-Clause-Clear": [
45610         "BSD 3-clause Clear License",
45611         false
45612     ],
45613     "BSD-3-Clause-LBNL": [
45614         "Lawrence Berkeley National Labs BSD variant license",
45615         false
45616     ],
45617     "BSD-3-Clause-No-Nuclear-License": [
45618         "BSD 3-Clause No Nuclear License",
45619         false
45620     ],
45621     "BSD-3-Clause-No-Nuclear-License-2014": [
45622         "BSD 3-Clause No Nuclear License 2014",
45623         false
45624     ],
45625     "BSD-3-Clause-No-Nuclear-Warranty": [
45626         "BSD 3-Clause No Nuclear Warranty",
45627         false
45628     ],
45629     "BSD-4-Clause": [
45630         "BSD 4-clause \"Original\" or \"Old\" License",
45631         false
45632     ],
45633     "BSD-4-Clause-UC": [
45634         "BSD-4-Clause (University of California-Specific)",
45635         false
45636     ],
45637     "BSD-Protection": [
45638         "BSD Protection License",
45639         false
45640     ],
45641     "BSD-Source-Code": [
45642         "BSD Source Code Attribution",
45643         false
45644     ],
45645     "BSL-1.0": [
45646         "Boost Software License 1.0",
45647         true
45648     ],
45649     "bzip2-1.0.5": [
45650         "bzip2 and libbzip2 License v1.0.5",
45651         false
45652     ],
45653     "bzip2-1.0.6": [
45654         "bzip2 and libbzip2 License v1.0.6",
45655         false
45656     ],
45657     "Caldera": [
45658         "Caldera License",
45659         false
45660     ],
45661     "CATOSL-1.1": [
45662         "Computer Associates Trusted Open Source License 1.1",
45663         true
45664     ],
45665     "CC-BY-1.0": [
45666         "Creative Commons Attribution 1.0",
45667         false
45668     ],
45669     "CC-BY-2.0": [
45670         "Creative Commons Attribution 2.0",
45671         false
45672     ],
45673     "CC-BY-2.5": [
45674         "Creative Commons Attribution 2.5",
45675         false
45676     ],
45677     "CC-BY-3.0": [
45678         "Creative Commons Attribution 3.0",
45679         false
45680     ],
45681     "CC-BY-4.0": [
45682         "Creative Commons Attribution 4.0",
45683         false
45684     ],
45685     "CC-BY-NC-1.0": [
45686         "Creative Commons Attribution Non Commercial 1.0",
45687         false
45688     ],
45689     "CC-BY-NC-2.0": [
45690         "Creative Commons Attribution Non Commercial 2.0",
45691         false
45692     ],
45693     "CC-BY-NC-2.5": [
45694         "Creative Commons Attribution Non Commercial 2.5",
45695         false
45696     ],
45697     "CC-BY-NC-3.0": [
45698         "Creative Commons Attribution Non Commercial 3.0",
45699         false
45700     ],
45701     "CC-BY-NC-4.0": [
45702         "Creative Commons Attribution Non Commercial 4.0",
45703         false
45704     ],
45705     "CC-BY-NC-ND-1.0": [
45706         "Creative Commons Attribution Non Commercial No Derivatives 1.0",
45707         false
45708     ],
45709     "CC-BY-NC-ND-2.0": [
45710         "Creative Commons Attribution Non Commercial No Derivatives 2.0",
45711         false
45712     ],
45713     "CC-BY-NC-ND-2.5": [
45714         "Creative Commons Attribution Non Commercial No Derivatives 2.5",
45715         false
45716     ],
45717     "CC-BY-NC-ND-3.0": [
45718         "Creative Commons Attribution Non Commercial No Derivatives 3.0",
45719         false
45720     ],
45721     "CC-BY-NC-ND-4.0": [
45722         "Creative Commons Attribution Non Commercial No Derivatives 4.0",
45723         false
45724     ],
45725     "CC-BY-NC-SA-1.0": [
45726         "Creative Commons Attribution Non Commercial Share Alike 1.0",
45727         false
45728     ],
45729     "CC-BY-NC-SA-2.0": [
45730         "Creative Commons Attribution Non Commercial Share Alike 2.0",
45731         false
45732     ],
45733     "CC-BY-NC-SA-2.5": [
45734         "Creative Commons Attribution Non Commercial Share Alike 2.5",
45735         false
45736     ],
45737     "CC-BY-NC-SA-3.0": [
45738         "Creative Commons Attribution Non Commercial Share Alike 3.0",
45739         false
45740     ],
45741     "CC-BY-NC-SA-4.0": [
45742         "Creative Commons Attribution Non Commercial Share Alike 4.0",
45743         false
45744     ],
45745     "CC-BY-ND-1.0": [
45746         "Creative Commons Attribution No Derivatives 1.0",
45747         false
45748     ],
45749     "CC-BY-ND-2.0": [
45750         "Creative Commons Attribution No Derivatives 2.0",
45751         false
45752     ],
45753     "CC-BY-ND-2.5": [
45754         "Creative Commons Attribution No Derivatives 2.5",
45755         false
45756     ],
45757     "CC-BY-ND-3.0": [
45758         "Creative Commons Attribution No Derivatives 3.0",
45759         false
45760     ],
45761     "CC-BY-ND-4.0": [
45762         "Creative Commons Attribution No Derivatives 4.0",
45763         false
45764     ],
45765     "CC-BY-SA-1.0": [
45766         "Creative Commons Attribution Share Alike 1.0",
45767         false
45768     ],
45769     "CC-BY-SA-2.0": [
45770         "Creative Commons Attribution Share Alike 2.0",
45771         false
45772     ],
45773     "CC-BY-SA-2.5": [
45774         "Creative Commons Attribution Share Alike 2.5",
45775         false
45776     ],
45777     "CC-BY-SA-3.0": [
45778         "Creative Commons Attribution Share Alike 3.0",
45779         false
45780     ],
45781     "CC-BY-SA-4.0": [
45782         "Creative Commons Attribution Share Alike 4.0",
45783         false
45784     ],
45785     "CC0-1.0": [
45786         "Creative Commons Zero v1.0 Universal",
45787         false
45788     ],
45789     "CDDL-1.0": [
45790         "Common Development and Distribution License 1.0",
45791         true
45792     ],
45793     "CDDL-1.1": [
45794         "Common Development and Distribution License 1.1",
45795         false
45796     ],
45797     "CECILL-1.0": [
45798         "CeCILL Free Software License Agreement v1.0",
45799         false
45800     ],
45801     "CECILL-1.1": [
45802         "CeCILL Free Software License Agreement v1.1",
45803         false
45804     ],
45805     "CECILL-2.0": [
45806         "CeCILL Free Software License Agreement v2.0",
45807         false
45808     ],
45809     "CECILL-2.1": [
45810         "CeCILL Free Software License Agreement v2.1",
45811         true
45812     ],
45813     "CECILL-B": [
45814         "CeCILL-B Free Software License Agreement",
45815         false
45816     ],
45817     "CECILL-C": [
45818         "CeCILL-C Free Software License Agreement",
45819         false
45820     ],
45821     "ClArtistic": [
45822         "Clarified Artistic License",
45823         false
45824     ],
45825     "CNRI-Jython": [
45826         "CNRI Jython License",
45827         false
45828     ],
45829     "CNRI-Python": [
45830         "CNRI Python License",
45831         true
45832     ],
45833     "CNRI-Python-GPL-Compatible": [
45834         "CNRI Python Open Source GPL Compatible License Agreement",
45835         false
45836     ],
45837     "Condor-1.1": [
45838         "Condor Public License v1.1",
45839         false
45840     ],
45841     "CPAL-1.0": [
45842         "Common Public Attribution License 1.0",
45843         true
45844     ],
45845     "CPL-1.0": [
45846         "Common Public License 1.0",
45847         true
45848     ],
45849     "CPOL-1.02": [
45850         "Code Project Open License 1.02",
45851         false
45852     ],
45853     "Crossword": [
45854         "Crossword License",
45855         false
45856     ],
45857     "CrystalStacker": [
45858         "CrystalStacker License",
45859         false
45860     ],
45861     "CUA-OPL-1.0": [
45862         "CUA Office Public License v1.0",
45863         true
45864     ],
45865     "Cube": [
45866         "Cube License",
45867         false
45868     ],
45869     "curl": [
45870         "curl License",
45871         false
45872     ],
45873     "D-FSL-1.0": [
45874         "Deutsche Freie Software Lizenz",
45875         false
45876     ],
45877     "diffmark": [
45878         "diffmark license",
45879         false
45880     ],
45881     "DOC": [
45882         "DOC License",
45883         false
45884     ],
45885     "Dotseqn": [
45886         "Dotseqn License",
45887         false
45888     ],
45889     "DSDP": [
45890         "DSDP License",
45891         false
45892     ],
45893     "dvipdfm": [
45894         "dvipdfm License",
45895         false
45896     ],
45897     "ECL-1.0": [
45898         "Educational Community License v1.0",
45899         true
45900     ],
45901     "ECL-2.0": [
45902         "Educational Community License v2.0",
45903         true
45904     ],
45905     "EFL-1.0": [
45906         "Eiffel Forum License v1.0",
45907         true
45908     ],
45909     "EFL-2.0": [
45910         "Eiffel Forum License v2.0",
45911         true
45912     ],
45913     "eGenix": [
45914         "eGenix.com Public License 1.1.0",
45915         false
45916     ],
45917     "Entessa": [
45918         "Entessa Public License v1.0",
45919         true
45920     ],
45921     "EPL-1.0": [
45922         "Eclipse Public License 1.0",
45923         true
45924     ],
45925     "ErlPL-1.1": [
45926         "Erlang Public License v1.1",
45927         false
45928     ],
45929     "EUDatagrid": [
45930         "EU DataGrid Software License",
45931         true
45932     ],
45933     "EUPL-1.0": [
45934         "European Union Public License 1.0",
45935         false
45936     ],
45937     "EUPL-1.1": [
45938         "European Union Public License 1.1",
45939         true
45940     ],
45941     "Eurosym": [
45942         "Eurosym License",
45943         false
45944     ],
45945     "Fair": [
45946         "Fair License",
45947         true
45948     ],
45949     "Frameworx-1.0": [
45950         "Frameworx Open License 1.0",
45951         true
45952     ],
45953     "FreeImage": [
45954         "FreeImage Public License v1.0",
45955         false
45956     ],
45957     "FSFAP": [
45958         "FSF All Permissive License",
45959         false
45960     ],
45961     "FSFUL": [
45962         "FSF Unlimited License",
45963         false
45964     ],
45965     "FSFULLR": [
45966         "FSF Unlimited License (with License Retention)",
45967         false
45968     ],
45969     "FTL": [
45970         "Freetype Project License",
45971         false
45972     ],
45973     "GFDL-1.1": [
45974         "GNU Free Documentation License v1.1",
45975         false
45976     ],
45977     "GFDL-1.2": [
45978         "GNU Free Documentation License v1.2",
45979         false
45980     ],
45981     "GFDL-1.3": [
45982         "GNU Free Documentation License v1.3",
45983         false
45984     ],
45985     "Giftware": [
45986         "Giftware License",
45987         false
45988     ],
45989     "GL2PS": [
45990         "GL2PS License",
45991         false
45992     ],
45993     "Glide": [
45994         "3dfx Glide License",
45995         false
45996     ],
45997     "Glulxe": [
45998         "Glulxe License",
45999         false
46000     ],
46001     "gnuplot": [
46002         "gnuplot License",
46003         false
46004     ],
46005     "GPL-1.0": [
46006         "GNU General Public License v1.0 only",
46007         false
46008     ],
46009     "GPL-2.0": [
46010         "GNU General Public License v2.0 only",
46011         true
46012     ],
46013     "GPL-3.0": [
46014         "GNU General Public License v3.0 only",
46015         true
46016     ],
46017     "gSOAP-1.3b": [
46018         "gSOAP Public License v1.3b",
46019         false
46020     ],
46021     "HaskellReport": [
46022         "Haskell Language Report License",
46023         false
46024     ],
46025     "HPND": [
46026         "Historic Permission Notice and Disclaimer",
46027         true
46028     ],
46029     "IBM-pibs": [
46030         "IBM PowerPC Initialization and Boot Software",
46031         false
46032     ],
46033     "ICU": [
46034         "ICU License",
46035         false
46036     ],
46037     "IJG": [
46038         "Independent JPEG Group License",
46039         false
46040     ],
46041     "ImageMagick": [
46042         "ImageMagick License",
46043         false
46044     ],
46045     "iMatix": [
46046         "iMatix Standard Function Library Agreement",
46047         false
46048     ],
46049     "Imlib2": [
46050         "Imlib2 License",
46051         false
46052     ],
46053     "Info-ZIP": [
46054         "Info-ZIP License",
46055         false
46056     ],
46057     "Intel": [
46058         "Intel Open Source License",
46059         true
46060     ],
46061     "Intel-ACPI": [
46062         "Intel ACPI Software License Agreement",
46063         false
46064     ],
46065     "Interbase-1.0": [
46066         "Interbase Public License v1.0",
46067         false
46068     ],
46069     "IPA": [
46070         "IPA Font License",
46071         true
46072     ],
46073     "IPL-1.0": [
46074         "IBM Public License v1.0",
46075         true
46076     ],
46077     "ISC": [
46078         "ISC License",
46079         true
46080     ],
46081     "JasPer-2.0": [
46082         "JasPer License",
46083         false
46084     ],
46085     "JSON": [
46086         "JSON License",
46087         false
46088     ],
46089     "LAL-1.2": [
46090         "Licence Art Libre 1.2",
46091         false
46092     ],
46093     "LAL-1.3": [
46094         "Licence Art Libre 1.3",
46095         false
46096     ],
46097     "Latex2e": [
46098         "Latex2e License",
46099         false
46100     ],
46101     "Leptonica": [
46102         "Leptonica License",
46103         false
46104     ],
46105     "LGPL-2.0": [
46106         "GNU Library General Public License v2 only",
46107         true
46108     ],
46109     "LGPL-2.1": [
46110         "GNU Lesser General Public License v2.1 only",
46111         true
46112     ],
46113     "LGPL-3.0": [
46114         "GNU Lesser General Public License v3.0 only",
46115         true
46116     ],
46117     "LGPLLR": [
46118         "Lesser General Public License For Linguistic Resources",
46119         false
46120     ],
46121     "Libpng": [
46122         "libpng License",
46123         false
46124     ],
46125     "libtiff": [
46126         "libtiff License",
46127         false
46128     ],
46129     "LiLiQ-P-1.1": [
46130         "Licence Libre du Qu\u00e9bec \u2013 Permissive version 1.1",
46131         true
46132     ],
46133     "LiLiQ-R-1.1": [
46134         "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 version 1.1",
46135         true
46136     ],
46137     "LiLiQ-Rplus-1.1": [
46138         "Licence Libre du Qu\u00e9bec \u2013 R\u00e9ciprocit\u00e9 forte version 1.1",
46139         true
46140     ],
46141     "LPL-1.0": [
46142         "Lucent Public License Version 1.0",
46143         true
46144     ],
46145     "LPL-1.02": [
46146         "Lucent Public License v1.02",
46147         true
46148     ],
46149     "LPPL-1.0": [
46150         "LaTeX Project Public License v1.0",
46151         false
46152     ],
46153     "LPPL-1.1": [
46154         "LaTeX Project Public License v1.1",
46155         false
46156     ],
46157     "LPPL-1.2": [
46158         "LaTeX Project Public License v1.2",
46159         false
46160     ],
46161     "LPPL-1.3a": [
46162         "LaTeX Project Public License v1.3a",
46163         false
46164     ],
46165     "LPPL-1.3c": [
46166         "LaTeX Project Public License v1.3c",
46167         true
46168     ],
46169     "MakeIndex": [
46170         "MakeIndex License",
46171         false
46172     ],
46173     "MirOS": [
46174         "MirOS Licence",
46175         true
46176     ],
46177     "MIT": [
46178         "MIT License",
46179         true
46180     ],
46181     "MIT-advertising": [
46182         "Enlightenment License (e16)",
46183         false
46184     ],
46185     "MIT-CMU": [
46186         "CMU License",
46187         false
46188     ],
46189     "MIT-enna": [
46190         "enna License",
46191         false
46192     ],
46193     "MIT-feh": [
46194         "feh License",
46195         false
46196     ],
46197     "MITNFA": [
46198         "MIT +no-false-attribs license",
46199         false
46200     ],
46201     "Motosoto": [
46202         "Motosoto License",
46203         true
46204     ],
46205     "mpich2": [
46206         "mpich2 License",
46207         false
46208     ],
46209     "MPL-1.0": [
46210         "Mozilla Public License 1.0",
46211         true
46212     ],
46213     "MPL-1.1": [
46214         "Mozilla Public License 1.1",
46215         true
46216     ],
46217     "MPL-2.0": [
46218         "Mozilla Public License 2.0",
46219         true
46220     ],
46221     "MPL-2.0-no-copyleft-exception": [
46222         "Mozilla Public License 2.0 (no copyleft exception)",
46223         true
46224     ],
46225     "MS-PL": [
46226         "Microsoft Public License",
46227         true
46228     ],
46229     "MS-RL": [
46230         "Microsoft Reciprocal License",
46231         true
46232     ],
46233     "MTLL": [
46234         "Matrix Template Library License",
46235         false
46236     ],
46237     "Multics": [
46238         "Multics License",
46239         true
46240     ],
46241     "Mup": [
46242         "Mup License",
46243         false
46244     ],
46245     "NASA-1.3": [
46246         "NASA Open Source Agreement 1.3",
46247         true
46248     ],
46249     "Naumen": [
46250         "Naumen Public License",
46251         true
46252     ],
46253     "NBPL-1.0": [
46254         "Net Boolean Public License v1",
46255         false
46256     ],
46257     "NCSA": [
46258         "University of Illinois/NCSA Open Source License",
46259         true
46260     ],
46261     "Net-SNMP": [
46262         "Net-SNMP License",
46263         false
46264     ],
46265     "NetCDF": [
46266         "NetCDF license",
46267         false
46268     ],
46269     "Newsletr": [
46270         "Newsletr License",
46271         false
46272     ],
46273     "NGPL": [
46274         "Nethack General Public License",
46275         true
46276     ],
46277     "NLOD-1.0": [
46278         "Norwegian Licence for Open Government Data",
46279         false
46280     ],
46281     "NLPL": [
46282         "No Limit Public License",
46283         false
46284     ],
46285     "Nokia": [
46286         "Nokia Open Source License",
46287         true
46288     ],
46289     "NOSL": [
46290         "Netizen Open Source License",
46291         false
46292     ],
46293     "Noweb": [
46294         "Noweb License",
46295         false
46296     ],
46297     "NPL-1.0": [
46298         "Netscape Public License v1.0",
46299         false
46300     ],
46301     "NPL-1.1": [
46302         "Netscape Public License v1.1",
46303         false
46304     ],
46305     "NPOSL-3.0": [
46306         "Non-Profit Open Software License 3.0",
46307         true
46308     ],
46309     "NRL": [
46310         "NRL License",
46311         false
46312     ],
46313     "NTP": [
46314         "NTP License",
46315         true
46316     ],
46317     "Nunit": [
46318         "Nunit License",
46319         false
46320     ],
46321     "OCCT-PL": [
46322         "Open CASCADE Technology Public License",
46323         false
46324     ],
46325     "OCLC-2.0": [
46326         "OCLC Research Public License 2.0",
46327         true
46328     ],
46329     "ODbL-1.0": [
46330         "ODC Open Database License v1.0",
46331         false
46332     ],
46333     "OFL-1.0": [
46334         "SIL Open Font License 1.0",
46335         false
46336     ],
46337     "OFL-1.1": [
46338         "SIL Open Font License 1.1",
46339         true
46340     ],
46341     "OGTSL": [
46342         "Open Group Test Suite License",
46343         true
46344     ],
46345     "OLDAP-1.1": [
46346         "Open LDAP Public License v1.1",
46347         false
46348     ],
46349     "OLDAP-1.2": [
46350         "Open LDAP Public License v1.2",
46351         false
46352     ],
46353     "OLDAP-1.3": [
46354         "Open LDAP Public License v1.3",
46355         false
46356     ],
46357     "OLDAP-1.4": [
46358         "Open LDAP Public License v1.4",
46359         false
46360     ],
46361     "OLDAP-2.0": [
46362         "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)",
46363         false
46364     ],
46365     "OLDAP-2.0.1": [
46366         "Open LDAP Public License v2.0.1",
46367         false
46368     ],
46369     "OLDAP-2.1": [
46370         "Open LDAP Public License v2.1",
46371         false
46372     ],
46373     "OLDAP-2.2": [
46374         "Open LDAP Public License v2.2",
46375         false
46376     ],
46377     "OLDAP-2.2.1": [
46378         "Open LDAP Public License v2.2.1",
46379         false
46380     ],
46381     "OLDAP-2.2.2": [
46382         "Open LDAP Public License  2.2.2",
46383         false
46384     ],
46385     "OLDAP-2.3": [
46386         "Open LDAP Public License v2.3",
46387         false
46388     ],
46389     "OLDAP-2.4": [
46390         "Open LDAP Public License v2.4",
46391         false
46392     ],
46393     "OLDAP-2.5": [
46394         "Open LDAP Public License v2.5",
46395         false
46396     ],
46397     "OLDAP-2.6": [
46398         "Open LDAP Public License v2.6",
46399         false
46400     ],
46401     "OLDAP-2.7": [
46402         "Open LDAP Public License v2.7",
46403         false
46404     ],
46405     "OLDAP-2.8": [
46406         "Open LDAP Public License v2.8",
46407         false
46408     ],
46409     "OML": [
46410         "Open Market License",
46411         false
46412     ],
46413     "OpenSSL": [
46414         "OpenSSL License",
46415         false
46416     ],
46417     "OPL-1.0": [
46418         "Open Public License v1.0",
46419         false
46420     ],
46421     "OSET-PL-2.1": [
46422         "OSET Public License version 2.1",
46423         true
46424     ],
46425     "OSL-1.0": [
46426         "Open Software License 1.0",
46427         true
46428     ],
46429     "OSL-1.1": [
46430         "Open Software License 1.1",
46431         false
46432     ],
46433     "OSL-2.0": [
46434         "Open Software License 2.0",
46435         true
46436     ],
46437     "OSL-2.1": [
46438         "Open Software License 2.1",
46439         true
46440     ],
46441     "OSL-3.0": [
46442         "Open Software License 3.0",
46443         true
46444     ],
46445     "PDDL-1.0": [
46446         "ODC Public Domain Dedication & License 1.0",
46447         false
46448     ],
46449     "PHP-3.0": [
46450         "PHP License v3.0",
46451         true
46452     ],
46453     "PHP-3.01": [
46454         "PHP License v3.01",
46455         false
46456     ],
46457     "Plexus": [
46458         "Plexus Classworlds License",
46459         false
46460     ],
46461     "PostgreSQL": [
46462         "PostgreSQL License",
46463         true
46464     ],
46465     "psfrag": [
46466         "psfrag License",
46467         false
46468     ],
46469     "psutils": [
46470         "psutils License",
46471         false
46472     ],
46473     "Python-2.0": [
46474         "Python License 2.0",
46475         true
46476     ],
46477     "Qhull": [
46478         "Qhull License",
46479         false
46480     ],
46481     "QPL-1.0": [
46482         "Q Public License 1.0",
46483         true
46484     ],
46485     "Rdisc": [
46486         "Rdisc License",
46487         false
46488     ],
46489     "RHeCos-1.1": [
46490         "Red Hat eCos Public License v1.1",
46491         false
46492     ],
46493     "RPL-1.1": [
46494         "Reciprocal Public License 1.1",
46495         true
46496     ],
46497     "RPL-1.5": [
46498         "Reciprocal Public License 1.5",
46499         true
46500     ],
46501     "RPSL-1.0": [
46502         "RealNetworks Public Source License v1.0",
46503         true
46504     ],
46505     "RSA-MD": [
46506         "RSA Message-Digest License",
46507         false
46508     ],
46509     "RSCPL": [
46510         "Ricoh Source Code Public License",
46511         true
46512     ],
46513     "Ruby": [
46514         "Ruby License",
46515         false
46516     ],
46517     "SAX-PD": [
46518         "Sax Public Domain Notice",
46519         false
46520     ],
46521     "Saxpath": [
46522         "Saxpath License",
46523         false
46524     ],
46525     "SCEA": [
46526         "SCEA Shared Source License",
46527         false
46528     ],
46529     "Sendmail": [
46530         "Sendmail License",
46531         false
46532     ],
46533     "SGI-B-1.0": [
46534         "SGI Free Software License B v1.0",
46535         false
46536     ],
46537     "SGI-B-1.1": [
46538         "SGI Free Software License B v1.1",
46539         false
46540     ],
46541     "SGI-B-2.0": [
46542         "SGI Free Software License B v2.0",
46543         false
46544     ],
46545     "SimPL-2.0": [
46546         "Simple Public License 2.0",
46547         true
46548     ],
46549     "SISSL": [
46550         "Sun Industry Standards Source License v1.1",
46551         true
46552     ],
46553     "SISSL-1.2": [
46554         "Sun Industry Standards Source License v1.2",
46555         false
46556     ],
46557     "Sleepycat": [
46558         "Sleepycat License",
46559         true
46560     ],
46561     "SMLNJ": [
46562         "Standard ML of New Jersey License",
46563         false
46564     ],
46565     "SMPPL": [
46566         "Secure Messaging Protocol Public License",
46567         false
46568     ],
46569     "SNIA": [
46570         "SNIA Public License 1.1",
46571         false
46572     ],
46573     "Spencer-86": [
46574         "Spencer License 86",
46575         false
46576     ],
46577     "Spencer-94": [
46578         "Spencer License 94",
46579         false
46580     ],
46581     "Spencer-99": [
46582         "Spencer License 99",
46583         false
46584     ],
46585     "SPL-1.0": [
46586         "Sun Public License v1.0",
46587         true
46588     ],
46589     "SugarCRM-1.1.3": [
46590         "SugarCRM Public License v1.1.3",
46591         false
46592     ],
46593     "SWL": [
46594         "Scheme Widget Library (SWL) Software License Agreement",
46595         false
46596     ],
46597     "TCL": [
46598         "TCL/TK License",
46599         false
46600     ],
46601     "TCP-wrappers": [
46602         "TCP Wrappers License",
46603         false
46604     ],
46605     "TMate": [
46606         "TMate Open Source License",
46607         false
46608     ],
46609     "TORQUE-1.1": [
46610         "TORQUE v2.5+ Software License v1.1",
46611         false
46612     ],
46613     "TOSL": [
46614         "Trusster Open Source License",
46615         false
46616     ],
46617     "Unicode-DFS-2015": [
46618         "Unicode License Agreement - Data Files and Software (2015)",
46619         false
46620     ],
46621     "Unicode-DFS-2016": [
46622         "Unicode License Agreement - Data Files and Software (2016)",
46623         false
46624     ],
46625     "Unicode-TOU": [
46626         "Unicode Terms of Use",
46627         false
46628     ],
46629     "Unlicense": [
46630         "The Unlicense",
46631         false
46632     ],
46633     "UPL-1.0": [
46634         "Universal Permissive License v1.0",
46635         true
46636     ],
46637     "Vim": [
46638         "Vim License",
46639         false
46640     ],
46641     "VOSTROM": [
46642         "VOSTROM Public License for Open Source",
46643         false
46644     ],
46645     "VSL-1.0": [
46646         "Vovida Software License v1.0",
46647         true
46648     ],
46649     "W3C": [
46650         "W3C Software Notice and License (2002-12-31)",
46651         true
46652     ],
46653     "W3C-19980720": [
46654         "W3C Software Notice and License (1998-07-20)",
46655         false
46656     ],
46657     "W3C-20150513": [
46658         "W3C Software Notice and Document License (2015-05-13)",
46659         false
46660     ],
46661     "Watcom-1.0": [
46662         "Sybase Open Watcom Public License 1.0",
46663         true
46664     ],
46665     "Wsuipa": [
46666         "Wsuipa License",
46667         false
46668     ],
46669     "WTFPL": [
46670         "Do What The F*ck You Want To Public License",
46671         false
46672     ],
46673     "X11": [
46674         "X11 License",
46675         false
46676     ],
46677     "Xerox": [
46678         "Xerox License",
46679         false
46680     ],
46681     "XFree86-1.1": [
46682         "XFree86 License 1.1",
46683         false
46684     ],
46685     "xinetd": [
46686         "xinetd License",
46687         false
46688     ],
46689     "Xnet": [
46690         "X.Net License",
46691         true
46692     ],
46693     "xpp": [
46694         "XPP License",
46695         false
46696     ],
46697     "XSkat": [
46698         "XSkat License",
46699         false
46700     ],
46701     "YPL-1.0": [
46702         "Yahoo! Public License v1.0",
46703         false
46704     ],
46705     "YPL-1.1": [
46706         "Yahoo! Public License v1.1",
46707         false
46708     ],
46709     "Zed": [
46710         "Zed License",
46711         false
46712     ],
46713     "Zend-2.0": [
46714         "Zend License v2.0",
46715         false
46716     ],
46717     "Zimbra-1.3": [
46718         "Zimbra Public License v1.3",
46719         false
46720     ],
46721     "Zimbra-1.4": [
46722         "Zimbra Public License v1.4",
46723         false
46724     ],
46725     "Zlib": [
46726         "zlib License",
46727         true
46728     ],
46729     "zlib-acknowledgement": [
46730         "zlib/libpng License with Acknowledgement",
46731         false
46732     ],
46733     "ZPL-1.1": [
46734         "Zope Public License 1.1",
46735         false
46736     ],
46737     "ZPL-2.0": [
46738         "Zope Public License 2.0",
46739         true
46740     ],
46741     "ZPL-2.1": [
46742         "Zope Public License 2.1",
46743         false
46744     ]
46745 }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
46746 $\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
46747 \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
46748 \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
46749 \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
46750 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
46751 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
46752 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
46753   <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">\r
46754     <security>\r
46755       <requestedPrivileges>\r
46756         <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>\r
46757       </requestedPrivileges>\r
46758     </security>\r
46759   </trustInfo>\r
46760   <dependency>\r
46761     <dependentAssembly>\r
46762       <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>\r
46763     </dependentAssembly>\r
46764   </dependency>\r
46765 </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
46766
46767
46768
46769
46770
46771
46772
46773
46774
46775
46776 namespace Symfony\Component\Console;
46777
46778 use Symfony\Component\Console\Descriptor\TextDescriptor;
46779 use Symfony\Component\Console\Descriptor\XmlDescriptor;
46780 use Symfony\Component\Console\Exception\ExceptionInterface;
46781 use Symfony\Component\Console\Formatter\OutputFormatter;
46782 use Symfony\Component\Console\Helper\DebugFormatterHelper;
46783 use Symfony\Component\Console\Helper\Helper;
46784 use Symfony\Component\Console\Helper\ProcessHelper;
46785 use Symfony\Component\Console\Helper\QuestionHelper;
46786 use Symfony\Component\Console\Input\InputInterface;
46787 use Symfony\Component\Console\Input\ArgvInput;
46788 use Symfony\Component\Console\Input\ArrayInput;
46789 use Symfony\Component\Console\Input\InputDefinition;
46790 use Symfony\Component\Console\Input\InputOption;
46791 use Symfony\Component\Console\Input\InputArgument;
46792 use Symfony\Component\Console\Input\InputAwareInterface;
46793 use Symfony\Component\Console\Output\BufferedOutput;
46794 use Symfony\Component\Console\Output\OutputInterface;
46795 use Symfony\Component\Console\Output\ConsoleOutput;
46796 use Symfony\Component\Console\Output\ConsoleOutputInterface;
46797 use Symfony\Component\Console\Command\Command;
46798 use Symfony\Component\Console\Command\HelpCommand;
46799 use Symfony\Component\Console\Command\ListCommand;
46800 use Symfony\Component\Console\Helper\HelperSet;
46801 use Symfony\Component\Console\Helper\FormatterHelper;
46802 use Symfony\Component\Console\Helper\DialogHelper;
46803 use Symfony\Component\Console\Helper\ProgressHelper;
46804 use Symfony\Component\Console\Helper\TableHelper;
46805 use Symfony\Component\Console\Event\ConsoleCommandEvent;
46806 use Symfony\Component\Console\Event\ConsoleExceptionEvent;
46807 use Symfony\Component\Console\Event\ConsoleTerminateEvent;
46808 use Symfony\Component\Console\Exception\CommandNotFoundException;
46809 use Symfony\Component\Console\Exception\LogicException;
46810 use Symfony\Component\Debug\Exception\FatalThrowableError;
46811 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
46812
46813
46814
46815
46816
46817
46818
46819
46820
46821
46822
46823
46824
46825
46826
46827
46828 class Application
46829 {
46830 private $commands = array();
46831 private $wantHelps = false;
46832 private $runningCommand;
46833 private $name;
46834 private $version;
46835 private $catchExceptions = true;
46836 private $autoExit = true;
46837 private $definition;
46838 private $helperSet;
46839 private $dispatcher;
46840 private $terminalDimensions;
46841 private $defaultCommand;
46842
46843
46844
46845
46846
46847
46848
46849 public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
46850 {
46851 $this->name = $name;
46852 $this->version = $version;
46853 $this->defaultCommand = 'list';
46854 $this->helperSet = $this->getDefaultHelperSet();
46855 $this->definition = $this->getDefaultInputDefinition();
46856
46857 foreach ($this->getDefaultCommands() as $command) {
46858 $this->add($command);
46859 }
46860 }
46861
46862 public function setDispatcher(EventDispatcherInterface $dispatcher)
46863 {
46864 $this->dispatcher = $dispatcher;
46865 }
46866
46867
46868
46869
46870
46871
46872
46873
46874
46875
46876
46877 public function run(InputInterface $input = null, OutputInterface $output = null)
46878 {
46879 if (null === $input) {
46880 $input = new ArgvInput();
46881 }
46882
46883 if (null === $output) {
46884 $output = new ConsoleOutput();
46885 }
46886
46887 $this->configureIO($input, $output);
46888
46889 try {
46890 $e = null;
46891 $exitCode = $this->doRun($input, $output);
46892 } catch (\Exception $x) {
46893 $e = $x;
46894 } catch (\Throwable $x) {
46895 $e = new FatalThrowableError($x);
46896 }
46897
46898 if (null !== $e) {
46899 if (!$this->catchExceptions || !$x instanceof \Exception) {
46900 throw $x;
46901 }
46902
46903 if ($output instanceof ConsoleOutputInterface) {
46904 $this->renderException($e, $output->getErrorOutput());
46905 } else {
46906 $this->renderException($e, $output);
46907 }
46908
46909 $exitCode = $e->getCode();
46910 if (is_numeric($exitCode)) {
46911 $exitCode = (int) $exitCode;
46912 if (0 === $exitCode) {
46913 $exitCode = 1;
46914 }
46915 } else {
46916 $exitCode = 1;
46917 }
46918 }
46919
46920 if ($this->autoExit) {
46921 if ($exitCode > 255) {
46922 $exitCode = 255;
46923 }
46924
46925 exit($exitCode);
46926 }
46927
46928 return $exitCode;
46929 }
46930
46931
46932
46933
46934
46935
46936
46937
46938
46939 public function doRun(InputInterface $input, OutputInterface $output)
46940 {
46941 if (true === $input->hasParameterOption(array('--version', '-V'))) {
46942 $output->writeln($this->getLongVersion());
46943
46944 return 0;
46945 }
46946
46947 $name = $this->getCommandName($input);
46948 if (true === $input->hasParameterOption(array('--help', '-h'))) {
46949 if (!$name) {
46950 $name = 'help';
46951 $input = new ArrayInput(array('command' => 'help'));
46952 } else {
46953 $this->wantHelps = true;
46954 }
46955 }
46956
46957 if (!$name) {
46958 $name = $this->defaultCommand;
46959 $this->definition->setArguments(array_merge(
46960 $this->definition->getArguments(),
46961 array(
46962 'command' => new InputArgument('command', InputArgument::OPTIONAL, $this->definition->getArgument('command')->getDescription(), $name),
46963 )
46964 ));
46965 }
46966
46967 $this->runningCommand = null;
46968
46969  $command = $this->find($name);
46970
46971 $this->runningCommand = $command;
46972 $exitCode = $this->doRunCommand($command, $input, $output);
46973 $this->runningCommand = null;
46974
46975 return $exitCode;
46976 }
46977
46978
46979
46980
46981
46982
46983 public function setHelperSet(HelperSet $helperSet)
46984 {
46985 $this->helperSet = $helperSet;
46986 }
46987
46988
46989
46990
46991
46992
46993 public function getHelperSet()
46994 {
46995 return $this->helperSet;
46996 }
46997
46998
46999
47000
47001
47002
47003 public function setDefinition(InputDefinition $definition)
47004 {
47005 $this->definition = $definition;
47006 }
47007
47008
47009
47010
47011
47012
47013 public function getDefinition()
47014 {
47015 return $this->definition;
47016 }
47017
47018
47019
47020
47021
47022
47023 public function getHelp()
47024 {
47025 return $this->getLongVersion();
47026 }
47027
47028
47029
47030
47031
47032
47033 public function setCatchExceptions($boolean)
47034 {
47035 $this->catchExceptions = (bool) $boolean;
47036 }
47037
47038
47039
47040
47041
47042
47043 public function setAutoExit($boolean)
47044 {
47045 $this->autoExit = (bool) $boolean;
47046 }
47047
47048
47049
47050
47051
47052
47053 public function getName()
47054 {
47055 return $this->name;
47056 }
47057
47058
47059
47060
47061
47062
47063 public function setName($name)
47064 {
47065 $this->name = $name;
47066 }
47067
47068
47069
47070
47071
47072
47073 public function getVersion()
47074 {
47075 return $this->version;
47076 }
47077
47078
47079
47080
47081
47082
47083 public function setVersion($version)
47084 {
47085 $this->version = $version;
47086 }
47087
47088
47089
47090
47091
47092
47093 public function getLongVersion()
47094 {
47095 if ('UNKNOWN' !== $this->getName()) {
47096 if ('UNKNOWN' !== $this->getVersion()) {
47097 return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion());
47098 }
47099
47100 return sprintf('<info>%s</info>', $this->getName());
47101 }
47102
47103 return '<info>Console Tool</info>';
47104 }
47105
47106
47107
47108
47109
47110
47111
47112
47113 public function register($name)
47114 {
47115 return $this->add(new Command($name));
47116 }
47117
47118
47119
47120
47121
47122
47123
47124
47125 public function addCommands(array $commands)
47126 {
47127 foreach ($commands as $command) {
47128 $this->add($command);
47129 }
47130 }
47131
47132
47133
47134
47135
47136
47137
47138
47139
47140
47141
47142 public function add(Command $command)
47143 {
47144 $command->setApplication($this);
47145
47146 if (!$command->isEnabled()) {
47147 $command->setApplication(null);
47148
47149 return;
47150 }
47151
47152 if (null === $command->getDefinition()) {
47153 throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command)));
47154 }
47155
47156 $this->commands[$command->getName()] = $command;
47157
47158 foreach ($command->getAliases() as $alias) {
47159 $this->commands[$alias] = $command;
47160 }
47161
47162 return $command;
47163 }
47164
47165
47166
47167
47168
47169
47170
47171
47172
47173
47174 public function get($name)
47175 {
47176 if (!isset($this->commands[$name])) {
47177 throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name));
47178 }
47179
47180 $command = $this->commands[$name];
47181
47182 if ($this->wantHelps) {
47183 $this->wantHelps = false;
47184
47185 $helpCommand = $this->get('help');
47186 $helpCommand->setCommand($command);
47187
47188 return $helpCommand;
47189 }
47190
47191 return $command;
47192 }
47193
47194
47195
47196
47197
47198
47199
47200
47201 public function has($name)
47202 {
47203 return isset($this->commands[$name]);
47204 }
47205
47206
47207
47208
47209
47210
47211
47212
47213 public function getNamespaces()
47214 {
47215 $namespaces = array();
47216 foreach ($this->all() as $command) {
47217 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($command->getName()));
47218
47219 foreach ($command->getAliases() as $alias) {
47220 $namespaces = array_merge($namespaces, $this->extractAllNamespaces($alias));
47221 }
47222 }
47223
47224 return array_values(array_unique(array_filter($namespaces)));
47225 }
47226
47227
47228
47229
47230
47231
47232
47233
47234
47235
47236 public function findNamespace($namespace)
47237 {
47238 $allNamespaces = $this->getNamespaces();
47239 $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $namespace);
47240 $namespaces = preg_grep('{^'.$expr.'}', $allNamespaces);
47241
47242 if (empty($namespaces)) {
47243 $message = sprintf('There are no commands defined in the "%s" namespace.', $namespace);
47244
47245 if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
47246 if (1 == count($alternatives)) {
47247 $message .= "\n\nDid you mean this?\n    ";
47248 } else {
47249 $message .= "\n\nDid you mean one of these?\n    ";
47250 }
47251
47252 $message .= implode("\n    ", $alternatives);
47253 }
47254
47255 throw new CommandNotFoundException($message, $alternatives);
47256 }
47257
47258 $exact = in_array($namespace, $namespaces, true);
47259 if (count($namespaces) > 1 && !$exact) {
47260 throw new CommandNotFoundException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions(array_values($namespaces))), array_values($namespaces));
47261 }
47262
47263 return $exact ? $namespace : reset($namespaces);
47264 }
47265
47266
47267
47268
47269
47270
47271
47272
47273
47274
47275
47276
47277
47278 public function find($name)
47279 {
47280 $allCommands = array_keys($this->commands);
47281 $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name);
47282 $commands = preg_grep('{^'.$expr.'}', $allCommands);
47283
47284 if (empty($commands) || count(preg_grep('{^'.$expr.'$}', $commands)) < 1) {
47285 if (false !== $pos = strrpos($name, ':')) {
47286
47287  $this->findNamespace(substr($name, 0, $pos));
47288 }
47289
47290 $message = sprintf('Command "%s" is not defined.', $name);
47291
47292 if ($alternatives = $this->findAlternatives($name, $allCommands)) {
47293 if (1 == count($alternatives)) {
47294 $message .= "\n\nDid you mean this?\n    ";
47295 } else {
47296 $message .= "\n\nDid you mean one of these?\n    ";
47297 }
47298 $message .= implode("\n    ", $alternatives);
47299 }
47300
47301 throw new CommandNotFoundException($message, $alternatives);
47302 }
47303
47304
47305  if (count($commands) > 1) {
47306 $commandList = $this->commands;
47307 $commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) {
47308 $commandName = $commandList[$nameOrAlias]->getName();
47309
47310 return $commandName === $nameOrAlias || !in_array($commandName, $commands);
47311 });
47312 }
47313
47314 $exact = in_array($name, $commands, true);
47315 if (count($commands) > 1 && !$exact) {
47316 $suggestions = $this->getAbbreviationSuggestions(array_values($commands));
47317
47318 throw new CommandNotFoundException(sprintf('Command "%s" is ambiguous (%s).', $name, $suggestions), array_values($commands));
47319 }
47320
47321 return $this->get($exact ? $name : reset($commands));
47322 }
47323
47324
47325
47326
47327
47328
47329
47330
47331
47332
47333 public function all($namespace = null)
47334 {
47335 if (null === $namespace) {
47336 return $this->commands;
47337 }
47338
47339 $commands = array();
47340 foreach ($this->commands as $name => $command) {
47341 if ($namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) {
47342 $commands[$name] = $command;
47343 }
47344 }
47345
47346 return $commands;
47347 }
47348
47349
47350
47351
47352
47353
47354
47355
47356 public static function getAbbreviations($names)
47357 {
47358 $abbrevs = array();
47359 foreach ($names as $name) {
47360 for ($len = strlen($name); $len > 0; --$len) {
47361 $abbrev = substr($name, 0, $len);
47362 $abbrevs[$abbrev][] = $name;
47363 }
47364 }
47365
47366 return $abbrevs;
47367 }
47368
47369
47370
47371
47372
47373
47374
47375
47376
47377
47378
47379 public function asText($namespace = null, $raw = false)
47380 {
47381 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
47382
47383 $descriptor = new TextDescriptor();
47384 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, !$raw);
47385 $descriptor->describe($output, $this, array('namespace' => $namespace, 'raw_output' => true));
47386
47387 return $output->fetch();
47388 }
47389
47390
47391
47392
47393
47394
47395
47396
47397
47398
47399
47400 public function asXml($namespace = null, $asDom = false)
47401 {
47402 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
47403
47404 $descriptor = new XmlDescriptor();
47405
47406 if ($asDom) {
47407 return $descriptor->getApplicationDocument($this, $namespace);
47408 }
47409
47410 $output = new BufferedOutput();
47411 $descriptor->describe($output, $this, array('namespace' => $namespace));
47412
47413 return $output->fetch();
47414 }
47415
47416
47417
47418
47419
47420
47421
47422 public function renderException($e, $output)
47423 {
47424 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
47425
47426 do {
47427 $title = sprintf('  [%s]  ', get_class($e));
47428
47429 $len = Helper::strlen($title);
47430
47431 $width = $this->getTerminalWidth() ? $this->getTerminalWidth() - 1 : PHP_INT_MAX;
47432
47433  if (defined('HHVM_VERSION') && $width > 1 << 31) {
47434 $width = 1 << 31;
47435 }
47436 $lines = array();
47437 foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) {
47438 foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
47439
47440  $lineLength = Helper::strlen($line) + 4;
47441 $lines[] = array($line, $lineLength);
47442
47443 $len = max($lineLength, $len);
47444 }
47445 }
47446
47447 $messages = array();
47448 $messages[] = $emptyLine = sprintf('<error>%s</error>', str_repeat(' ', $len));
47449 $messages[] = sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - Helper::strlen($title))));
47450 foreach ($lines as $line) {
47451 $messages[] = sprintf('<error>  %s  %s</error>', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1]));
47452 }
47453 $messages[] = $emptyLine;
47454 $messages[] = '';
47455
47456 $output->writeln($messages, OutputInterface::VERBOSITY_QUIET);
47457
47458 if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
47459 $output->writeln('<comment>Exception trace:</comment>', OutputInterface::VERBOSITY_QUIET);
47460
47461
47462  $trace = $e->getTrace();
47463 array_unshift($trace, array(
47464 'function' => '',
47465 'file' => $e->getFile() !== null ? $e->getFile() : 'n/a',
47466 'line' => $e->getLine() !== null ? $e->getLine() : 'n/a',
47467 'args' => array(),
47468 ));
47469
47470 for ($i = 0, $count = count($trace); $i < $count; ++$i) {
47471 $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
47472 $type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
47473 $function = $trace[$i]['function'];
47474 $file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
47475 $line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';
47476
47477 $output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line), OutputInterface::VERBOSITY_QUIET);
47478 }
47479
47480 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
47481 }
47482 } while ($e = $e->getPrevious());
47483
47484 if (null !== $this->runningCommand) {
47485 $output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET);
47486 $output->writeln('', OutputInterface::VERBOSITY_QUIET);
47487 }
47488 }
47489
47490
47491
47492
47493
47494
47495 protected function getTerminalWidth()
47496 {
47497 $dimensions = $this->getTerminalDimensions();
47498
47499 return $dimensions[0];
47500 }
47501
47502
47503
47504
47505
47506
47507 protected function getTerminalHeight()
47508 {
47509 $dimensions = $this->getTerminalDimensions();
47510
47511 return $dimensions[1];
47512 }
47513
47514
47515
47516
47517
47518
47519 public function getTerminalDimensions()
47520 {
47521 if ($this->terminalDimensions) {
47522 return $this->terminalDimensions;
47523 }
47524
47525 if ('\\' === DIRECTORY_SEPARATOR) {
47526
47527  if (preg_match('/^(\d+)x\d+ \(\d+x(\d+)\)$/', trim(getenv('ANSICON')), $matches)) {
47528 return array((int) $matches[1], (int) $matches[2]);
47529 }
47530
47531  if (preg_match('/^(\d+)x(\d+)$/', $this->getConsoleMode(), $matches)) {
47532 return array((int) $matches[1], (int) $matches[2]);
47533 }
47534 }
47535
47536 if ($sttyString = $this->getSttyColumns()) {
47537
47538  if (preg_match('/rows.(\d+);.columns.(\d+);/i', $sttyString, $matches)) {
47539 return array((int) $matches[2], (int) $matches[1]);
47540 }
47541
47542  if (preg_match('/;.(\d+).rows;.(\d+).columns/i', $sttyString, $matches)) {
47543 return array((int) $matches[2], (int) $matches[1]);
47544 }
47545 }
47546
47547 return array(null, null);
47548 }
47549
47550
47551
47552
47553
47554
47555
47556
47557
47558
47559
47560 public function setTerminalDimensions($width, $height)
47561 {
47562 $this->terminalDimensions = array($width, $height);
47563
47564 return $this;
47565 }
47566
47567
47568
47569
47570
47571
47572
47573 protected function configureIO(InputInterface $input, OutputInterface $output)
47574 {
47575 if (true === $input->hasParameterOption(array('--ansi'))) {
47576 $output->setDecorated(true);
47577 } elseif (true === $input->hasParameterOption(array('--no-ansi'))) {
47578 $output->setDecorated(false);
47579 }
47580
47581 if (true === $input->hasParameterOption(array('--no-interaction', '-n'))) {
47582 $input->setInteractive(false);
47583 } elseif (function_exists('posix_isatty') && $this->getHelperSet()->has('question')) {
47584 $inputStream = $this->getHelperSet()->get('question')->getInputStream();
47585 if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) {
47586 $input->setInteractive(false);
47587 }
47588 }
47589
47590 if (true === $input->hasParameterOption(array('--quiet', '-q'))) {
47591 $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
47592 $input->setInteractive(false);
47593 } else {
47594 if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) {
47595 $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
47596 } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || $input->getParameterOption('--verbose') === 2) {
47597 $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
47598 } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) {
47599 $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
47600 }
47601 }
47602 }
47603
47604
47605
47606
47607
47608
47609
47610
47611
47612
47613
47614
47615
47616 protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
47617 {
47618 foreach ($command->getHelperSet() as $helper) {
47619 if ($helper instanceof InputAwareInterface) {
47620 $helper->setInput($input);
47621 }
47622 }
47623
47624 if (null === $this->dispatcher) {
47625 return $command->run($input, $output);
47626 }
47627
47628
47629  try {
47630 $command->mergeApplicationDefinition();
47631 $input->bind($command->getDefinition());
47632 } catch (ExceptionInterface $e) {
47633
47634  }
47635
47636 $event = new ConsoleCommandEvent($command, $input, $output);
47637 $e = null;
47638
47639 try {
47640 $this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
47641
47642 if ($event->commandShouldRun()) {
47643 $exitCode = $command->run($input, $output);
47644 } else {
47645 $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
47646 }
47647 } catch (\Exception $e) {
47648 } catch (\Throwable $e) {
47649 }
47650 if (null !== $e) {
47651 $x = $e instanceof \Exception ? $e : new FatalThrowableError($e);
47652 $event = new ConsoleExceptionEvent($command, $input, $output, $x, $x->getCode());
47653 $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
47654
47655 if ($x !== $event->getException()) {
47656 $e = $event->getException();
47657 }
47658 $exitCode = $e->getCode();
47659 }
47660
47661 $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
47662 $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
47663
47664 if (null !== $e) {
47665 throw $e;
47666 }
47667
47668 return $event->getExitCode();
47669 }
47670
47671
47672
47673
47674
47675
47676
47677
47678 protected function getCommandName(InputInterface $input)
47679 {
47680 return $input->getFirstArgument();
47681 }
47682
47683
47684
47685
47686
47687
47688 protected function getDefaultInputDefinition()
47689 {
47690 return new InputDefinition(array(
47691 new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
47692
47693 new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display this help message'),
47694 new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'),
47695 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'),
47696 new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'),
47697 new InputOption('--ansi', '', InputOption::VALUE_NONE, 'Force ANSI output'),
47698 new InputOption('--no-ansi', '', InputOption::VALUE_NONE, 'Disable ANSI output'),
47699 new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question'),
47700 ));
47701 }
47702
47703
47704
47705
47706
47707
47708 protected function getDefaultCommands()
47709 {
47710 return array(new HelpCommand(), new ListCommand());
47711 }
47712
47713
47714
47715
47716
47717
47718 protected function getDefaultHelperSet()
47719 {
47720 return new HelperSet(array(
47721 new FormatterHelper(),
47722 new DialogHelper(false),
47723 new ProgressHelper(false),
47724 new TableHelper(false),
47725 new DebugFormatterHelper(),
47726 new ProcessHelper(),
47727 new QuestionHelper(),
47728 ));
47729 }
47730
47731
47732
47733
47734
47735
47736 private function getSttyColumns()
47737 {
47738 if (!function_exists('proc_open')) {
47739 return;
47740 }
47741
47742 $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
47743 $process = proc_open('stty -a | grep columns', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
47744 if (is_resource($process)) {
47745 $info = stream_get_contents($pipes[1]);
47746 fclose($pipes[1]);
47747 fclose($pipes[2]);
47748 proc_close($process);
47749
47750 return $info;
47751 }
47752 }
47753
47754
47755
47756
47757
47758
47759 private function getConsoleMode()
47760 {
47761 if (!function_exists('proc_open')) {
47762 return;
47763 }
47764
47765 $descriptorspec = array(1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
47766 $process = proc_open('mode CON', $descriptorspec, $pipes, null, null, array('suppress_errors' => true));
47767 if (is_resource($process)) {
47768 $info = stream_get_contents($pipes[1]);
47769 fclose($pipes[1]);
47770 fclose($pipes[2]);
47771 proc_close($process);
47772
47773 if (preg_match('/--------+\r?\n.+?(\d+)\r?\n.+?(\d+)\r?\n/', $info, $matches)) {
47774 return $matches[2].'x'.$matches[1];
47775 }
47776 }
47777 }
47778
47779
47780
47781
47782
47783
47784
47785
47786 private function getAbbreviationSuggestions($abbrevs)
47787 {
47788 return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : '');
47789 }
47790
47791
47792
47793
47794
47795
47796
47797
47798
47799
47800
47801 public function extractNamespace($name, $limit = null)
47802 {
47803 $parts = explode(':', $name);
47804 array_pop($parts);
47805
47806 return implode(':', null === $limit ? $parts : array_slice($parts, 0, $limit));
47807 }
47808
47809
47810
47811
47812
47813
47814
47815
47816
47817
47818 private function findAlternatives($name, $collection)
47819 {
47820 $threshold = 1e3;
47821 $alternatives = array();
47822
47823 $collectionParts = array();
47824 foreach ($collection as $item) {
47825 $collectionParts[$item] = explode(':', $item);
47826 }
47827
47828 foreach (explode(':', $name) as $i => $subname) {
47829 foreach ($collectionParts as $collectionName => $parts) {
47830 $exists = isset($alternatives[$collectionName]);
47831 if (!isset($parts[$i]) && $exists) {
47832 $alternatives[$collectionName] += $threshold;
47833 continue;
47834 } elseif (!isset($parts[$i])) {
47835 continue;
47836 }
47837
47838 $lev = levenshtein($subname, $parts[$i]);
47839 if ($lev <= strlen($subname) / 3 || '' !== $subname && false !== strpos($parts[$i], $subname)) {
47840 $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
47841 } elseif ($exists) {
47842 $alternatives[$collectionName] += $threshold;
47843 }
47844 }
47845 }
47846
47847 foreach ($collection as $item) {
47848 $lev = levenshtein($name, $item);
47849 if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
47850 $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
47851 }
47852 }
47853
47854 $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; });
47855 asort($alternatives);
47856
47857 return array_keys($alternatives);
47858 }
47859
47860
47861
47862
47863
47864
47865 public function setDefaultCommand($commandName)
47866 {
47867 $this->defaultCommand = $commandName;
47868 }
47869
47870 private function splitStringByWidth($string, $width)
47871 {
47872
47873  
47874  
47875  if (false === $encoding = mb_detect_encoding($string, null, true)) {
47876 return str_split($string, $width);
47877 }
47878
47879 $utf8String = mb_convert_encoding($string, 'utf8', $encoding);
47880 $lines = array();
47881 $line = '';
47882 foreach (preg_split('//u', $utf8String) as $char) {
47883
47884  if (mb_strwidth($line.$char, 'utf8') <= $width) {
47885 $line .= $char;
47886 continue;
47887 }
47888
47889  $lines[] = str_pad($line, $width);
47890 $line = $char;
47891 }
47892 if ('' !== $line) {
47893 $lines[] = count($lines) ? str_pad($line, $width) : $line;
47894 }
47895
47896 mb_convert_variables($encoding, 'utf8', $lines);
47897
47898 return $lines;
47899 }
47900
47901
47902
47903
47904
47905
47906
47907
47908 private function extractAllNamespaces($name)
47909 {
47910
47911  $parts = explode(':', $name, -1);
47912 $namespaces = array();
47913
47914 foreach ($parts as $part) {
47915 if (count($namespaces)) {
47916 $namespaces[] = end($namespaces).':'.$part;
47917 } else {
47918 $namespaces[] = $part;
47919 }
47920 }
47921
47922 return $namespaces;
47923 }
47924 }
47925 <?php
47926
47927
47928
47929
47930
47931
47932
47933
47934
47935
47936 namespace Symfony\Component\Console\Command;
47937
47938 use Symfony\Component\Console\Descriptor\TextDescriptor;
47939 use Symfony\Component\Console\Descriptor\XmlDescriptor;
47940 use Symfony\Component\Console\Exception\ExceptionInterface;
47941 use Symfony\Component\Console\Input\InputDefinition;
47942 use Symfony\Component\Console\Input\InputOption;
47943 use Symfony\Component\Console\Input\InputArgument;
47944 use Symfony\Component\Console\Input\InputInterface;
47945 use Symfony\Component\Console\Output\BufferedOutput;
47946 use Symfony\Component\Console\Output\OutputInterface;
47947 use Symfony\Component\Console\Application;
47948 use Symfony\Component\Console\Helper\HelperSet;
47949 use Symfony\Component\Console\Exception\InvalidArgumentException;
47950 use Symfony\Component\Console\Exception\LogicException;
47951
47952
47953
47954
47955
47956
47957 class Command
47958 {
47959 private $application;
47960 private $name;
47961 private $processTitle;
47962 private $aliases = array();
47963 private $definition;
47964 private $help;
47965 private $description;
47966 private $ignoreValidationErrors = false;
47967 private $applicationDefinitionMerged = false;
47968 private $applicationDefinitionMergedWithArgs = false;
47969 private $code;
47970 private $synopsis = array();
47971 private $usages = array();
47972 private $helperSet;
47973
47974
47975
47976
47977
47978
47979
47980
47981 public function __construct($name = null)
47982 {
47983 $this->definition = new InputDefinition();
47984
47985 if (null !== $name) {
47986 $this->setName($name);
47987 }
47988
47989 $this->configure();
47990
47991 if (!$this->name) {
47992 throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($this)));
47993 }
47994 }
47995
47996
47997
47998
47999
48000
48001 public function ignoreValidationErrors()
48002 {
48003 $this->ignoreValidationErrors = true;
48004 }
48005
48006
48007
48008
48009
48010
48011 public function setApplication(Application $application = null)
48012 {
48013 $this->application = $application;
48014 if ($application) {
48015 $this->setHelperSet($application->getHelperSet());
48016 } else {
48017 $this->helperSet = null;
48018 }
48019 }
48020
48021
48022
48023
48024
48025
48026 public function setHelperSet(HelperSet $helperSet)
48027 {
48028 $this->helperSet = $helperSet;
48029 }
48030
48031
48032
48033
48034
48035
48036 public function getHelperSet()
48037 {
48038 return $this->helperSet;
48039 }
48040
48041
48042
48043
48044
48045
48046 public function getApplication()
48047 {
48048 return $this->application;
48049 }
48050
48051
48052
48053
48054
48055
48056
48057
48058
48059 public function isEnabled()
48060 {
48061 return true;
48062 }
48063
48064
48065
48066
48067 protected function configure()
48068 {
48069 }
48070
48071
48072
48073
48074
48075
48076
48077
48078
48079
48080
48081
48082
48083
48084
48085
48086
48087
48088 protected function execute(InputInterface $input, OutputInterface $output)
48089 {
48090 throw new LogicException('You must override the execute() method in the concrete command class.');
48091 }
48092
48093
48094
48095
48096
48097
48098
48099
48100
48101
48102
48103 protected function interact(InputInterface $input, OutputInterface $output)
48104 {
48105 }
48106
48107
48108
48109
48110
48111
48112
48113
48114
48115
48116 protected function initialize(InputInterface $input, OutputInterface $output)
48117 {
48118 }
48119
48120
48121
48122
48123
48124
48125
48126
48127
48128
48129
48130
48131
48132
48133
48134
48135
48136
48137 public function run(InputInterface $input, OutputInterface $output)
48138 {
48139
48140  $this->getSynopsis(true);
48141 $this->getSynopsis(false);
48142
48143
48144  $this->mergeApplicationDefinition();
48145
48146
48147  try {
48148 $input->bind($this->definition);
48149 } catch (ExceptionInterface $e) {
48150 if (!$this->ignoreValidationErrors) {
48151 throw $e;
48152 }
48153 }
48154
48155 $this->initialize($input, $output);
48156
48157 if (null !== $this->processTitle) {
48158 if (function_exists('cli_set_process_title')) {
48159 if (false === @cli_set_process_title($this->processTitle)) {
48160 if ('Darwin' === PHP_OS) {
48161 $output->writeln('<comment>Running "cli_get_process_title" as an unprivileged user is not supported on MacOS.</comment>');
48162 } else {
48163 $error = error_get_last();
48164 trigger_error($error['message'], E_USER_WARNING);
48165 }
48166 }
48167 } elseif (function_exists('setproctitle')) {
48168 setproctitle($this->processTitle);
48169 } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
48170 $output->writeln('<comment>Install the proctitle PECL to be able to change the process title.</comment>');
48171 }
48172 }
48173
48174 if ($input->isInteractive()) {
48175 $this->interact($input, $output);
48176 }
48177
48178
48179  
48180  
48181  if ($input->hasArgument('command') && null === $input->getArgument('command')) {
48182 $input->setArgument('command', $this->getName());
48183 }
48184
48185 $input->validate();
48186
48187 if ($this->code) {
48188 $statusCode = call_user_func($this->code, $input, $output);
48189 } else {
48190 $statusCode = $this->execute($input, $output);
48191 }
48192
48193 return is_numeric($statusCode) ? (int) $statusCode : 0;
48194 }
48195
48196
48197
48198
48199
48200
48201
48202
48203
48204
48205
48206
48207
48208
48209
48210 public function setCode($code)
48211 {
48212 if (!is_callable($code)) {
48213 throw new InvalidArgumentException('Invalid callable provided to Command::setCode.');
48214 }
48215
48216 if (PHP_VERSION_ID >= 50400 && $code instanceof \Closure) {
48217 $r = new \ReflectionFunction($code);
48218 if (null === $r->getClosureThis()) {
48219 if (PHP_VERSION_ID < 70000) {
48220
48221  
48222  
48223  
48224  $code = @\Closure::bind($code, $this);
48225 } else {
48226 $code = \Closure::bind($code, $this);
48227 }
48228 }
48229 }
48230
48231 $this->code = $code;
48232
48233 return $this;
48234 }
48235
48236
48237
48238
48239
48240
48241
48242
48243 public function mergeApplicationDefinition($mergeArgs = true)
48244 {
48245 if (null === $this->application || (true === $this->applicationDefinitionMerged && ($this->applicationDefinitionMergedWithArgs || !$mergeArgs))) {
48246 return;
48247 }
48248
48249 $this->definition->addOptions($this->application->getDefinition()->getOptions());
48250
48251 if ($mergeArgs) {
48252 $currentArguments = $this->definition->getArguments();
48253 $this->definition->setArguments($this->application->getDefinition()->getArguments());
48254 $this->definition->addArguments($currentArguments);
48255 }
48256
48257 $this->applicationDefinitionMerged = true;
48258 if ($mergeArgs) {
48259 $this->applicationDefinitionMergedWithArgs = true;
48260 }
48261 }
48262
48263
48264
48265
48266
48267
48268
48269
48270 public function setDefinition($definition)
48271 {
48272 if ($definition instanceof InputDefinition) {
48273 $this->definition = $definition;
48274 } else {
48275 $this->definition->setDefinition($definition);
48276 }
48277
48278 $this->applicationDefinitionMerged = false;
48279
48280 return $this;
48281 }
48282
48283
48284
48285
48286
48287
48288 public function getDefinition()
48289 {
48290 return $this->definition;
48291 }
48292
48293
48294
48295
48296
48297
48298
48299
48300
48301
48302
48303 public function getNativeDefinition()
48304 {
48305 return $this->getDefinition();
48306 }
48307
48308
48309
48310
48311
48312
48313
48314
48315
48316
48317
48318 public function addArgument($name, $mode = null, $description = '', $default = null)
48319 {
48320 $this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
48321
48322 return $this;
48323 }
48324
48325
48326
48327
48328
48329
48330
48331
48332
48333
48334
48335
48336 public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
48337 {
48338 $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
48339
48340 return $this;
48341 }
48342
48343
48344
48345
48346
48347
48348
48349
48350
48351
48352
48353
48354
48355
48356
48357 public function setName($name)
48358 {
48359 $this->validateName($name);
48360
48361 $this->name = $name;
48362
48363 return $this;
48364 }
48365
48366
48367
48368
48369
48370
48371
48372
48373
48374
48375
48376
48377
48378 public function setProcessTitle($title)
48379 {
48380 $this->processTitle = $title;
48381
48382 return $this;
48383 }
48384
48385
48386
48387
48388
48389
48390 public function getName()
48391 {
48392 return $this->name;
48393 }
48394
48395
48396
48397
48398
48399
48400
48401
48402 public function setDescription($description)
48403 {
48404 $this->description = $description;
48405
48406 return $this;
48407 }
48408
48409
48410
48411
48412
48413
48414 public function getDescription()
48415 {
48416 return $this->description;
48417 }
48418
48419
48420
48421
48422
48423
48424
48425
48426 public function setHelp($help)
48427 {
48428 $this->help = $help;
48429
48430 return $this;
48431 }
48432
48433
48434
48435
48436
48437
48438 public function getHelp()
48439 {
48440 return $this->help;
48441 }
48442
48443
48444
48445
48446
48447
48448
48449 public function getProcessedHelp()
48450 {
48451 $name = $this->name;
48452
48453 $placeholders = array(
48454 '%command.name%',
48455 '%command.full_name%',
48456 );
48457 $replacements = array(
48458 $name,
48459 $_SERVER['PHP_SELF'].' '.$name,
48460 );
48461
48462 return str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription());
48463 }
48464
48465
48466
48467
48468
48469
48470
48471
48472
48473
48474 public function setAliases($aliases)
48475 {
48476 if (!is_array($aliases) && !$aliases instanceof \Traversable) {
48477 throw new InvalidArgumentException('$aliases must be an array or an instance of \Traversable');
48478 }
48479
48480 foreach ($aliases as $alias) {
48481 $this->validateName($alias);
48482 }
48483
48484 $this->aliases = $aliases;
48485
48486 return $this;
48487 }
48488
48489
48490
48491
48492
48493
48494 public function getAliases()
48495 {
48496 return $this->aliases;
48497 }
48498
48499
48500
48501
48502
48503
48504
48505
48506 public function getSynopsis($short = false)
48507 {
48508 $key = $short ? 'short' : 'long';
48509
48510 if (!isset($this->synopsis[$key])) {
48511 $this->synopsis[$key] = trim(sprintf('%s %s', $this->name, $this->definition->getSynopsis($short)));
48512 }
48513
48514 return $this->synopsis[$key];
48515 }
48516
48517
48518
48519
48520
48521
48522
48523
48524 public function addUsage($usage)
48525 {
48526 if (0 !== strpos($usage, $this->name)) {
48527 $usage = sprintf('%s %s', $this->name, $usage);
48528 }
48529
48530 $this->usages[] = $usage;
48531
48532 return $this;
48533 }
48534
48535
48536
48537
48538
48539
48540 public function getUsages()
48541 {
48542 return $this->usages;
48543 }
48544
48545
48546
48547
48548
48549
48550
48551
48552
48553
48554
48555 public function getHelper($name)
48556 {
48557 if (null === $this->helperSet) {
48558 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));
48559 }
48560
48561 return $this->helperSet->get($name);
48562 }
48563
48564
48565
48566
48567
48568
48569
48570
48571 public function asText()
48572 {
48573 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
48574
48575 $descriptor = new TextDescriptor();
48576 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
48577 $descriptor->describe($output, $this, array('raw_output' => true));
48578
48579 return $output->fetch();
48580 }
48581
48582
48583
48584
48585
48586
48587
48588
48589
48590
48591 public function asXml($asDom = false)
48592 {
48593 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
48594
48595 $descriptor = new XmlDescriptor();
48596
48597 if ($asDom) {
48598 return $descriptor->getCommandDocument($this);
48599 }
48600
48601 $output = new BufferedOutput();
48602 $descriptor->describe($output, $this);
48603
48604 return $output->fetch();
48605 }
48606
48607
48608
48609
48610
48611
48612
48613
48614
48615
48616 private function validateName($name)
48617 {
48618 if (!preg_match('/^[^\:]++(\:[^\:]++)*$/', $name)) {
48619 throw new InvalidArgumentException(sprintf('Command name "%s" is invalid.', $name));
48620 }
48621 }
48622 }
48623 <?php
48624
48625
48626
48627
48628
48629
48630
48631
48632
48633
48634 namespace Symfony\Component\Console\Command;
48635
48636 use Symfony\Component\Console\Helper\DescriptorHelper;
48637 use Symfony\Component\Console\Input\InputArgument;
48638 use Symfony\Component\Console\Input\InputOption;
48639 use Symfony\Component\Console\Input\InputInterface;
48640 use Symfony\Component\Console\Output\OutputInterface;
48641
48642
48643
48644
48645
48646
48647 class HelpCommand extends Command
48648 {
48649 private $command;
48650
48651
48652
48653
48654 protected function configure()
48655 {
48656 $this->ignoreValidationErrors();
48657
48658 $this
48659 ->setName('help')
48660 ->setDefinition(array(
48661 new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
48662 new InputOption('xml', null, InputOption::VALUE_NONE, 'To output help as XML'),
48663 new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
48664 new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help'),
48665 ))
48666 ->setDescription('Displays help for a command')
48667 ->setHelp(<<<'EOF'
48668 The <info>%command.name%</info> command displays help for a given command:
48669
48670   <info>php %command.full_name% list</info>
48671
48672 You can also output the help in other formats by using the <comment>--format</comment> option:
48673
48674   <info>php %command.full_name% --format=xml list</info>
48675
48676 To display the list of available commands, please use the <info>list</info> command.
48677 EOF
48678 )
48679 ;
48680 }
48681
48682
48683
48684
48685
48686
48687 public function setCommand(Command $command)
48688 {
48689 $this->command = $command;
48690 }
48691
48692
48693
48694
48695 protected function execute(InputInterface $input, OutputInterface $output)
48696 {
48697 if (null === $this->command) {
48698 $this->command = $this->getApplication()->find($input->getArgument('command_name'));
48699 }
48700
48701 if ($input->getOption('xml')) {
48702 @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);
48703
48704 $input->setOption('format', 'xml');
48705 }
48706
48707 $helper = new DescriptorHelper();
48708 $helper->describe($output, $this->command, array(
48709 'format' => $input->getOption('format'),
48710 'raw_text' => $input->getOption('raw'),
48711 ));
48712
48713 $this->command = null;
48714 }
48715 }
48716 <?php
48717
48718
48719
48720
48721
48722
48723
48724
48725
48726
48727 namespace Symfony\Component\Console\Command;
48728
48729 use Symfony\Component\Console\Helper\DescriptorHelper;
48730 use Symfony\Component\Console\Input\InputArgument;
48731 use Symfony\Component\Console\Input\InputOption;
48732 use Symfony\Component\Console\Input\InputInterface;
48733 use Symfony\Component\Console\Output\OutputInterface;
48734 use Symfony\Component\Console\Input\InputDefinition;
48735
48736
48737
48738
48739
48740
48741 class ListCommand extends Command
48742 {
48743
48744
48745
48746 protected function configure()
48747 {
48748 $this
48749 ->setName('list')
48750 ->setDefinition($this->createDefinition())
48751 ->setDescription('Lists commands')
48752 ->setHelp(<<<'EOF'
48753 The <info>%command.name%</info> command lists all commands:
48754
48755   <info>php %command.full_name%</info>
48756
48757 You can also display the commands for a specific namespace:
48758
48759   <info>php %command.full_name% test</info>
48760
48761 You can also output the information in other formats by using the <comment>--format</comment> option:
48762
48763   <info>php %command.full_name% --format=xml</info>
48764
48765 It's also possible to get raw list of commands (useful for embedding command runner):
48766
48767   <info>php %command.full_name% --raw</info>
48768 EOF
48769 )
48770 ;
48771 }
48772
48773
48774
48775
48776 public function getNativeDefinition()
48777 {
48778 return $this->createDefinition();
48779 }
48780
48781
48782
48783
48784 protected function execute(InputInterface $input, OutputInterface $output)
48785 {
48786 if ($input->getOption('xml')) {
48787 @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);
48788
48789 $input->setOption('format', 'xml');
48790 }
48791
48792 $helper = new DescriptorHelper();
48793 $helper->describe($output, $this->getApplication(), array(
48794 'format' => $input->getOption('format'),
48795 'raw_text' => $input->getOption('raw'),
48796 'namespace' => $input->getArgument('namespace'),
48797 ));
48798 }
48799
48800
48801
48802
48803 private function createDefinition()
48804 {
48805 return new InputDefinition(array(
48806 new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
48807 new InputOption('xml', null, InputOption::VALUE_NONE, 'To output list as XML'),
48808 new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'),
48809 new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'),
48810 ));
48811 }
48812 }
48813 <?php
48814
48815
48816
48817
48818
48819
48820
48821
48822
48823
48824 namespace Symfony\Component\Console;
48825
48826
48827
48828
48829
48830
48831 final class ConsoleEvents
48832 {
48833
48834
48835
48836
48837
48838
48839
48840
48841
48842
48843
48844
48845 const COMMAND = 'console.command';
48846
48847
48848
48849
48850
48851
48852
48853
48854
48855
48856
48857
48858 const TERMINATE = 'console.terminate';
48859
48860
48861
48862
48863
48864
48865
48866
48867
48868
48869
48870
48871
48872 const EXCEPTION = 'console.exception';
48873 }
48874 <?php
48875
48876
48877
48878
48879
48880
48881
48882
48883
48884
48885 namespace Symfony\Component\Console\Descriptor;
48886
48887 use Symfony\Component\Console\Application;
48888 use Symfony\Component\Console\Command\Command;
48889 use Symfony\Component\Console\Exception\CommandNotFoundException;
48890
48891
48892
48893
48894
48895
48896 class ApplicationDescription
48897 {
48898 const GLOBAL_NAMESPACE = '_global';
48899
48900
48901
48902
48903 private $application;
48904
48905
48906
48907
48908 private $namespace;
48909
48910
48911
48912
48913 private $namespaces;
48914
48915
48916
48917
48918 private $commands;
48919
48920
48921
48922
48923 private $aliases;
48924
48925
48926
48927
48928
48929
48930
48931 public function __construct(Application $application, $namespace = null)
48932 {
48933 $this->application = $application;
48934 $this->namespace = $namespace;
48935 }
48936
48937
48938
48939
48940 public function getNamespaces()
48941 {
48942 if (null === $this->namespaces) {
48943 $this->inspectApplication();
48944 }
48945
48946 return $this->namespaces;
48947 }
48948
48949
48950
48951
48952 public function getCommands()
48953 {
48954 if (null === $this->commands) {
48955 $this->inspectApplication();
48956 }
48957
48958 return $this->commands;
48959 }
48960
48961
48962
48963
48964
48965
48966
48967
48968 public function getCommand($name)
48969 {
48970 if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
48971 throw new CommandNotFoundException(sprintf('Command %s does not exist.', $name));
48972 }
48973
48974 return isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name];
48975 }
48976
48977 private function inspectApplication()
48978 {
48979 $this->commands = array();
48980 $this->namespaces = array();
48981
48982 $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null);
48983 foreach ($this->sortCommands($all) as $namespace => $commands) {
48984 $names = array();
48985
48986
48987 foreach ($commands as $name => $command) {
48988 if (!$command->getName()) {
48989 continue;
48990 }
48991
48992 if ($command->getName() === $name) {
48993 $this->commands[$name] = $command;
48994 } else {
48995 $this->aliases[$name] = $command;
48996 }
48997
48998 $names[] = $name;
48999 }
49000
49001 $this->namespaces[$namespace] = array('id' => $namespace, 'commands' => $names);
49002 }
49003 }
49004
49005
49006
49007
49008
49009
49010 private function sortCommands(array $commands)
49011 {
49012 $namespacedCommands = array();
49013 $globalCommands = array();
49014 foreach ($commands as $name => $command) {
49015 $key = $this->application->extractNamespace($name, 1);
49016 if (!$key) {
49017 $globalCommands['_global'][$name] = $command;
49018 } else {
49019 $namespacedCommands[$key][$name] = $command;
49020 }
49021 }
49022 ksort($namespacedCommands);
49023 $namespacedCommands = array_merge($globalCommands, $namespacedCommands);
49024
49025 foreach ($namespacedCommands as &$commandsSet) {
49026 ksort($commandsSet);
49027 }
49028
49029  unset($commandsSet);
49030
49031 return $namespacedCommands;
49032 }
49033 }
49034 <?php
49035
49036
49037
49038
49039
49040
49041
49042
49043
49044
49045 namespace Symfony\Component\Console\Descriptor;
49046
49047 use Symfony\Component\Console\Application;
49048 use Symfony\Component\Console\Command\Command;
49049 use Symfony\Component\Console\Input\InputArgument;
49050 use Symfony\Component\Console\Input\InputDefinition;
49051 use Symfony\Component\Console\Input\InputOption;
49052 use Symfony\Component\Console\Output\OutputInterface;
49053 use Symfony\Component\Console\Exception\InvalidArgumentException;
49054
49055
49056
49057
49058
49059
49060 abstract class Descriptor implements DescriptorInterface
49061 {
49062
49063
49064
49065 private $output;
49066
49067
49068
49069
49070 public function describe(OutputInterface $output, $object, array $options = array())
49071 {
49072 $this->output = $output;
49073
49074 switch (true) {
49075 case $object instanceof InputArgument:
49076 $this->describeInputArgument($object, $options);
49077 break;
49078 case $object instanceof InputOption:
49079 $this->describeInputOption($object, $options);
49080 break;
49081 case $object instanceof InputDefinition:
49082 $this->describeInputDefinition($object, $options);
49083 break;
49084 case $object instanceof Command:
49085 $this->describeCommand($object, $options);
49086 break;
49087 case $object instanceof Application:
49088 $this->describeApplication($object, $options);
49089 break;
49090 default:
49091 throw new InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object)));
49092 }
49093 }
49094
49095
49096
49097
49098
49099
49100
49101 protected function write($content, $decorated = false)
49102 {
49103 $this->output->write($content, false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW);
49104 }
49105
49106
49107
49108
49109
49110
49111
49112
49113
49114 abstract protected function describeInputArgument(InputArgument $argument, array $options = array());
49115
49116
49117
49118
49119
49120
49121
49122
49123
49124 abstract protected function describeInputOption(InputOption $option, array $options = array());
49125
49126
49127
49128
49129
49130
49131
49132
49133
49134 abstract protected function describeInputDefinition(InputDefinition $definition, array $options = array());
49135
49136
49137
49138
49139
49140
49141
49142
49143
49144 abstract protected function describeCommand(Command $command, array $options = array());
49145
49146
49147
49148
49149
49150
49151
49152
49153
49154 abstract protected function describeApplication(Application $application, array $options = array());
49155 }
49156 <?php
49157
49158
49159
49160
49161
49162
49163
49164
49165
49166
49167 namespace Symfony\Component\Console\Descriptor;
49168
49169 use Symfony\Component\Console\Output\OutputInterface;
49170
49171
49172
49173
49174
49175
49176 interface DescriptorInterface
49177 {
49178
49179
49180
49181
49182
49183
49184
49185 public function describe(OutputInterface $output, $object, array $options = array());
49186 }
49187 <?php
49188
49189
49190
49191
49192
49193
49194
49195
49196
49197
49198 namespace Symfony\Component\Console\Descriptor;
49199
49200 use Symfony\Component\Console\Application;
49201 use Symfony\Component\Console\Command\Command;
49202 use Symfony\Component\Console\Input\InputArgument;
49203 use Symfony\Component\Console\Input\InputDefinition;
49204 use Symfony\Component\Console\Input\InputOption;
49205
49206
49207
49208
49209
49210
49211
49212
49213 class JsonDescriptor extends Descriptor
49214 {
49215
49216
49217
49218 protected function describeInputArgument(InputArgument $argument, array $options = array())
49219 {
49220 $this->writeData($this->getInputArgumentData($argument), $options);
49221 }
49222
49223
49224
49225
49226 protected function describeInputOption(InputOption $option, array $options = array())
49227 {
49228 $this->writeData($this->getInputOptionData($option), $options);
49229 }
49230
49231
49232
49233
49234 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
49235 {
49236 $this->writeData($this->getInputDefinitionData($definition), $options);
49237 }
49238
49239
49240
49241
49242 protected function describeCommand(Command $command, array $options = array())
49243 {
49244 $this->writeData($this->getCommandData($command), $options);
49245 }
49246
49247
49248
49249
49250 protected function describeApplication(Application $application, array $options = array())
49251 {
49252 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
49253 $description = new ApplicationDescription($application, $describedNamespace);
49254 $commands = array();
49255
49256 foreach ($description->getCommands() as $command) {
49257 $commands[] = $this->getCommandData($command);
49258 }
49259
49260 $data = $describedNamespace
49261 ? array('commands' => $commands, 'namespace' => $describedNamespace)
49262 : array('commands' => $commands, 'namespaces' => array_values($description->getNamespaces()));
49263
49264 $this->writeData($data, $options);
49265 }
49266
49267
49268
49269
49270
49271
49272
49273
49274
49275 private function writeData(array $data, array $options)
49276 {
49277 $this->write(json_encode($data, isset($options['json_encoding']) ? $options['json_encoding'] : 0));
49278 }
49279
49280
49281
49282
49283
49284
49285 private function getInputArgumentData(InputArgument $argument)
49286 {
49287 return array(
49288 'name' => $argument->getName(),
49289 'is_required' => $argument->isRequired(),
49290 'is_array' => $argument->isArray(),
49291 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()),
49292 'default' => INF === $argument->getDefault() ? 'INF' : $argument->getDefault(),
49293 );
49294 }
49295
49296
49297
49298
49299
49300
49301 private function getInputOptionData(InputOption $option)
49302 {
49303 return array(
49304 'name' => '--'.$option->getName(),
49305 'shortcut' => $option->getShortcut() ? '-'.implode('|-', explode('|', $option->getShortcut())) : '',
49306 'accept_value' => $option->acceptValue(),
49307 'is_value_required' => $option->isValueRequired(),
49308 'is_multiple' => $option->isArray(),
49309 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()),
49310 'default' => INF === $option->getDefault() ? 'INF' : $option->getDefault(),
49311 );
49312 }
49313
49314
49315
49316
49317
49318
49319 private function getInputDefinitionData(InputDefinition $definition)
49320 {
49321 $inputArguments = array();
49322 foreach ($definition->getArguments() as $name => $argument) {
49323 $inputArguments[$name] = $this->getInputArgumentData($argument);
49324 }
49325
49326 $inputOptions = array();
49327 foreach ($definition->getOptions() as $name => $option) {
49328 $inputOptions[$name] = $this->getInputOptionData($option);
49329 }
49330
49331 return array('arguments' => $inputArguments, 'options' => $inputOptions);
49332 }
49333
49334
49335
49336
49337
49338
49339 private function getCommandData(Command $command)
49340 {
49341 $command->getSynopsis();
49342 $command->mergeApplicationDefinition(false);
49343
49344 return array(
49345 'name' => $command->getName(),
49346 'usage' => array_merge(array($command->getSynopsis()), $command->getUsages(), $command->getAliases()),
49347 'description' => $command->getDescription(),
49348 'help' => $command->getProcessedHelp(),
49349 'definition' => $this->getInputDefinitionData($command->getNativeDefinition()),
49350 );
49351 }
49352 }
49353 <?php
49354
49355
49356
49357
49358
49359
49360
49361
49362
49363
49364 namespace Symfony\Component\Console\Descriptor;
49365
49366 use Symfony\Component\Console\Application;
49367 use Symfony\Component\Console\Command\Command;
49368 use Symfony\Component\Console\Helper\Helper;
49369 use Symfony\Component\Console\Input\InputArgument;
49370 use Symfony\Component\Console\Input\InputDefinition;
49371 use Symfony\Component\Console\Input\InputOption;
49372
49373
49374
49375
49376
49377
49378
49379
49380 class MarkdownDescriptor extends Descriptor
49381 {
49382
49383
49384
49385 protected function describeInputArgument(InputArgument $argument, array $options = array())
49386 {
49387 $this->write(
49388 '**'.$argument->getName().':**'."\n\n"
49389 .'* Name: '.($argument->getName() ?: '<none>')."\n"
49390 .'* Is required: '.($argument->isRequired() ? 'yes' : 'no')."\n"
49391 .'* Is array: '.($argument->isArray() ? 'yes' : 'no')."\n"
49392 .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n  ", $argument->getDescription() ?: '<none>')."\n"
49393 .'* Default: `'.str_replace("\n", '', var_export($argument->getDefault(), true)).'`'
49394 );
49395 }
49396
49397
49398
49399
49400 protected function describeInputOption(InputOption $option, array $options = array())
49401 {
49402 $this->write(
49403 '**'.$option->getName().':**'."\n\n"
49404 .'* Name: `--'.$option->getName().'`'."\n"
49405 .'* Shortcut: '.($option->getShortcut() ? '`-'.implode('|-', explode('|', $option->getShortcut())).'`' : '<none>')."\n"
49406 .'* Accept value: '.($option->acceptValue() ? 'yes' : 'no')."\n"
49407 .'* Is value required: '.($option->isValueRequired() ? 'yes' : 'no')."\n"
49408 .'* Is multiple: '.($option->isArray() ? 'yes' : 'no')."\n"
49409 .'* Description: '.preg_replace('/\s*[\r\n]\s*/', "\n  ", $option->getDescription() ?: '<none>')."\n"
49410 .'* Default: `'.str_replace("\n", '', var_export($option->getDefault(), true)).'`'
49411 );
49412 }
49413
49414
49415
49416
49417 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
49418 {
49419 if ($showArguments = count($definition->getArguments()) > 0) {
49420 $this->write('### Arguments:');
49421 foreach ($definition->getArguments() as $argument) {
49422 $this->write("\n\n");
49423 $this->write($this->describeInputArgument($argument));
49424 }
49425 }
49426
49427 if (count($definition->getOptions()) > 0) {
49428 if ($showArguments) {
49429 $this->write("\n\n");
49430 }
49431
49432 $this->write('### Options:');
49433 foreach ($definition->getOptions() as $option) {
49434 $this->write("\n\n");
49435 $this->write($this->describeInputOption($option));
49436 }
49437 }
49438 }
49439
49440
49441
49442
49443 protected function describeCommand(Command $command, array $options = array())
49444 {
49445 $command->getSynopsis();
49446 $command->mergeApplicationDefinition(false);
49447
49448 $this->write(
49449 $command->getName()."\n"
49450 .str_repeat('-', Helper::strlen($command->getName()))."\n\n"
49451 .'* Description: '.($command->getDescription() ?: '<none>')."\n"
49452 .'* Usage:'."\n\n"
49453 .array_reduce(array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()), function ($carry, $usage) {
49454 return $carry.'  * `'.$usage.'`'."\n";
49455 })
49456 );
49457
49458 if ($help = $command->getProcessedHelp()) {
49459 $this->write("\n");
49460 $this->write($help);
49461 }
49462
49463 if ($command->getNativeDefinition()) {
49464 $this->write("\n\n");
49465 $this->describeInputDefinition($command->getNativeDefinition());
49466 }
49467 }
49468
49469
49470
49471
49472 protected function describeApplication(Application $application, array $options = array())
49473 {
49474 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
49475 $description = new ApplicationDescription($application, $describedNamespace);
49476
49477 $this->write($application->getName()."\n".str_repeat('=', Helper::strlen($application->getName())));
49478
49479 foreach ($description->getNamespaces() as $namespace) {
49480 if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
49481 $this->write("\n\n");
49482 $this->write('**'.$namespace['id'].':**');
49483 }
49484
49485 $this->write("\n\n");
49486 $this->write(implode("\n", array_map(function ($commandName) {
49487 return '* '.$commandName;
49488 }, $namespace['commands'])));
49489 }
49490
49491 foreach ($description->getCommands() as $command) {
49492 $this->write("\n\n");
49493 $this->write($this->describeCommand($command));
49494 }
49495 }
49496 }
49497 <?php
49498
49499
49500
49501
49502
49503
49504
49505
49506
49507
49508 namespace Symfony\Component\Console\Descriptor;
49509
49510 use Symfony\Component\Console\Application;
49511 use Symfony\Component\Console\Command\Command;
49512 use Symfony\Component\Console\Formatter\OutputFormatter;
49513 use Symfony\Component\Console\Helper\Helper;
49514 use Symfony\Component\Console\Input\InputArgument;
49515 use Symfony\Component\Console\Input\InputDefinition;
49516 use Symfony\Component\Console\Input\InputOption;
49517
49518
49519
49520
49521
49522
49523
49524
49525 class TextDescriptor extends Descriptor
49526 {
49527
49528
49529
49530 protected function describeInputArgument(InputArgument $argument, array $options = array())
49531 {
49532 if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault()))) {
49533 $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault()));
49534 } else {
49535 $default = '';
49536 }
49537
49538 $totalWidth = isset($options['total_width']) ? $options['total_width'] : Helper::strlen($argument->getName());
49539 $spacingWidth = $totalWidth - strlen($argument->getName());
49540
49541 $this->writeText(sprintf('  <info>%s</info>  %s%s%s',
49542 $argument->getName(),
49543 str_repeat(' ', $spacingWidth),
49544
49545  preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $argument->getDescription()),
49546 $default
49547 ), $options);
49548 }
49549
49550
49551
49552
49553 protected function describeInputOption(InputOption $option, array $options = array())
49554 {
49555 if ($option->acceptValue() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault()))) {
49556 $default = sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($option->getDefault()));
49557 } else {
49558 $default = '';
49559 }
49560
49561 $value = '';
49562 if ($option->acceptValue()) {
49563 $value = '='.strtoupper($option->getName());
49564
49565 if ($option->isValueOptional()) {
49566 $value = '['.$value.']';
49567 }
49568 }
49569
49570 $totalWidth = isset($options['total_width']) ? $options['total_width'] : $this->calculateTotalWidthForOptions(array($option));
49571 $synopsis = sprintf('%s%s',
49572 $option->getShortcut() ? sprintf('-%s, ', $option->getShortcut()) : '    ',
49573 sprintf('--%s%s', $option->getName(), $value)
49574 );
49575
49576 $spacingWidth = $totalWidth - Helper::strlen($synopsis);
49577
49578 $this->writeText(sprintf('  <info>%s</info>  %s%s%s%s',
49579 $synopsis,
49580 str_repeat(' ', $spacingWidth),
49581
49582  preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()),
49583 $default,
49584 $option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
49585 ), $options);
49586 }
49587
49588
49589
49590
49591 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
49592 {
49593 $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions());
49594 foreach ($definition->getArguments() as $argument) {
49595 $totalWidth = max($totalWidth, Helper::strlen($argument->getName()));
49596 }
49597
49598 if ($definition->getArguments()) {
49599 $this->writeText('<comment>Arguments:</comment>', $options);
49600 $this->writeText("\n");
49601 foreach ($definition->getArguments() as $argument) {
49602 $this->describeInputArgument($argument, array_merge($options, array('total_width' => $totalWidth)));
49603 $this->writeText("\n");
49604 }
49605 }
49606
49607 if ($definition->getArguments() && $definition->getOptions()) {
49608 $this->writeText("\n");
49609 }
49610
49611 if ($definition->getOptions()) {
49612 $laterOptions = array();
49613
49614 $this->writeText('<comment>Options:</comment>', $options);
49615 foreach ($definition->getOptions() as $option) {
49616 if (strlen($option->getShortcut()) > 1) {
49617 $laterOptions[] = $option;
49618 continue;
49619 }
49620 $this->writeText("\n");
49621 $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
49622 }
49623 foreach ($laterOptions as $option) {
49624 $this->writeText("\n");
49625 $this->describeInputOption($option, array_merge($options, array('total_width' => $totalWidth)));
49626 }
49627 }
49628 }
49629
49630
49631
49632
49633 protected function describeCommand(Command $command, array $options = array())
49634 {
49635 $command->getSynopsis(true);
49636 $command->getSynopsis(false);
49637 $command->mergeApplicationDefinition(false);
49638
49639 $this->writeText('<comment>Usage:</comment>', $options);
49640 foreach (array_merge(array($command->getSynopsis(true)), $command->getAliases(), $command->getUsages()) as $usage) {
49641 $this->writeText("\n");
49642 $this->writeText('  '.$usage, $options);
49643 }
49644 $this->writeText("\n");
49645
49646 $definition = $command->getNativeDefinition();
49647 if ($definition->getOptions() || $definition->getArguments()) {
49648 $this->writeText("\n");
49649 $this->describeInputDefinition($definition, $options);
49650 $this->writeText("\n");
49651 }
49652
49653 if ($help = $command->getProcessedHelp()) {
49654 $this->writeText("\n");
49655 $this->writeText('<comment>Help:</comment>', $options);
49656 $this->writeText("\n");
49657 $this->writeText('  '.str_replace("\n", "\n  ", $help), $options);
49658 $this->writeText("\n");
49659 }
49660 }
49661
49662
49663
49664
49665 protected function describeApplication(Application $application, array $options = array())
49666 {
49667 $describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
49668 $description = new ApplicationDescription($application, $describedNamespace);
49669
49670 if (isset($options['raw_text']) && $options['raw_text']) {
49671 $width = $this->getColumnWidth($description->getCommands());
49672
49673 foreach ($description->getCommands() as $command) {
49674 $this->writeText(sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options);
49675 $this->writeText("\n");
49676 }
49677 } else {
49678 if ('' != $help = $application->getHelp()) {
49679 $this->writeText("$help\n\n", $options);
49680 }
49681
49682 $this->writeText("<comment>Usage:</comment>\n", $options);
49683 $this->writeText("  command [options] [arguments]\n\n", $options);
49684
49685 $this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options);
49686
49687 $this->writeText("\n");
49688 $this->writeText("\n");
49689
49690 $width = $this->getColumnWidth($description->getCommands());
49691
49692 if ($describedNamespace) {
49693 $this->writeText(sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options);
49694 } else {
49695 $this->writeText('<comment>Available commands:</comment>', $options);
49696 }
49697
49698
49699  foreach ($description->getNamespaces() as $namespace) {
49700 if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
49701 $this->writeText("\n");
49702 $this->writeText(' <comment>'.$namespace['id'].'</comment>', $options);
49703 }
49704
49705 foreach ($namespace['commands'] as $name) {
49706 $this->writeText("\n");
49707 $spacingWidth = $width - Helper::strlen($name);
49708 $this->writeText(sprintf('  <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $description->getCommand($name)->getDescription()), $options);
49709 }
49710 }
49711
49712 $this->writeText("\n");
49713 }
49714 }
49715
49716
49717
49718
49719 private function writeText($content, array $options = array())
49720 {
49721 $this->write(
49722 isset($options['raw_text']) && $options['raw_text'] ? strip_tags($content) : $content,
49723 isset($options['raw_output']) ? !$options['raw_output'] : true
49724 );
49725 }
49726
49727
49728
49729
49730
49731
49732
49733
49734 private function formatDefaultValue($default)
49735 {
49736 if (INF === $default) {
49737 return 'INF';
49738 }
49739
49740 if (is_string($default)) {
49741 $default = OutputFormatter::escape($default);
49742 } elseif (is_array($default)) {
49743 foreach ($default as $key => $value) {
49744 if (is_string($value)) {
49745 $default[$key] = OutputFormatter::escape($value);
49746 }
49747 }
49748 }
49749
49750 if (\PHP_VERSION_ID < 50400) {
49751 return str_replace(array('\/', '\\\\'), array('/', '\\'), json_encode($default));
49752 }
49753
49754 return str_replace('\\\\', '\\', json_encode($default, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE));
49755 }
49756
49757
49758
49759
49760
49761
49762 private function getColumnWidth(array $commands)
49763 {
49764 $widths = array();
49765
49766 foreach ($commands as $command) {
49767 $widths[] = Helper::strlen($command->getName());
49768 foreach ($command->getAliases() as $alias) {
49769 $widths[] = Helper::strlen($alias);
49770 }
49771 }
49772
49773 return max($widths) + 2;
49774 }
49775
49776
49777
49778
49779
49780
49781 private function calculateTotalWidthForOptions($options)
49782 {
49783 $totalWidth = 0;
49784 foreach ($options as $option) {
49785
49786  $nameLength = 1 + max(strlen($option->getShortcut()), 1) + 4 + Helper::strlen($option->getName());
49787
49788 if ($option->acceptValue()) {
49789 $valueLength = 1 + Helper::strlen($option->getName()); 
49790  $valueLength += $option->isValueOptional() ? 2 : 0; 
49791
49792 $nameLength += $valueLength;
49793 }
49794 $totalWidth = max($totalWidth, $nameLength);
49795 }
49796
49797 return $totalWidth;
49798 }
49799 }
49800 <?php
49801
49802
49803
49804
49805
49806
49807
49808
49809
49810
49811 namespace Symfony\Component\Console\Descriptor;
49812
49813 use Symfony\Component\Console\Application;
49814 use Symfony\Component\Console\Command\Command;
49815 use Symfony\Component\Console\Input\InputArgument;
49816 use Symfony\Component\Console\Input\InputDefinition;
49817 use Symfony\Component\Console\Input\InputOption;
49818
49819
49820
49821
49822
49823
49824
49825
49826 class XmlDescriptor extends Descriptor
49827 {
49828
49829
49830
49831
49832
49833 public function getInputDefinitionDocument(InputDefinition $definition)
49834 {
49835 $dom = new \DOMDocument('1.0', 'UTF-8');
49836 $dom->appendChild($definitionXML = $dom->createElement('definition'));
49837
49838 $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
49839 foreach ($definition->getArguments() as $argument) {
49840 $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument));
49841 }
49842
49843 $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
49844 foreach ($definition->getOptions() as $option) {
49845 $this->appendDocument($optionsXML, $this->getInputOptionDocument($option));
49846 }
49847
49848 return $dom;
49849 }
49850
49851
49852
49853
49854
49855
49856 public function getCommandDocument(Command $command)
49857 {
49858 $dom = new \DOMDocument('1.0', 'UTF-8');
49859 $dom->appendChild($commandXML = $dom->createElement('command'));
49860
49861 $command->getSynopsis();
49862 $command->mergeApplicationDefinition(false);
49863
49864 $commandXML->setAttribute('id', $command->getName());
49865 $commandXML->setAttribute('name', $command->getName());
49866
49867 $commandXML->appendChild($usagesXML = $dom->createElement('usages'));
49868
49869 foreach (array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()) as $usage) {
49870 $usagesXML->appendChild($dom->createElement('usage', $usage));
49871 }
49872
49873 $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
49874 $descriptionXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getDescription())));
49875
49876 $commandXML->appendChild($helpXML = $dom->createElement('help'));
49877 $helpXML->appendChild($dom->createTextNode(str_replace("\n", "\n ", $command->getProcessedHelp())));
49878
49879 $definitionXML = $this->getInputDefinitionDocument($command->getNativeDefinition());
49880 $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));
49881
49882 return $dom;
49883 }
49884
49885
49886
49887
49888
49889
49890
49891 public function getApplicationDocument(Application $application, $namespace = null)
49892 {
49893 $dom = new \DOMDocument('1.0', 'UTF-8');
49894 $dom->appendChild($rootXml = $dom->createElement('symfony'));
49895
49896 if ($application->getName() !== 'UNKNOWN') {
49897 $rootXml->setAttribute('name', $application->getName());
49898 if ($application->getVersion() !== 'UNKNOWN') {
49899 $rootXml->setAttribute('version', $application->getVersion());
49900 }
49901 }
49902
49903 $rootXml->appendChild($commandsXML = $dom->createElement('commands'));
49904
49905 $description = new ApplicationDescription($application, $namespace);
49906
49907 if ($namespace) {
49908 $commandsXML->setAttribute('namespace', $namespace);
49909 }
49910
49911 foreach ($description->getCommands() as $command) {
49912 $this->appendDocument($commandsXML, $this->getCommandDocument($command));
49913 }
49914
49915 if (!$namespace) {
49916 $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces'));
49917
49918 foreach ($description->getNamespaces() as $namespaceDescription) {
49919 $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
49920 $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']);
49921
49922 foreach ($namespaceDescription['commands'] as $name) {
49923 $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
49924 $commandXML->appendChild($dom->createTextNode($name));
49925 }
49926 }
49927 }
49928
49929 return $dom;
49930 }
49931
49932
49933
49934
49935 protected function describeInputArgument(InputArgument $argument, array $options = array())
49936 {
49937 $this->writeDocument($this->getInputArgumentDocument($argument));
49938 }
49939
49940
49941
49942
49943 protected function describeInputOption(InputOption $option, array $options = array())
49944 {
49945 $this->writeDocument($this->getInputOptionDocument($option));
49946 }
49947
49948
49949
49950
49951 protected function describeInputDefinition(InputDefinition $definition, array $options = array())
49952 {
49953 $this->writeDocument($this->getInputDefinitionDocument($definition));
49954 }
49955
49956
49957
49958
49959 protected function describeCommand(Command $command, array $options = array())
49960 {
49961 $this->writeDocument($this->getCommandDocument($command));
49962 }
49963
49964
49965
49966
49967 protected function describeApplication(Application $application, array $options = array())
49968 {
49969 $this->writeDocument($this->getApplicationDocument($application, isset($options['namespace']) ? $options['namespace'] : null));
49970 }
49971
49972
49973
49974
49975
49976
49977
49978 private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent)
49979 {
49980 foreach ($importedParent->childNodes as $childNode) {
49981 $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, true));
49982 }
49983 }
49984
49985
49986
49987
49988
49989
49990
49991
49992 private function writeDocument(\DOMDocument $dom)
49993 {
49994 $dom->formatOutput = true;
49995 $this->write($dom->saveXML());
49996 }
49997
49998
49999
50000
50001
50002
50003 private function getInputArgumentDocument(InputArgument $argument)
50004 {
50005 $dom = new \DOMDocument('1.0', 'UTF-8');
50006
50007 $dom->appendChild($objectXML = $dom->createElement('argument'));
50008 $objectXML->setAttribute('name', $argument->getName());
50009 $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
50010 $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
50011 $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
50012 $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
50013
50014 $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
50015 $defaults = is_array($argument->getDefault()) ? $argument->getDefault() : (is_bool($argument->getDefault()) ? array(var_export($argument->getDefault(), true)) : ($argument->getDefault() ? array($argument->getDefault()) : array()));
50016 foreach ($defaults as $default) {
50017 $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
50018 $defaultXML->appendChild($dom->createTextNode($default));
50019 }
50020
50021 return $dom;
50022 }
50023
50024
50025
50026
50027
50028
50029 private function getInputOptionDocument(InputOption $option)
50030 {
50031 $dom = new \DOMDocument('1.0', 'UTF-8');
50032
50033 $dom->appendChild($objectXML = $dom->createElement('option'));
50034 $objectXML->setAttribute('name', '--'.$option->getName());
50035 $pos = strpos($option->getShortcut(), '|');
50036 if (false !== $pos) {
50037 $objectXML->setAttribute('shortcut', '-'.substr($option->getShortcut(), 0, $pos));
50038 $objectXML->setAttribute('shortcuts', '-'.implode('|-', explode('|', $option->getShortcut())));
50039 } else {
50040 $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
50041 }
50042 $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
50043 $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
50044 $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
50045 $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
50046 $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
50047
50048 if ($option->acceptValue()) {
50049 $defaults = is_array($option->getDefault()) ? $option->getDefault() : (is_bool($option->getDefault()) ? array(var_export($option->getDefault(), true)) : ($option->getDefault() ? array($option->getDefault()) : array()));
50050 $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
50051
50052 if (!empty($defaults)) {
50053 foreach ($defaults as $default) {
50054 $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
50055 $defaultXML->appendChild($dom->createTextNode($default));
50056 }
50057 }
50058 }
50059
50060 return $dom;
50061 }
50062 }
50063 <?php
50064
50065
50066
50067
50068
50069
50070
50071
50072
50073
50074 namespace Symfony\Component\Console\Event;
50075
50076
50077
50078
50079
50080
50081 class ConsoleCommandEvent extends ConsoleEvent
50082 {
50083
50084
50085
50086 const RETURN_CODE_DISABLED = 113;
50087
50088
50089
50090
50091
50092
50093 private $commandShouldRun = true;
50094
50095
50096
50097
50098
50099
50100 public function disableCommand()
50101 {
50102 return $this->commandShouldRun = false;
50103 }
50104
50105
50106
50107
50108
50109
50110 public function enableCommand()
50111 {
50112 return $this->commandShouldRun = true;
50113 }
50114
50115
50116
50117
50118
50119
50120 public function commandShouldRun()
50121 {
50122 return $this->commandShouldRun;
50123 }
50124 }
50125 <?php
50126
50127
50128
50129
50130
50131
50132
50133
50134
50135
50136 namespace Symfony\Component\Console\Event;
50137
50138 use Symfony\Component\Console\Command\Command;
50139 use Symfony\Component\Console\Input\InputInterface;
50140 use Symfony\Component\Console\Output\OutputInterface;
50141 use Symfony\Component\EventDispatcher\Event;
50142
50143
50144
50145
50146
50147
50148 class ConsoleEvent extends Event
50149 {
50150 protected $command;
50151
50152 private $input;
50153 private $output;
50154
50155 public function __construct(Command $command, InputInterface $input, OutputInterface $output)
50156 {
50157 $this->command = $command;
50158 $this->input = $input;
50159 $this->output = $output;
50160 }
50161
50162
50163
50164
50165
50166
50167 public function getCommand()
50168 {
50169 return $this->command;
50170 }
50171
50172
50173
50174
50175
50176
50177 public function getInput()
50178 {
50179 return $this->input;
50180 }
50181
50182
50183
50184
50185
50186
50187 public function getOutput()
50188 {
50189 return $this->output;
50190 }
50191 }
50192 <?php
50193
50194
50195
50196
50197
50198
50199
50200
50201
50202
50203 namespace Symfony\Component\Console\Event;
50204
50205 use Symfony\Component\Console\Command\Command;
50206 use Symfony\Component\Console\Input\InputInterface;
50207 use Symfony\Component\Console\Output\OutputInterface;
50208
50209
50210
50211
50212
50213
50214 class ConsoleExceptionEvent extends ConsoleEvent
50215 {
50216 private $exception;
50217 private $exitCode;
50218
50219 public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode)
50220 {
50221 parent::__construct($command, $input, $output);
50222
50223 $this->setException($exception);
50224 $this->exitCode = (int) $exitCode;
50225 }
50226
50227
50228
50229
50230
50231
50232 public function getException()
50233 {
50234 return $this->exception;
50235 }
50236
50237
50238
50239
50240
50241
50242
50243
50244 public function setException(\Exception $exception)
50245 {
50246 $this->exception = $exception;
50247 }
50248
50249
50250
50251
50252
50253
50254 public function getExitCode()
50255 {
50256 return $this->exitCode;
50257 }
50258 }
50259 <?php
50260
50261
50262
50263
50264
50265
50266
50267
50268
50269
50270 namespace Symfony\Component\Console\Event;
50271
50272 use Symfony\Component\Console\Command\Command;
50273 use Symfony\Component\Console\Input\InputInterface;
50274 use Symfony\Component\Console\Output\OutputInterface;
50275
50276
50277
50278
50279
50280
50281 class ConsoleTerminateEvent extends ConsoleEvent
50282 {
50283
50284
50285
50286
50287
50288 private $exitCode;
50289
50290 public function __construct(Command $command, InputInterface $input, OutputInterface $output, $exitCode)
50291 {
50292 parent::__construct($command, $input, $output);
50293
50294 $this->setExitCode($exitCode);
50295 }
50296
50297
50298
50299
50300
50301
50302 public function setExitCode($exitCode)
50303 {
50304 $this->exitCode = (int) $exitCode;
50305 }
50306
50307
50308
50309
50310
50311
50312 public function getExitCode()
50313 {
50314 return $this->exitCode;
50315 }
50316 }
50317 <?php
50318
50319
50320
50321
50322
50323
50324
50325
50326
50327
50328 namespace Symfony\Component\Console\Exception;
50329
50330
50331
50332
50333
50334
50335 class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface
50336 {
50337 private $alternatives;
50338
50339
50340
50341
50342
50343
50344
50345 public function __construct($message, array $alternatives = array(), $code = 0, \Exception $previous = null)
50346 {
50347 parent::__construct($message, $code, $previous);
50348
50349 $this->alternatives = $alternatives;
50350 }
50351
50352
50353
50354
50355 public function getAlternatives()
50356 {
50357 return $this->alternatives;
50358 }
50359 }
50360 <?php
50361
50362
50363
50364
50365
50366
50367
50368
50369
50370
50371 namespace Symfony\Component\Console\Exception;
50372
50373
50374
50375
50376
50377
50378 interface ExceptionInterface
50379 {
50380 }
50381 <?php
50382
50383
50384
50385
50386
50387
50388
50389
50390
50391
50392 namespace Symfony\Component\Console\Exception;
50393
50394
50395
50396
50397 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
50398 {
50399 }
50400 <?php
50401
50402
50403
50404
50405
50406
50407
50408
50409
50410
50411 namespace Symfony\Component\Console\Exception;
50412
50413
50414
50415
50416
50417
50418 class InvalidOptionException extends \InvalidArgumentException implements ExceptionInterface
50419 {
50420 }
50421 <?php
50422
50423
50424
50425
50426
50427
50428
50429
50430
50431
50432 namespace Symfony\Component\Console\Exception;
50433
50434
50435
50436
50437 class LogicException extends \LogicException implements ExceptionInterface
50438 {
50439 }
50440 <?php
50441
50442
50443
50444
50445
50446
50447
50448
50449
50450
50451 namespace Symfony\Component\Console\Exception;
50452
50453
50454
50455
50456 class RuntimeException extends \RuntimeException implements ExceptionInterface
50457 {
50458 }
50459 <?php
50460
50461
50462
50463
50464
50465
50466
50467
50468
50469
50470 namespace Symfony\Component\Console\Formatter;
50471
50472 use Symfony\Component\Console\Exception\InvalidArgumentException;
50473
50474
50475
50476
50477
50478
50479 class OutputFormatter implements OutputFormatterInterface
50480 {
50481 private $decorated;
50482 private $styles = array();
50483 private $styleStack;
50484
50485
50486
50487
50488
50489
50490
50491
50492 public static function escape($text)
50493 {
50494 $text = preg_replace('/([^\\\\]?)</', '$1\\<', $text);
50495
50496 return self::escapeTrailingBackslash($text);
50497 }
50498
50499
50500
50501
50502
50503
50504
50505
50506
50507
50508 public static function escapeTrailingBackslash($text)
50509 {
50510 if ('\\' === substr($text, -1)) {
50511 $len = strlen($text);
50512 $text = rtrim($text, '\\');
50513 $text .= str_repeat('<<', $len - strlen($text));
50514 }
50515
50516 return $text;
50517 }
50518
50519
50520
50521
50522
50523
50524
50525 public function __construct($decorated = false, array $styles = array())
50526 {
50527 $this->decorated = (bool) $decorated;
50528
50529 $this->setStyle('error', new OutputFormatterStyle('white', 'red'));
50530 $this->setStyle('info', new OutputFormatterStyle('green'));
50531 $this->setStyle('comment', new OutputFormatterStyle('yellow'));
50532 $this->setStyle('question', new OutputFormatterStyle('black', 'cyan'));
50533
50534 foreach ($styles as $name => $style) {
50535 $this->setStyle($name, $style);
50536 }
50537
50538 $this->styleStack = new OutputFormatterStyleStack();
50539 }
50540
50541
50542
50543
50544 public function setDecorated($decorated)
50545 {
50546 $this->decorated = (bool) $decorated;
50547 }
50548
50549
50550
50551
50552 public function isDecorated()
50553 {
50554 return $this->decorated;
50555 }
50556
50557
50558
50559
50560 public function setStyle($name, OutputFormatterStyleInterface $style)
50561 {
50562 $this->styles[strtolower($name)] = $style;
50563 }
50564
50565
50566
50567
50568 public function hasStyle($name)
50569 {
50570 return isset($this->styles[strtolower($name)]);
50571 }
50572
50573
50574
50575
50576 public function getStyle($name)
50577 {
50578 if (!$this->hasStyle($name)) {
50579 throw new InvalidArgumentException(sprintf('Undefined style: %s', $name));
50580 }
50581
50582 return $this->styles[strtolower($name)];
50583 }
50584
50585
50586
50587
50588 public function format($message)
50589 {
50590 $message = (string) $message;
50591 $offset = 0;
50592 $output = '';
50593 $tagRegex = '[a-z][a-z0-9_=;-]*+';
50594 preg_match_all("#<(($tagRegex) | /($tagRegex)?)>#ix", $message, $matches, PREG_OFFSET_CAPTURE);
50595 foreach ($matches[0] as $i => $match) {
50596 $pos = $match[1];
50597 $text = $match[0];
50598
50599 if (0 != $pos && '\\' == $message[$pos - 1]) {
50600 continue;
50601 }
50602
50603
50604  $output .= $this->applyCurrentStyle(substr($message, $offset, $pos - $offset));
50605 $offset = $pos + strlen($text);
50606
50607
50608  if ($open = '/' != $text[1]) {
50609 $tag = $matches[1][$i][0];
50610 } else {
50611 $tag = isset($matches[3][$i][0]) ? $matches[3][$i][0] : '';
50612 }
50613
50614 if (!$open && !$tag) {
50615
50616  $this->styleStack->pop();
50617 } elseif (false === $style = $this->createStyleFromString(strtolower($tag))) {
50618 $output .= $this->applyCurrentStyle($text);
50619 } elseif ($open) {
50620 $this->styleStack->push($style);
50621 } else {
50622 $this->styleStack->pop($style);
50623 }
50624 }
50625
50626 $output .= $this->applyCurrentStyle(substr($message, $offset));
50627
50628 if (false !== strpos($output, '<<')) {
50629 return strtr($output, array('\\<' => '<', '<<' => '\\'));
50630 }
50631
50632 return str_replace('\\<', '<', $output);
50633 }
50634
50635
50636
50637
50638 public function getStyleStack()
50639 {
50640 return $this->styleStack;
50641 }
50642
50643
50644
50645
50646
50647
50648
50649
50650 private function createStyleFromString($string)
50651 {
50652 if (isset($this->styles[$string])) {
50653 return $this->styles[$string];
50654 }
50655
50656 if (!preg_match_all('/([^=]+)=([^;]+)(;|$)/', strtolower($string), $matches, PREG_SET_ORDER)) {
50657 return false;
50658 }
50659
50660 $style = new OutputFormatterStyle();
50661 foreach ($matches as $match) {
50662 array_shift($match);
50663
50664 if ('fg' == $match[0]) {
50665 $style->setForeground($match[1]);
50666 } elseif ('bg' == $match[0]) {
50667 $style->setBackground($match[1]);
50668 } else {
50669 try {
50670 $style->setOption($match[1]);
50671 } catch (\InvalidArgumentException $e) {
50672 return false;
50673 }
50674 }
50675 }
50676
50677 return $style;
50678 }
50679
50680
50681
50682
50683
50684
50685
50686
50687 private function applyCurrentStyle($text)
50688 {
50689 return $this->isDecorated() && strlen($text) > 0 ? $this->styleStack->getCurrent()->apply($text) : $text;
50690 }
50691 }
50692 <?php
50693
50694
50695
50696
50697
50698
50699
50700
50701
50702
50703 namespace Symfony\Component\Console\Formatter;
50704
50705
50706
50707
50708
50709
50710 interface OutputFormatterInterface
50711 {
50712
50713
50714
50715
50716
50717 public function setDecorated($decorated);
50718
50719
50720
50721
50722
50723
50724 public function isDecorated();
50725
50726
50727
50728
50729
50730
50731
50732 public function setStyle($name, OutputFormatterStyleInterface $style);
50733
50734
50735
50736
50737
50738
50739
50740
50741 public function hasStyle($name);
50742
50743
50744
50745
50746
50747
50748
50749
50750
50751
50752 public function getStyle($name);
50753
50754
50755
50756
50757
50758
50759
50760
50761 public function format($message);
50762 }
50763 <?php
50764
50765
50766
50767
50768
50769
50770
50771
50772
50773
50774 namespace Symfony\Component\Console\Formatter;
50775
50776 use Symfony\Component\Console\Exception\InvalidArgumentException;
50777
50778
50779
50780
50781
50782
50783 class OutputFormatterStyle implements OutputFormatterStyleInterface
50784 {
50785 private static $availableForegroundColors = array(
50786 'black' => array('set' => 30, 'unset' => 39),
50787 'red' => array('set' => 31, 'unset' => 39),
50788 'green' => array('set' => 32, 'unset' => 39),
50789 'yellow' => array('set' => 33, 'unset' => 39),
50790 'blue' => array('set' => 34, 'unset' => 39),
50791 'magenta' => array('set' => 35, 'unset' => 39),
50792 'cyan' => array('set' => 36, 'unset' => 39),
50793 'white' => array('set' => 37, 'unset' => 39),
50794 'default' => array('set' => 39, 'unset' => 39),
50795 );
50796 private static $availableBackgroundColors = array(
50797 'black' => array('set' => 40, 'unset' => 49),
50798 'red' => array('set' => 41, 'unset' => 49),
50799 'green' => array('set' => 42, 'unset' => 49),
50800 'yellow' => array('set' => 43, 'unset' => 49),
50801 'blue' => array('set' => 44, 'unset' => 49),
50802 'magenta' => array('set' => 45, 'unset' => 49),
50803 'cyan' => array('set' => 46, 'unset' => 49),
50804 'white' => array('set' => 47, 'unset' => 49),
50805 'default' => array('set' => 49, 'unset' => 49),
50806 );
50807 private static $availableOptions = array(
50808 'bold' => array('set' => 1, 'unset' => 22),
50809 'underscore' => array('set' => 4, 'unset' => 24),
50810 'blink' => array('set' => 5, 'unset' => 25),
50811 'reverse' => array('set' => 7, 'unset' => 27),
50812 'conceal' => array('set' => 8, 'unset' => 28),
50813 );
50814
50815 private $foreground;
50816 private $background;
50817 private $options = array();
50818
50819
50820
50821
50822
50823
50824
50825
50826 public function __construct($foreground = null, $background = null, array $options = array())
50827 {
50828 if (null !== $foreground) {
50829 $this->setForeground($foreground);
50830 }
50831 if (null !== $background) {
50832 $this->setBackground($background);
50833 }
50834 if (count($options)) {
50835 $this->setOptions($options);
50836 }
50837 }
50838
50839
50840
50841
50842
50843
50844
50845
50846 public function setForeground($color = null)
50847 {
50848 if (null === $color) {
50849 $this->foreground = null;
50850
50851 return;
50852 }
50853
50854 if (!isset(static::$availableForegroundColors[$color])) {
50855 throw new InvalidArgumentException(sprintf(
50856 'Invalid foreground color specified: "%s". Expected one of (%s)',
50857 $color,
50858 implode(', ', array_keys(static::$availableForegroundColors))
50859 ));
50860 }
50861
50862 $this->foreground = static::$availableForegroundColors[$color];
50863 }
50864
50865
50866
50867
50868
50869
50870
50871
50872 public function setBackground($color = null)
50873 {
50874 if (null === $color) {
50875 $this->background = null;
50876
50877 return;
50878 }
50879
50880 if (!isset(static::$availableBackgroundColors[$color])) {
50881 throw new InvalidArgumentException(sprintf(
50882 'Invalid background color specified: "%s". Expected one of (%s)',
50883 $color,
50884 implode(', ', array_keys(static::$availableBackgroundColors))
50885 ));
50886 }
50887
50888 $this->background = static::$availableBackgroundColors[$color];
50889 }
50890
50891
50892
50893
50894
50895
50896
50897
50898 public function setOption($option)
50899 {
50900 if (!isset(static::$availableOptions[$option])) {
50901 throw new InvalidArgumentException(sprintf(
50902 'Invalid option specified: "%s". Expected one of (%s)',
50903 $option,
50904 implode(', ', array_keys(static::$availableOptions))
50905 ));
50906 }
50907
50908 if (!in_array(static::$availableOptions[$option], $this->options)) {
50909 $this->options[] = static::$availableOptions[$option];
50910 }
50911 }
50912
50913
50914
50915
50916
50917
50918
50919
50920 public function unsetOption($option)
50921 {
50922 if (!isset(static::$availableOptions[$option])) {
50923 throw new InvalidArgumentException(sprintf(
50924 'Invalid option specified: "%s". Expected one of (%s)',
50925 $option,
50926 implode(', ', array_keys(static::$availableOptions))
50927 ));
50928 }
50929
50930 $pos = array_search(static::$availableOptions[$option], $this->options);
50931 if (false !== $pos) {
50932 unset($this->options[$pos]);
50933 }
50934 }
50935
50936
50937
50938
50939
50940
50941 public function setOptions(array $options)
50942 {
50943 $this->options = array();
50944
50945 foreach ($options as $option) {
50946 $this->setOption($option);
50947 }
50948 }
50949
50950
50951
50952
50953
50954
50955
50956
50957 public function apply($text)
50958 {
50959 $setCodes = array();
50960 $unsetCodes = array();
50961
50962 if (null !== $this->foreground) {
50963 $setCodes[] = $this->foreground['set'];
50964 $unsetCodes[] = $this->foreground['unset'];
50965 }
50966 if (null !== $this->background) {
50967 $setCodes[] = $this->background['set'];
50968 $unsetCodes[] = $this->background['unset'];
50969 }
50970 if (count($this->options)) {
50971 foreach ($this->options as $option) {
50972 $setCodes[] = $option['set'];
50973 $unsetCodes[] = $option['unset'];
50974 }
50975 }
50976
50977 if (0 === count($setCodes)) {
50978 return $text;
50979 }
50980
50981 return sprintf("\033[%sm%s\033[%sm", implode(';', $setCodes), $text, implode(';', $unsetCodes));
50982 }
50983 }
50984 <?php
50985
50986
50987
50988
50989
50990
50991
50992
50993
50994
50995 namespace Symfony\Component\Console\Formatter;
50996
50997
50998
50999
51000
51001
51002 interface OutputFormatterStyleInterface
51003 {
51004
51005
51006
51007
51008
51009 public function setForeground($color = null);
51010
51011
51012
51013
51014
51015
51016 public function setBackground($color = null);
51017
51018
51019
51020
51021
51022
51023 public function setOption($option);
51024
51025
51026
51027
51028
51029
51030 public function unsetOption($option);
51031
51032
51033
51034
51035
51036
51037 public function setOptions(array $options);
51038
51039
51040
51041
51042
51043
51044
51045
51046 public function apply($text);
51047 }
51048 <?php
51049
51050
51051
51052
51053
51054
51055
51056
51057
51058
51059 namespace Symfony\Component\Console\Formatter;
51060
51061 use Symfony\Component\Console\Exception\InvalidArgumentException;
51062
51063
51064
51065
51066 class OutputFormatterStyleStack
51067 {
51068
51069
51070
51071 private $styles;
51072
51073
51074
51075
51076 private $emptyStyle;
51077
51078
51079
51080
51081
51082
51083 public function __construct(OutputFormatterStyleInterface $emptyStyle = null)
51084 {
51085 $this->emptyStyle = $emptyStyle ?: new OutputFormatterStyle();
51086 $this->reset();
51087 }
51088
51089
51090
51091
51092 public function reset()
51093 {
51094 $this->styles = array();
51095 }
51096
51097
51098
51099
51100
51101
51102 public function push(OutputFormatterStyleInterface $style)
51103 {
51104 $this->styles[] = $style;
51105 }
51106
51107
51108
51109
51110
51111
51112
51113
51114
51115
51116 public function pop(OutputFormatterStyleInterface $style = null)
51117 {
51118 if (empty($this->styles)) {
51119 return $this->emptyStyle;
51120 }
51121
51122 if (null === $style) {
51123 return array_pop($this->styles);
51124 }
51125
51126 foreach (array_reverse($this->styles, true) as $index => $stackedStyle) {
51127 if ($style->apply('') === $stackedStyle->apply('')) {
51128 $this->styles = array_slice($this->styles, 0, $index);
51129
51130 return $stackedStyle;
51131 }
51132 }
51133
51134 throw new InvalidArgumentException('Incorrectly nested style tag found.');
51135 }
51136
51137
51138
51139
51140
51141
51142 public function getCurrent()
51143 {
51144 if (empty($this->styles)) {
51145 return $this->emptyStyle;
51146 }
51147
51148 return $this->styles[count($this->styles) - 1];
51149 }
51150
51151
51152
51153
51154
51155
51156 public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle)
51157 {
51158 $this->emptyStyle = $emptyStyle;
51159
51160 return $this;
51161 }
51162
51163
51164
51165
51166 public function getEmptyStyle()
51167 {
51168 return $this->emptyStyle;
51169 }
51170 }
51171 <?php
51172
51173
51174
51175
51176
51177
51178
51179
51180
51181
51182 namespace Symfony\Component\Console\Helper;
51183
51184
51185
51186
51187
51188
51189
51190
51191 class DebugFormatterHelper extends Helper
51192 {
51193 private $colors = array('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default');
51194 private $started = array();
51195 private $count = -1;
51196
51197
51198
51199
51200
51201
51202
51203
51204
51205
51206 public function start($id, $message, $prefix = 'RUN')
51207 {
51208 $this->started[$id] = array('border' => ++$this->count % count($this->colors));
51209
51210 return sprintf("%s<bg=blue;fg=white> %s </> <fg=blue>%s</>\n", $this->getBorder($id), $prefix, $message);
51211 }
51212
51213
51214
51215
51216
51217
51218
51219
51220
51221
51222
51223
51224 public function progress($id, $buffer, $error = false, $prefix = 'OUT', $errorPrefix = 'ERR')
51225 {
51226 $message = '';
51227
51228 if ($error) {
51229 if (isset($this->started[$id]['out'])) {
51230 $message .= "\n";
51231 unset($this->started[$id]['out']);
51232 }
51233 if (!isset($this->started[$id]['err'])) {
51234 $message .= sprintf('%s<bg=red;fg=white> %s </> ', $this->getBorder($id), $errorPrefix);
51235 $this->started[$id]['err'] = true;
51236 }
51237
51238 $message .= str_replace("\n", sprintf("\n%s<bg=red;fg=white> %s </> ", $this->getBorder($id), $errorPrefix), $buffer);
51239 } else {
51240 if (isset($this->started[$id]['err'])) {
51241 $message .= "\n";
51242 unset($this->started[$id]['err']);
51243 }
51244 if (!isset($this->started[$id]['out'])) {
51245 $message .= sprintf('%s<bg=green;fg=white> %s </> ', $this->getBorder($id), $prefix);
51246 $this->started[$id]['out'] = true;
51247 }
51248
51249 $message .= str_replace("\n", sprintf("\n%s<bg=green;fg=white> %s </> ", $this->getBorder($id), $prefix), $buffer);
51250 }
51251
51252 return $message;
51253 }
51254
51255
51256
51257
51258
51259
51260
51261
51262
51263
51264
51265 public function stop($id, $message, $successful, $prefix = 'RES')
51266 {
51267 $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : '';
51268
51269 if ($successful) {
51270 return sprintf("%s%s<bg=green;fg=white> %s </> <fg=green>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
51271 }
51272
51273 $message = sprintf("%s%s<bg=red;fg=white> %s </> <fg=red>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
51274
51275 unset($this->started[$id]['out'], $this->started[$id]['err']);
51276
51277 return $message;
51278 }
51279
51280
51281
51282
51283
51284
51285 private function getBorder($id)
51286 {
51287 return sprintf('<bg=%s> </>', $this->colors[$this->started[$id]['border']]);
51288 }
51289
51290
51291
51292
51293 public function getName()
51294 {
51295 return 'debug_formatter';
51296 }
51297 }
51298 <?php
51299
51300
51301
51302
51303
51304
51305
51306
51307
51308
51309 namespace Symfony\Component\Console\Helper;
51310
51311 use Symfony\Component\Console\Descriptor\DescriptorInterface;
51312 use Symfony\Component\Console\Descriptor\JsonDescriptor;
51313 use Symfony\Component\Console\Descriptor\MarkdownDescriptor;
51314 use Symfony\Component\Console\Descriptor\TextDescriptor;
51315 use Symfony\Component\Console\Descriptor\XmlDescriptor;
51316 use Symfony\Component\Console\Output\OutputInterface;
51317 use Symfony\Component\Console\Exception\InvalidArgumentException;
51318
51319
51320
51321
51322
51323
51324 class DescriptorHelper extends Helper
51325 {
51326
51327
51328
51329 private $descriptors = array();
51330
51331
51332
51333
51334 public function __construct()
51335 {
51336 $this
51337 ->register('txt', new TextDescriptor())
51338 ->register('xml', new XmlDescriptor())
51339 ->register('json', new JsonDescriptor())
51340 ->register('md', new MarkdownDescriptor())
51341 ;
51342 }
51343
51344
51345
51346
51347
51348
51349
51350
51351
51352
51353
51354
51355
51356
51357 public function describe(OutputInterface $output, $object, array $options = array())
51358 {
51359 $options = array_merge(array(
51360 'raw_text' => false,
51361 'format' => 'txt',
51362 ), $options);
51363
51364 if (!isset($this->descriptors[$options['format']])) {
51365 throw new InvalidArgumentException(sprintf('Unsupported format "%s".', $options['format']));
51366 }
51367
51368 $descriptor = $this->descriptors[$options['format']];
51369 $descriptor->describe($output, $object, $options);
51370 }
51371
51372
51373
51374
51375
51376
51377
51378
51379
51380 public function register($format, DescriptorInterface $descriptor)
51381 {
51382 $this->descriptors[$format] = $descriptor;
51383
51384 return $this;
51385 }
51386
51387
51388
51389
51390 public function getName()
51391 {
51392 return 'descriptor';
51393 }
51394 }
51395 <?php
51396
51397
51398
51399
51400
51401
51402
51403
51404
51405
51406 namespace Symfony\Component\Console\Helper;
51407
51408 use Symfony\Component\Console\Exception\InvalidArgumentException;
51409 use Symfony\Component\Console\Exception\RuntimeException;
51410 use Symfony\Component\Console\Output\ConsoleOutputInterface;
51411 use Symfony\Component\Console\Output\OutputInterface;
51412 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
51413
51414
51415
51416
51417
51418
51419
51420
51421
51422 class DialogHelper extends InputAwareHelper
51423 {
51424 private $inputStream;
51425 private static $shell;
51426 private static $stty;
51427
51428 public function __construct($triggerDeprecationError = true)
51429 {
51430 if ($triggerDeprecationError) {
51431 @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);
51432 }
51433 }
51434
51435
51436
51437
51438
51439
51440
51441
51442
51443
51444
51445
51446
51447
51448
51449
51450 public function select(OutputInterface $output, $question, $choices, $default = null, $attempts = false, $errorMessage = 'Value "%s" is invalid', $multiselect = false)
51451 {
51452 if ($output instanceof ConsoleOutputInterface) {
51453 $output = $output->getErrorOutput();
51454 }
51455
51456 $width = max(array_map('strlen', array_keys($choices)));
51457
51458 $messages = (array) $question;
51459 foreach ($choices as $key => $value) {
51460 $messages[] = sprintf("  [<info>%-{$width}s</info>] %s", $key, $value);
51461 }
51462
51463 $output->writeln($messages);
51464
51465 $result = $this->askAndValidate($output, '> ', function ($picked) use ($choices, $errorMessage, $multiselect) {
51466
51467  $selectedChoices = str_replace(' ', '', $picked);
51468
51469 if ($multiselect) {
51470
51471  if (!preg_match('/^[a-zA-Z0-9_-]+(?:,[a-zA-Z0-9_-]+)*$/', $selectedChoices, $matches)) {
51472 throw new InvalidArgumentException(sprintf($errorMessage, $picked));
51473 }
51474 $selectedChoices = explode(',', $selectedChoices);
51475 } else {
51476 $selectedChoices = array($picked);
51477 }
51478
51479 $multiselectChoices = array();
51480
51481 foreach ($selectedChoices as $value) {
51482 if (empty($choices[$value])) {
51483 throw new InvalidArgumentException(sprintf($errorMessage, $value));
51484 }
51485 $multiselectChoices[] = $value;
51486 }
51487
51488 if ($multiselect) {
51489 return $multiselectChoices;
51490 }
51491
51492 return $picked;
51493 }, $attempts, $default);
51494
51495 return $result;
51496 }
51497
51498
51499
51500
51501
51502
51503
51504
51505
51506
51507
51508
51509
51510 public function ask(OutputInterface $output, $question, $default = null, array $autocomplete = null)
51511 {
51512 if ($this->input && !$this->input->isInteractive()) {
51513 return $default;
51514 }
51515
51516 if ($output instanceof ConsoleOutputInterface) {
51517 $output = $output->getErrorOutput();
51518 }
51519
51520 $output->write($question);
51521
51522 $inputStream = $this->inputStream ?: STDIN;
51523
51524 if (null === $autocomplete || !$this->hasSttyAvailable()) {
51525 $ret = fgets($inputStream, 4096);
51526 if (false === $ret) {
51527 throw new RuntimeException('Aborted');
51528 }
51529 $ret = trim($ret);
51530 } else {
51531 $ret = '';
51532
51533 $i = 0;
51534 $ofs = -1;
51535 $matches = $autocomplete;
51536 $numMatches = count($matches);
51537
51538 $sttyMode = shell_exec('stty -g');
51539
51540
51541  shell_exec('stty -icanon -echo');
51542
51543
51544  $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
51545
51546
51547  while (!feof($inputStream)) {
51548 $c = fread($inputStream, 1);
51549
51550
51551  if ("\177" === $c) {
51552 if (0 === $numMatches && 0 !== $i) {
51553 --$i;
51554
51555  $output->write("\033[1D");
51556 }
51557
51558 if ($i === 0) {
51559 $ofs = -1;
51560 $matches = $autocomplete;
51561 $numMatches = count($matches);
51562 } else {
51563 $numMatches = 0;
51564 }
51565
51566
51567  $ret = substr($ret, 0, $i);
51568 } elseif ("\033" === $c) {
51569
51570  $c .= fread($inputStream, 2);
51571
51572
51573  if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
51574 if ('A' === $c[2] && -1 === $ofs) {
51575 $ofs = 0;
51576 }
51577
51578 if (0 === $numMatches) {
51579 continue;
51580 }
51581
51582 $ofs += ('A' === $c[2]) ? -1 : 1;
51583 $ofs = ($numMatches + $ofs) % $numMatches;
51584 }
51585 } elseif (ord($c) < 32) {
51586 if ("\t" === $c || "\n" === $c) {
51587 if ($numMatches > 0 && -1 !== $ofs) {
51588 $ret = $matches[$ofs];
51589
51590  $output->write(substr($ret, $i));
51591 $i = strlen($ret);
51592 }
51593
51594 if ("\n" === $c) {
51595 $output->write($c);
51596 break;
51597 }
51598
51599 $numMatches = 0;
51600 }
51601
51602 continue;
51603 } else {
51604 $output->write($c);
51605 $ret .= $c;
51606 ++$i;
51607
51608 $numMatches = 0;
51609 $ofs = 0;
51610
51611 foreach ($autocomplete as $value) {
51612
51613  if (0 === strpos($value, $ret) && $i !== strlen($value)) {
51614 $matches[$numMatches++] = $value;
51615 }
51616 }
51617 }
51618
51619
51620  $output->write("\033[K");
51621
51622 if ($numMatches > 0 && -1 !== $ofs) {
51623
51624  $output->write("\0337");
51625
51626  $output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
51627
51628  $output->write("\0338");
51629 }
51630 }
51631
51632
51633  shell_exec(sprintf('stty %s', $sttyMode));
51634 }
51635
51636 return strlen($ret) > 0 ? $ret : $default;
51637 }
51638
51639
51640
51641
51642
51643
51644
51645
51646
51647
51648
51649
51650 public function askConfirmation(OutputInterface $output, $question, $default = true)
51651 {
51652 $answer = 'z';
51653 while ($answer && !in_array(strtolower($answer[0]), array('y', 'n'))) {
51654 $answer = $this->ask($output, $question);
51655 }
51656
51657 if (false === $default) {
51658 return $answer && 'y' == strtolower($answer[0]);
51659 }
51660
51661 return !$answer || 'y' == strtolower($answer[0]);
51662 }
51663
51664
51665
51666
51667
51668
51669
51670
51671
51672
51673
51674
51675 public function askHiddenResponse(OutputInterface $output, $question, $fallback = true)
51676 {
51677 if ($output instanceof ConsoleOutputInterface) {
51678 $output = $output->getErrorOutput();
51679 }
51680
51681 if ('\\' === DIRECTORY_SEPARATOR) {
51682 $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
51683
51684
51685  if ('phar:' === substr(__FILE__, 0, 5)) {
51686 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
51687 copy($exe, $tmpExe);
51688 $exe = $tmpExe;
51689 }
51690
51691 $output->write($question);
51692 $value = rtrim(shell_exec($exe));
51693 $output->writeln('');
51694
51695 if (isset($tmpExe)) {
51696 unlink($tmpExe);
51697 }
51698
51699 return $value;
51700 }
51701
51702 if ($this->hasSttyAvailable()) {
51703 $output->write($question);
51704
51705 $sttyMode = shell_exec('stty -g');
51706
51707 shell_exec('stty -echo');
51708 $value = fgets($this->inputStream ?: STDIN, 4096);
51709 shell_exec(sprintf('stty %s', $sttyMode));
51710
51711 if (false === $value) {
51712 throw new RuntimeException('Aborted');
51713 }
51714
51715 $value = trim($value);
51716 $output->writeln('');
51717
51718 return $value;
51719 }
51720
51721 if (false !== $shell = $this->getShell()) {
51722 $output->write($question);
51723 $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword';
51724 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
51725 $value = rtrim(shell_exec($command));
51726 $output->writeln('');
51727
51728 return $value;
51729 }
51730
51731 if ($fallback) {
51732 return $this->ask($output, $question);
51733 }
51734
51735 throw new RuntimeException('Unable to hide the response');
51736 }
51737
51738
51739
51740
51741
51742
51743
51744
51745
51746
51747
51748
51749
51750
51751
51752
51753
51754
51755
51756 public function askAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $default = null, array $autocomplete = null)
51757 {
51758 $that = $this;
51759
51760 $interviewer = function () use ($output, $question, $default, $autocomplete, $that) {
51761 return $that->ask($output, $question, $default, $autocomplete);
51762 };
51763
51764 return $this->validateAttempts($interviewer, $output, $validator, $attempts);
51765 }
51766
51767
51768
51769
51770
51771
51772
51773
51774
51775
51776
51777
51778
51779
51780
51781
51782
51783
51784
51785 public function askHiddenResponseAndValidate(OutputInterface $output, $question, $validator, $attempts = false, $fallback = true)
51786 {
51787 $that = $this;
51788
51789 $interviewer = function () use ($output, $question, $fallback, $that) {
51790 return $that->askHiddenResponse($output, $question, $fallback);
51791 };
51792
51793 return $this->validateAttempts($interviewer, $output, $validator, $attempts);
51794 }
51795
51796
51797
51798
51799
51800
51801
51802
51803 public function setInputStream($stream)
51804 {
51805 $this->inputStream = $stream;
51806 }
51807
51808
51809
51810
51811
51812
51813 public function getInputStream()
51814 {
51815 return $this->inputStream;
51816 }
51817
51818
51819
51820
51821 public function getName()
51822 {
51823 return 'dialog';
51824 }
51825
51826
51827
51828
51829
51830
51831 private function getShell()
51832 {
51833 if (null !== self::$shell) {
51834 return self::$shell;
51835 }
51836
51837 self::$shell = false;
51838
51839 if (file_exists('/usr/bin/env')) {
51840
51841  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
51842 foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
51843 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
51844 self::$shell = $sh;
51845 break;
51846 }
51847 }
51848 }
51849
51850 return self::$shell;
51851 }
51852
51853 private function hasSttyAvailable()
51854 {
51855 if (null !== self::$stty) {
51856 return self::$stty;
51857 }
51858
51859 exec('stty 2>&1', $output, $exitcode);
51860
51861 return self::$stty = $exitcode === 0;
51862 }
51863
51864
51865
51866
51867
51868
51869
51870
51871
51872
51873
51874
51875
51876 private function validateAttempts($interviewer, OutputInterface $output, $validator, $attempts)
51877 {
51878 if ($output instanceof ConsoleOutputInterface) {
51879 $output = $output->getErrorOutput();
51880 }
51881
51882 $e = null;
51883 while (false === $attempts || $attempts--) {
51884 if (null !== $e) {
51885 $output->writeln($this->getHelperSet()->get('formatter')->formatBlock($e->getMessage(), 'error'));
51886 }
51887
51888 try {
51889 return call_user_func($validator, $interviewer());
51890 } catch (\Exception $e) {
51891 }
51892 }
51893
51894 throw $e;
51895 }
51896 }
51897 <?php
51898
51899
51900
51901
51902
51903
51904
51905
51906
51907
51908 namespace Symfony\Component\Console\Helper;
51909
51910 use Symfony\Component\Console\Formatter\OutputFormatter;
51911
51912
51913
51914
51915
51916
51917 class FormatterHelper extends Helper
51918 {
51919
51920
51921
51922
51923
51924
51925
51926
51927
51928 public function formatSection($section, $message, $style = 'info')
51929 {
51930 return sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message);
51931 }
51932
51933
51934
51935
51936
51937
51938
51939
51940
51941
51942 public function formatBlock($messages, $style, $large = false)
51943 {
51944 if (!is_array($messages)) {
51945 $messages = array($messages);
51946 }
51947
51948 $len = 0;
51949 $lines = array();
51950 foreach ($messages as $message) {
51951 $message = OutputFormatter::escape($message);
51952 $lines[] = sprintf($large ? '  %s  ' : ' %s ', $message);
51953 $len = max($this->strlen($message) + ($large ? 4 : 2), $len);
51954 }
51955
51956 $messages = $large ? array(str_repeat(' ', $len)) : array();
51957 for ($i = 0; isset($lines[$i]); ++$i) {
51958 $messages[] = $lines[$i].str_repeat(' ', $len - $this->strlen($lines[$i]));
51959 }
51960 if ($large) {
51961 $messages[] = str_repeat(' ', $len);
51962 }
51963
51964 for ($i = 0; isset($messages[$i]); ++$i) {
51965 $messages[$i] = sprintf('<%s>%s</%s>', $style, $messages[$i], $style);
51966 }
51967
51968 return implode("\n", $messages);
51969 }
51970
51971
51972
51973
51974 public function getName()
51975 {
51976 return 'formatter';
51977 }
51978 }
51979 <?php
51980
51981
51982
51983
51984
51985
51986
51987
51988
51989
51990 namespace Symfony\Component\Console\Helper;
51991
51992 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
51993
51994
51995
51996
51997
51998
51999 abstract class Helper implements HelperInterface
52000 {
52001 protected $helperSet = null;
52002
52003
52004
52005
52006
52007
52008 public function setHelperSet(HelperSet $helperSet = null)
52009 {
52010 $this->helperSet = $helperSet;
52011 }
52012
52013
52014
52015
52016
52017
52018 public function getHelperSet()
52019 {
52020 return $this->helperSet;
52021 }
52022
52023
52024
52025
52026
52027
52028
52029
52030 public static function strlen($string)
52031 {
52032 if (false === $encoding = mb_detect_encoding($string, null, true)) {
52033 return strlen($string);
52034 }
52035
52036 return mb_strwidth($string, $encoding);
52037 }
52038
52039 public static function formatTime($secs)
52040 {
52041 static $timeFormats = array(
52042 array(0, '< 1 sec'),
52043 array(1, '1 sec'),
52044 array(2, 'secs', 1),
52045 array(60, '1 min'),
52046 array(120, 'mins', 60),
52047 array(3600, '1 hr'),
52048 array(7200, 'hrs', 3600),
52049 array(86400, '1 day'),
52050 array(172800, 'days', 86400),
52051 );
52052
52053 foreach ($timeFormats as $index => $format) {
52054 if ($secs >= $format[0]) {
52055 if ((isset($timeFormats[$index + 1]) && $secs < $timeFormats[$index + 1][0])
52056 || $index == count($timeFormats) - 1
52057 ) {
52058 if (2 == count($format)) {
52059 return $format[1];
52060 }
52061
52062 return floor($secs / $format[2]).' '.$format[1];
52063 }
52064 }
52065 }
52066 }
52067
52068 public static function formatMemory($memory)
52069 {
52070 if ($memory >= 1024 * 1024 * 1024) {
52071 return sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024);
52072 }
52073
52074 if ($memory >= 1024 * 1024) {
52075 return sprintf('%.1f MiB', $memory / 1024 / 1024);
52076 }
52077
52078 if ($memory >= 1024) {
52079 return sprintf('%d KiB', $memory / 1024);
52080 }
52081
52082 return sprintf('%d B', $memory);
52083 }
52084
52085 public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string)
52086 {
52087 return self::strlen(self::removeDecoration($formatter, $string));
52088 }
52089
52090 public static function removeDecoration(OutputFormatterInterface $formatter, $string)
52091 {
52092 $isDecorated = $formatter->isDecorated();
52093 $formatter->setDecorated(false);
52094
52095  $string = $formatter->format($string);
52096
52097  $string = preg_replace("/\033\[[^m]*m/", '', $string);
52098 $formatter->setDecorated($isDecorated);
52099
52100 return $string;
52101 }
52102 }
52103 <?php
52104
52105
52106
52107
52108
52109
52110
52111
52112
52113
52114 namespace Symfony\Component\Console\Helper;
52115
52116
52117
52118
52119
52120
52121 interface HelperInterface
52122 {
52123
52124
52125
52126
52127
52128 public function setHelperSet(HelperSet $helperSet = null);
52129
52130
52131
52132
52133
52134
52135 public function getHelperSet();
52136
52137
52138
52139
52140
52141
52142 public function getName();
52143 }
52144 <?php
52145
52146
52147
52148
52149
52150
52151
52152
52153
52154
52155 namespace Symfony\Component\Console\Helper;
52156
52157 use Symfony\Component\Console\Command\Command;
52158 use Symfony\Component\Console\Exception\InvalidArgumentException;
52159
52160
52161
52162
52163
52164
52165 class HelperSet implements \IteratorAggregate
52166 {
52167
52168
52169
52170 private $helpers = array();
52171 private $command;
52172
52173
52174
52175
52176
52177
52178 public function __construct(array $helpers = array())
52179 {
52180 foreach ($helpers as $alias => $helper) {
52181 $this->set($helper, is_int($alias) ? null : $alias);
52182 }
52183 }
52184
52185
52186
52187
52188
52189
52190
52191 public function set(HelperInterface $helper, $alias = null)
52192 {
52193 $this->helpers[$helper->getName()] = $helper;
52194 if (null !== $alias) {
52195 $this->helpers[$alias] = $helper;
52196 }
52197
52198 $helper->setHelperSet($this);
52199 }
52200
52201
52202
52203
52204
52205
52206
52207
52208 public function has($name)
52209 {
52210 return isset($this->helpers[$name]);
52211 }
52212
52213
52214
52215
52216
52217
52218
52219
52220
52221
52222 public function get($name)
52223 {
52224 if (!$this->has($name)) {
52225 throw new InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
52226 }
52227
52228 if ('dialog' === $name && $this->helpers[$name] instanceof DialogHelper) {
52229 @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);
52230 } elseif ('progress' === $name && $this->helpers[$name] instanceof ProgressHelper) {
52231 @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);
52232 } elseif ('table' === $name && $this->helpers[$name] instanceof TableHelper) {
52233 @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);
52234 }
52235
52236 return $this->helpers[$name];
52237 }
52238
52239
52240
52241
52242
52243
52244 public function setCommand(Command $command = null)
52245 {
52246 $this->command = $command;
52247 }
52248
52249
52250
52251
52252
52253
52254 public function getCommand()
52255 {
52256 return $this->command;
52257 }
52258
52259
52260
52261
52262 public function getIterator()
52263 {
52264 return new \ArrayIterator($this->helpers);
52265 }
52266 }
52267 <?php
52268
52269
52270
52271
52272
52273
52274
52275
52276
52277
52278 namespace Symfony\Component\Console\Helper;
52279
52280 use Symfony\Component\Console\Input\InputInterface;
52281 use Symfony\Component\Console\Input\InputAwareInterface;
52282
52283
52284
52285
52286
52287
52288 abstract class InputAwareHelper extends Helper implements InputAwareInterface
52289 {
52290 protected $input;
52291
52292
52293
52294
52295 public function setInput(InputInterface $input)
52296 {
52297 $this->input = $input;
52298 }
52299 }
52300 <?php
52301
52302
52303
52304
52305
52306
52307
52308
52309
52310
52311 namespace Symfony\Component\Console\Helper;
52312
52313 use Symfony\Component\Console\Output\ConsoleOutputInterface;
52314 use Symfony\Component\Console\Output\OutputInterface;
52315 use Symfony\Component\Process\Exception\ProcessFailedException;
52316 use Symfony\Component\Process\Process;
52317 use Symfony\Component\Process\ProcessBuilder;
52318
52319
52320
52321
52322
52323
52324 class ProcessHelper extends Helper
52325 {
52326
52327
52328
52329
52330
52331
52332
52333
52334
52335
52336
52337
52338 public function run(OutputInterface $output, $cmd, $error = null, $callback = null, $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE)
52339 {
52340 if ($output instanceof ConsoleOutputInterface) {
52341 $output = $output->getErrorOutput();
52342 }
52343
52344 $formatter = $this->getHelperSet()->get('debug_formatter');
52345
52346 if (is_array($cmd)) {
52347 $process = ProcessBuilder::create($cmd)->getProcess();
52348 } elseif ($cmd instanceof Process) {
52349 $process = $cmd;
52350 } else {
52351 $process = new Process($cmd);
52352 }
52353
52354 if ($verbosity <= $output->getVerbosity()) {
52355 $output->write($formatter->start(spl_object_hash($process), $this->escapeString($process->getCommandLine())));
52356 }
52357
52358 if ($output->isDebug()) {
52359 $callback = $this->wrapCallback($output, $process, $callback);
52360 }
52361
52362 $process->run($callback);
52363
52364 if ($verbosity <= $output->getVerbosity()) {
52365 $message = $process->isSuccessful() ? 'Command ran successfully' : sprintf('%s Command did not run successfully', $process->getExitCode());
52366 $output->write($formatter->stop(spl_object_hash($process), $message, $process->isSuccessful()));
52367 }
52368
52369 if (!$process->isSuccessful() && null !== $error) {
52370 $output->writeln(sprintf('<error>%s</error>', $this->escapeString($error)));
52371 }
52372
52373 return $process;
52374 }
52375
52376
52377
52378
52379
52380
52381
52382
52383
52384
52385
52386
52387
52388
52389
52390
52391
52392
52393
52394 public function mustRun(OutputInterface $output, $cmd, $error = null, $callback = null)
52395 {
52396 $process = $this->run($output, $cmd, $error, $callback);
52397
52398 if (!$process->isSuccessful()) {
52399 throw new ProcessFailedException($process);
52400 }
52401
52402 return $process;
52403 }
52404
52405
52406
52407
52408
52409
52410
52411
52412
52413
52414 public function wrapCallback(OutputInterface $output, Process $process, $callback = null)
52415 {
52416 if ($output instanceof ConsoleOutputInterface) {
52417 $output = $output->getErrorOutput();
52418 }
52419
52420 $formatter = $this->getHelperSet()->get('debug_formatter');
52421
52422 $that = $this;
52423
52424 return function ($type, $buffer) use ($output, $process, $callback, $formatter, $that) {
52425 $output->write($formatter->progress(spl_object_hash($process), $that->escapeString($buffer), Process::ERR === $type));
52426
52427 if (null !== $callback) {
52428 call_user_func($callback, $type, $buffer);
52429 }
52430 };
52431 }
52432
52433
52434
52435
52436
52437
52438 public function escapeString($str)
52439 {
52440 return str_replace('<', '\\<', $str);
52441 }
52442
52443
52444
52445
52446 public function getName()
52447 {
52448 return 'process';
52449 }
52450 }
52451 <?php
52452
52453
52454
52455
52456
52457
52458
52459
52460
52461
52462 namespace Symfony\Component\Console\Helper;
52463
52464 use Symfony\Component\Console\Output\ConsoleOutputInterface;
52465 use Symfony\Component\Console\Output\OutputInterface;
52466 use Symfony\Component\Console\Exception\LogicException;
52467
52468
52469
52470
52471
52472
52473
52474 class ProgressBar
52475 {
52476
52477  private $barWidth = 28;
52478 private $barChar;
52479 private $emptyBarChar = '-';
52480 private $progressChar = '>';
52481 private $format;
52482 private $internalFormat;
52483 private $redrawFreq = 1;
52484
52485
52486
52487
52488 private $output;
52489 private $step = 0;
52490 private $max;
52491 private $startTime;
52492 private $stepWidth;
52493 private $percent = 0.0;
52494 private $formatLineCount;
52495 private $messages = array();
52496 private $overwrite = true;
52497 private $firstRun = true;
52498
52499 private static $formatters;
52500 private static $formats;
52501
52502
52503
52504
52505
52506
52507
52508 public function __construct(OutputInterface $output, $max = 0)
52509 {
52510 if ($output instanceof ConsoleOutputInterface) {
52511 $output = $output->getErrorOutput();
52512 }
52513
52514 $this->output = $output;
52515 $this->setMaxSteps($max);
52516
52517 if (!$this->output->isDecorated()) {
52518
52519  $this->overwrite = false;
52520
52521
52522  $this->setRedrawFrequency($max / 10);
52523 }
52524
52525 $this->startTime = time();
52526 }
52527
52528
52529
52530
52531
52532
52533
52534
52535
52536 public static function setPlaceholderFormatterDefinition($name, $callable)
52537 {
52538 if (!self::$formatters) {
52539 self::$formatters = self::initPlaceholderFormatters();
52540 }
52541
52542 self::$formatters[$name] = $callable;
52543 }
52544
52545
52546
52547
52548
52549
52550
52551
52552 public static function getPlaceholderFormatterDefinition($name)
52553 {
52554 if (!self::$formatters) {
52555 self::$formatters = self::initPlaceholderFormatters();
52556 }
52557
52558 return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
52559 }
52560
52561
52562
52563
52564
52565
52566
52567
52568
52569 public static function setFormatDefinition($name, $format)
52570 {
52571 if (!self::$formats) {
52572 self::$formats = self::initFormats();
52573 }
52574
52575 self::$formats[$name] = $format;
52576 }
52577
52578
52579
52580
52581
52582
52583
52584
52585 public static function getFormatDefinition($name)
52586 {
52587 if (!self::$formats) {
52588 self::$formats = self::initFormats();
52589 }
52590
52591 return isset(self::$formats[$name]) ? self::$formats[$name] : null;
52592 }
52593
52594
52595
52596
52597
52598
52599
52600
52601
52602
52603
52604 public function setMessage($message, $name = 'message')
52605 {
52606 $this->messages[$name] = $message;
52607 }
52608
52609 public function getMessage($name = 'message')
52610 {
52611 return $this->messages[$name];
52612 }
52613
52614
52615
52616
52617
52618
52619 public function getStartTime()
52620 {
52621 return $this->startTime;
52622 }
52623
52624
52625
52626
52627
52628
52629 public function getMaxSteps()
52630 {
52631 return $this->max;
52632 }
52633
52634
52635
52636
52637
52638
52639
52640
52641 public function getStep()
52642 {
52643 @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);
52644
52645 return $this->getProgress();
52646 }
52647
52648
52649
52650
52651
52652
52653 public function getProgress()
52654 {
52655 return $this->step;
52656 }
52657
52658
52659
52660
52661
52662
52663
52664
52665 public function getStepWidth()
52666 {
52667 return $this->stepWidth;
52668 }
52669
52670
52671
52672
52673
52674
52675 public function getProgressPercent()
52676 {
52677 return $this->percent;
52678 }
52679
52680
52681
52682
52683
52684
52685 public function setBarWidth($size)
52686 {
52687 $this->barWidth = (int) $size;
52688 }
52689
52690
52691
52692
52693
52694
52695 public function getBarWidth()
52696 {
52697 return $this->barWidth;
52698 }
52699
52700
52701
52702
52703
52704
52705 public function setBarCharacter($char)
52706 {
52707 $this->barChar = $char;
52708 }
52709
52710
52711
52712
52713
52714
52715 public function getBarCharacter()
52716 {
52717 if (null === $this->barChar) {
52718 return $this->max ? '=' : $this->emptyBarChar;
52719 }
52720
52721 return $this->barChar;
52722 }
52723
52724
52725
52726
52727
52728
52729 public function setEmptyBarCharacter($char)
52730 {
52731 $this->emptyBarChar = $char;
52732 }
52733
52734
52735
52736
52737
52738
52739 public function getEmptyBarCharacter()
52740 {
52741 return $this->emptyBarChar;
52742 }
52743
52744
52745
52746
52747
52748
52749 public function setProgressCharacter($char)
52750 {
52751 $this->progressChar = $char;
52752 }
52753
52754
52755
52756
52757
52758
52759 public function getProgressCharacter()
52760 {
52761 return $this->progressChar;
52762 }
52763
52764
52765
52766
52767
52768
52769 public function setFormat($format)
52770 {
52771 $this->format = null;
52772 $this->internalFormat = $format;
52773 }
52774
52775
52776
52777
52778
52779
52780 public function setRedrawFrequency($freq)
52781 {
52782 $this->redrawFreq = max((int) $freq, 1);
52783 }
52784
52785
52786
52787
52788
52789
52790 public function start($max = null)
52791 {
52792 $this->startTime = time();
52793 $this->step = 0;
52794 $this->percent = 0.0;
52795
52796 if (null !== $max) {
52797 $this->setMaxSteps($max);
52798 }
52799
52800 $this->display();
52801 }
52802
52803
52804
52805
52806
52807
52808
52809
52810 public function advance($step = 1)
52811 {
52812 $this->setProgress($this->step + $step);
52813 }
52814
52815
52816
52817
52818
52819
52820
52821
52822
52823
52824 public function setCurrent($step)
52825 {
52826 @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);
52827
52828 $this->setProgress($step);
52829 }
52830
52831
52832
52833
52834
52835
52836 public function setOverwrite($overwrite)
52837 {
52838 $this->overwrite = (bool) $overwrite;
52839 }
52840
52841
52842
52843
52844
52845
52846
52847
52848 public function setProgress($step)
52849 {
52850 $step = (int) $step;
52851 if ($step < $this->step) {
52852 throw new LogicException('You can\'t regress the progress bar.');
52853 }
52854
52855 if ($this->max && $step > $this->max) {
52856 $this->max = $step;
52857 }
52858
52859 $prevPeriod = (int) ($this->step / $this->redrawFreq);
52860 $currPeriod = (int) ($step / $this->redrawFreq);
52861 $this->step = $step;
52862 $this->percent = $this->max ? (float) $this->step / $this->max : 0;
52863 if ($prevPeriod !== $currPeriod || $this->max === $step) {
52864 $this->display();
52865 }
52866 }
52867
52868
52869
52870
52871 public function finish()
52872 {
52873 if (!$this->max) {
52874 $this->max = $this->step;
52875 }
52876
52877 if ($this->step === $this->max && !$this->overwrite) {
52878
52879  return;
52880 }
52881
52882 $this->setProgress($this->max);
52883 }
52884
52885
52886
52887
52888 public function display()
52889 {
52890 if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
52891 return;
52892 }
52893
52894 if (null === $this->format) {
52895 $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
52896 }
52897
52898
52899  $self = $this;
52900 $output = $this->output;
52901 $messages = $this->messages;
52902 $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self, $output, $messages) {
52903 if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
52904 $text = call_user_func($formatter, $self, $output);
52905 } elseif (isset($messages[$matches[1]])) {
52906 $text = $messages[$matches[1]];
52907 } else {
52908 return $matches[0];
52909 }
52910
52911 if (isset($matches[2])) {
52912 $text = sprintf('%'.$matches[2], $text);
52913 }
52914
52915 return $text;
52916 }, $this->format));
52917 }
52918
52919
52920
52921
52922
52923
52924
52925
52926 public function clear()
52927 {
52928 if (!$this->overwrite) {
52929 return;
52930 }
52931
52932 if (null === $this->format) {
52933 $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
52934 }
52935
52936 $this->overwrite('');
52937 }
52938
52939
52940
52941
52942
52943
52944 private function setRealFormat($format)
52945 {
52946
52947  if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) {
52948 $this->format = self::getFormatDefinition($format.'_nomax');
52949 } elseif (null !== self::getFormatDefinition($format)) {
52950 $this->format = self::getFormatDefinition($format);
52951 } else {
52952 $this->format = $format;
52953 }
52954
52955 $this->formatLineCount = substr_count($this->format, "\n");
52956 }
52957
52958
52959
52960
52961
52962
52963 private function setMaxSteps($max)
52964 {
52965 $this->max = max(0, (int) $max);
52966 $this->stepWidth = $this->max ? Helper::strlen($this->max) : 4;
52967 }
52968
52969
52970
52971
52972
52973
52974 private function overwrite($message)
52975 {
52976 if ($this->overwrite) {
52977 if (!$this->firstRun) {
52978
52979  $this->output->write("\x0D");
52980
52981
52982  $this->output->write("\x1B[2K");
52983
52984
52985  if ($this->formatLineCount > 0) {
52986 $this->output->write(str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount));
52987 }
52988 }
52989 } elseif ($this->step > 0) {
52990 $this->output->writeln('');
52991 }
52992
52993 $this->firstRun = false;
52994
52995 $this->output->write($message);
52996 }
52997
52998 private function determineBestFormat()
52999 {
53000 switch ($this->output->getVerbosity()) {
53001
53002  case OutputInterface::VERBOSITY_VERBOSE:
53003 return $this->max ? 'verbose' : 'verbose_nomax';
53004 case OutputInterface::VERBOSITY_VERY_VERBOSE:
53005 return $this->max ? 'very_verbose' : 'very_verbose_nomax';
53006 case OutputInterface::VERBOSITY_DEBUG:
53007 return $this->max ? 'debug' : 'debug_nomax';
53008 default:
53009 return $this->max ? 'normal' : 'normal_nomax';
53010 }
53011 }
53012
53013 private static function initPlaceholderFormatters()
53014 {
53015 return array(
53016 'bar' => function (ProgressBar $bar, OutputInterface $output) {
53017 $completeBars = floor($bar->getMaxSteps() > 0 ? $bar->getProgressPercent() * $bar->getBarWidth() : $bar->getProgress() % $bar->getBarWidth());
53018 $display = str_repeat($bar->getBarCharacter(), $completeBars);
53019 if ($completeBars < $bar->getBarWidth()) {
53020 $emptyBars = $bar->getBarWidth() - $completeBars - Helper::strlenWithoutDecoration($output->getFormatter(), $bar->getProgressCharacter());
53021 $display .= $bar->getProgressCharacter().str_repeat($bar->getEmptyBarCharacter(), $emptyBars);
53022 }
53023
53024 return $display;
53025 },
53026 'elapsed' => function (ProgressBar $bar) {
53027 return Helper::formatTime(time() - $bar->getStartTime());
53028 },
53029 'remaining' => function (ProgressBar $bar) {
53030 if (!$bar->getMaxSteps()) {
53031 throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.');
53032 }
53033
53034 if (!$bar->getProgress()) {
53035 $remaining = 0;
53036 } else {
53037 $remaining = round((time() - $bar->getStartTime()) / $bar->getProgress() * ($bar->getMaxSteps() - $bar->getProgress()));
53038 }
53039
53040 return Helper::formatTime($remaining);
53041 },
53042 'estimated' => function (ProgressBar $bar) {
53043 if (!$bar->getMaxSteps()) {
53044 throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.');
53045 }
53046
53047 if (!$bar->getProgress()) {
53048 $estimated = 0;
53049 } else {
53050 $estimated = round((time() - $bar->getStartTime()) / $bar->getProgress() * $bar->getMaxSteps());
53051 }
53052
53053 return Helper::formatTime($estimated);
53054 },
53055 'memory' => function (ProgressBar $bar) {
53056 return Helper::formatMemory(memory_get_usage(true));
53057 },
53058 'current' => function (ProgressBar $bar) {
53059 return str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', STR_PAD_LEFT);
53060 },
53061 'max' => function (ProgressBar $bar) {
53062 return $bar->getMaxSteps();
53063 },
53064 'percent' => function (ProgressBar $bar) {
53065 return floor($bar->getProgressPercent() * 100);
53066 },
53067 );
53068 }
53069
53070 private static function initFormats()
53071 {
53072 return array(
53073 'normal' => ' %current%/%max% [%bar%] %percent:3s%%',
53074 'normal_nomax' => ' %current% [%bar%]',
53075
53076 'verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%',
53077 'verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
53078
53079 'very_verbose' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%',
53080 'very_verbose_nomax' => ' %current% [%bar%] %elapsed:6s%',
53081
53082 'debug' => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%',
53083 'debug_nomax' => ' %current% [%bar%] %elapsed:6s% %memory:6s%',
53084 );
53085 }
53086 }
53087 <?php
53088
53089
53090
53091
53092
53093
53094
53095
53096
53097
53098 namespace Symfony\Component\Console\Helper;
53099
53100 use Symfony\Component\Console\Output\NullOutput;
53101 use Symfony\Component\Console\Output\ConsoleOutputInterface;
53102 use Symfony\Component\Console\Output\OutputInterface;
53103 use Symfony\Component\Console\Exception\LogicException;
53104
53105
53106
53107
53108
53109
53110
53111
53112
53113
53114 class ProgressHelper extends Helper
53115 {
53116 const FORMAT_QUIET = ' %percent%%';
53117 const FORMAT_NORMAL = ' %current%/%max% [%bar%] %percent%%';
53118 const FORMAT_VERBOSE = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%';
53119 const FORMAT_QUIET_NOMAX = ' %current%';
53120 const FORMAT_NORMAL_NOMAX = ' %current% [%bar%]';
53121 const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%';
53122
53123
53124  private $barWidth = 28;
53125 private $barChar = '=';
53126 private $emptyBarChar = '-';
53127 private $progressChar = '>';
53128 private $format = null;
53129 private $redrawFreq = 1;
53130
53131 private $lastMessagesLength;
53132 private $barCharOriginal;
53133
53134
53135
53136
53137 private $output;
53138
53139
53140
53141
53142
53143
53144 private $current;
53145
53146
53147
53148
53149
53150
53151 private $max;
53152
53153
53154
53155
53156
53157
53158 private $startTime;
53159
53160
53161
53162
53163
53164
53165 private $defaultFormatVars = array(
53166 'current',
53167 'max',
53168 'bar',
53169 'percent',
53170 'elapsed',
53171 );
53172
53173
53174
53175
53176
53177
53178 private $formatVars;
53179
53180
53181
53182
53183
53184
53185 private $widths = array(
53186 'current' => 4,
53187 'max' => 4,
53188 'percent' => 3,
53189 'elapsed' => 6,
53190 );
53191
53192
53193
53194
53195
53196
53197 private $timeFormats = array(
53198 array(0, '???'),
53199 array(2, '1 sec'),
53200 array(59, 'secs', 1),
53201 array(60, '1 min'),
53202 array(3600, 'mins', 60),
53203 array(5400, '1 hr'),
53204 array(86400, 'hrs', 3600),
53205 array(129600, '1 day'),
53206 array(604800, 'days', 86400),
53207 );
53208
53209 public function __construct($triggerDeprecationError = true)
53210 {
53211 if ($triggerDeprecationError) {
53212 @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);
53213 }
53214 }
53215
53216
53217
53218
53219
53220
53221 public function setBarWidth($size)
53222 {
53223 $this->barWidth = (int) $size;
53224 }
53225
53226
53227
53228
53229
53230
53231 public function setBarCharacter($char)
53232 {
53233 $this->barChar = $char;
53234 }
53235
53236
53237
53238
53239
53240
53241 public function setEmptyBarCharacter($char)
53242 {
53243 $this->emptyBarChar = $char;
53244 }
53245
53246
53247
53248
53249
53250
53251 public function setProgressCharacter($char)
53252 {
53253 $this->progressChar = $char;
53254 }
53255
53256
53257
53258
53259
53260
53261 public function setFormat($format)
53262 {
53263 $this->format = $format;
53264 }
53265
53266
53267
53268
53269
53270
53271 public function setRedrawFrequency($freq)
53272 {
53273 $this->redrawFreq = (int) $freq;
53274 }
53275
53276
53277
53278
53279
53280
53281
53282 public function start(OutputInterface $output, $max = null)
53283 {
53284 if ($output instanceof ConsoleOutputInterface) {
53285 $output = $output->getErrorOutput();
53286 }
53287
53288 $this->startTime = time();
53289 $this->current = 0;
53290 $this->max = (int) $max;
53291
53292
53293  $this->output = $output->isDecorated() ? $output : new NullOutput();
53294 $this->lastMessagesLength = 0;
53295 $this->barCharOriginal = '';
53296
53297 if (null === $this->format) {
53298 switch ($output->getVerbosity()) {
53299 case OutputInterface::VERBOSITY_QUIET:
53300 $this->format = self::FORMAT_QUIET_NOMAX;
53301 if ($this->max > 0) {
53302 $this->format = self::FORMAT_QUIET;
53303 }
53304 break;
53305 case OutputInterface::VERBOSITY_VERBOSE:
53306 case OutputInterface::VERBOSITY_VERY_VERBOSE:
53307 case OutputInterface::VERBOSITY_DEBUG:
53308 $this->format = self::FORMAT_VERBOSE_NOMAX;
53309 if ($this->max > 0) {
53310 $this->format = self::FORMAT_VERBOSE;
53311 }
53312 break;
53313 default:
53314 $this->format = self::FORMAT_NORMAL_NOMAX;
53315 if ($this->max > 0) {
53316 $this->format = self::FORMAT_NORMAL;
53317 }
53318 break;
53319 }
53320 }
53321
53322 $this->initialize();
53323 }
53324
53325
53326
53327
53328
53329
53330
53331
53332
53333 public function advance($step = 1, $redraw = false)
53334 {
53335 $this->setCurrent($this->current + $step, $redraw);
53336 }
53337
53338
53339
53340
53341
53342
53343
53344
53345
53346 public function setCurrent($current, $redraw = false)
53347 {
53348 if (null === $this->startTime) {
53349 throw new LogicException('You must start the progress bar before calling setCurrent().');
53350 }
53351
53352 $current = (int) $current;
53353
53354 if ($current < $this->current) {
53355 throw new LogicException('You can\'t regress the progress bar');
53356 }
53357
53358 if (0 === $this->current) {
53359 $redraw = true;
53360 }
53361
53362 $prevPeriod = (int) ($this->current / $this->redrawFreq);
53363
53364 $this->current = $current;
53365
53366 $currPeriod = (int) ($this->current / $this->redrawFreq);
53367 if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) {
53368 $this->display();
53369 }
53370 }
53371
53372
53373
53374
53375
53376
53377
53378
53379 public function display($finish = false)
53380 {
53381 if (null === $this->startTime) {
53382 throw new LogicException('You must start the progress bar before calling display().');
53383 }
53384
53385 $message = $this->format;
53386 foreach ($this->generate($finish) as $name => $value) {
53387 $message = str_replace("%{$name}%", $value, $message);
53388 }
53389 $this->overwrite($this->output, $message);
53390 }
53391
53392
53393
53394
53395
53396
53397
53398
53399 public function clear()
53400 {
53401 $this->overwrite($this->output, '');
53402 }
53403
53404
53405
53406
53407 public function finish()
53408 {
53409 if (null === $this->startTime) {
53410 throw new LogicException('You must start the progress bar before calling finish().');
53411 }
53412
53413 if (null !== $this->startTime) {
53414 if (!$this->max) {
53415 $this->barChar = $this->barCharOriginal;
53416 $this->display(true);
53417 }
53418 $this->startTime = null;
53419 $this->output->writeln('');
53420 $this->output = null;
53421 }
53422 }
53423
53424
53425
53426
53427 private function initialize()
53428 {
53429 $this->formatVars = array();
53430 foreach ($this->defaultFormatVars as $var) {
53431 if (false !== strpos($this->format, "%{$var}%")) {
53432 $this->formatVars[$var] = true;
53433 }
53434 }
53435
53436 if ($this->max > 0) {
53437 $this->widths['max'] = $this->strlen($this->max);
53438 $this->widths['current'] = $this->widths['max'];
53439 } else {
53440 $this->barCharOriginal = $this->barChar;
53441 $this->barChar = $this->emptyBarChar;
53442 }
53443 }
53444
53445
53446
53447
53448
53449
53450
53451
53452 private function generate($finish = false)
53453 {
53454 $vars = array();
53455 $percent = 0;
53456 if ($this->max > 0) {
53457 $percent = (float) $this->current / $this->max;
53458 }
53459
53460 if (isset($this->formatVars['bar'])) {
53461 if ($this->max > 0) {
53462 $completeBars = floor($percent * $this->barWidth);
53463 } else {
53464 if (!$finish) {
53465 $completeBars = floor($this->current % $this->barWidth);
53466 } else {
53467 $completeBars = $this->barWidth;
53468 }
53469 }
53470
53471 $emptyBars = $this->barWidth - $completeBars - $this->strlen($this->progressChar);
53472 $bar = str_repeat($this->barChar, $completeBars);
53473 if ($completeBars < $this->barWidth) {
53474 $bar .= $this->progressChar;
53475 $bar .= str_repeat($this->emptyBarChar, $emptyBars);
53476 }
53477
53478 $vars['bar'] = $bar;
53479 }
53480
53481 if (isset($this->formatVars['elapsed'])) {
53482 $elapsed = time() - $this->startTime;
53483 $vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT);
53484 }
53485
53486 if (isset($this->formatVars['current'])) {
53487 $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT);
53488 }
53489
53490 if (isset($this->formatVars['max'])) {
53491 $vars['max'] = $this->max;
53492 }
53493
53494 if (isset($this->formatVars['percent'])) {
53495 $vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT);
53496 }
53497
53498 return $vars;
53499 }
53500
53501
53502
53503
53504
53505
53506
53507
53508 private function humaneTime($secs)
53509 {
53510 $text = '';
53511 foreach ($this->timeFormats as $format) {
53512 if ($secs < $format[0]) {
53513 if (count($format) == 2) {
53514 $text = $format[1];
53515 break;
53516 } else {
53517 $text = ceil($secs / $format[2]).' '.$format[1];
53518 break;
53519 }
53520 }
53521 }
53522
53523 return $text;
53524 }
53525
53526
53527
53528
53529
53530
53531
53532 private function overwrite(OutputInterface $output, $message)
53533 {
53534 $length = $this->strlen($message);
53535
53536
53537  if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) {
53538 $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
53539 }
53540
53541
53542  $output->write("\x0D");
53543 $output->write($message);
53544
53545 $this->lastMessagesLength = $this->strlen($message);
53546 }
53547
53548
53549
53550
53551 public function getName()
53552 {
53553 return 'progress';
53554 }
53555 }
53556 <?php
53557
53558
53559
53560
53561
53562
53563
53564
53565
53566
53567 namespace Symfony\Component\Console\Helper;
53568
53569 use Symfony\Component\Console\Exception\InvalidArgumentException;
53570 use Symfony\Component\Console\Exception\LogicException;
53571 use Symfony\Component\Console\Output\OutputInterface;
53572
53573
53574
53575
53576 class ProgressIndicator
53577 {
53578 private $output;
53579 private $startTime;
53580 private $format;
53581 private $message;
53582 private $indicatorValues;
53583 private $indicatorCurrent;
53584 private $indicatorChangeInterval;
53585 private $indicatorUpdateTime;
53586 private $started = false;
53587
53588 private static $formatters;
53589 private static $formats;
53590
53591
53592
53593
53594
53595
53596
53597 public function __construct(OutputInterface $output, $format = null, $indicatorChangeInterval = 100, $indicatorValues = null)
53598 {
53599 $this->output = $output;
53600
53601 if (null === $format) {
53602 $format = $this->determineBestFormat();
53603 }
53604
53605 if (null === $indicatorValues) {
53606 $indicatorValues = array('-', '\\', '|', '/');
53607 }
53608
53609 $indicatorValues = array_values($indicatorValues);
53610
53611 if (2 > count($indicatorValues)) {
53612 throw new InvalidArgumentException('Must have at least 2 indicator value characters.');
53613 }
53614
53615 $this->format = self::getFormatDefinition($format);
53616 $this->indicatorChangeInterval = $indicatorChangeInterval;
53617 $this->indicatorValues = $indicatorValues;
53618 $this->startTime = time();
53619 }
53620
53621
53622
53623
53624
53625
53626 public function setMessage($message)
53627 {
53628 $this->message = $message;
53629
53630 $this->display();
53631 }
53632
53633
53634
53635
53636
53637
53638
53639
53640 public function getMessage()
53641 {
53642 return $this->message;
53643 }
53644
53645
53646
53647
53648
53649
53650
53651
53652 public function getStartTime()
53653 {
53654 return $this->startTime;
53655 }
53656
53657
53658
53659
53660
53661
53662
53663
53664 public function getCurrentValue()
53665 {
53666 return $this->indicatorValues[$this->indicatorCurrent % count($this->indicatorValues)];
53667 }
53668
53669
53670
53671
53672
53673
53674 public function start($message)
53675 {
53676 if ($this->started) {
53677 throw new LogicException('Progress indicator already started.');
53678 }
53679
53680 $this->message = $message;
53681 $this->started = true;
53682 $this->startTime = time();
53683 $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval;
53684 $this->indicatorCurrent = 0;
53685
53686 $this->display();
53687 }
53688
53689
53690
53691
53692 public function advance()
53693 {
53694 if (!$this->started) {
53695 throw new LogicException('Progress indicator has not yet been started.');
53696 }
53697
53698 if (!$this->output->isDecorated()) {
53699 return;
53700 }
53701
53702 $currentTime = $this->getCurrentTimeInMilliseconds();
53703
53704 if ($currentTime < $this->indicatorUpdateTime) {
53705 return;
53706 }
53707
53708 $this->indicatorUpdateTime = $currentTime + $this->indicatorChangeInterval;
53709 ++$this->indicatorCurrent;
53710
53711 $this->display();
53712 }
53713
53714
53715
53716
53717
53718
53719 public function finish($message)
53720 {
53721 if (!$this->started) {
53722 throw new LogicException('Progress indicator has not yet been started.');
53723 }
53724
53725 $this->message = $message;
53726 $this->display();
53727 $this->output->writeln('');
53728 $this->started = false;
53729 }
53730
53731
53732
53733
53734
53735
53736
53737
53738 public static function getFormatDefinition($name)
53739 {
53740 if (!self::$formats) {
53741 self::$formats = self::initFormats();
53742 }
53743
53744 return isset(self::$formats[$name]) ? self::$formats[$name] : null;
53745 }
53746
53747
53748
53749
53750
53751
53752
53753
53754
53755 public static function setPlaceholderFormatterDefinition($name, $callable)
53756 {
53757 if (!self::$formatters) {
53758 self::$formatters = self::initPlaceholderFormatters();
53759 }
53760
53761 self::$formatters[$name] = $callable;
53762 }
53763
53764
53765
53766
53767
53768
53769
53770
53771 public static function getPlaceholderFormatterDefinition($name)
53772 {
53773 if (!self::$formatters) {
53774 self::$formatters = self::initPlaceholderFormatters();
53775 }
53776
53777 return isset(self::$formatters[$name]) ? self::$formatters[$name] : null;
53778 }
53779
53780 private function display()
53781 {
53782 if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
53783 return;
53784 }
53785
53786 $self = $this;
53787
53788 $this->overwrite(preg_replace_callback("{%([a-z\-_]+)(?:\:([^%]+))?%}i", function ($matches) use ($self) {
53789 if ($formatter = $self::getPlaceholderFormatterDefinition($matches[1])) {
53790 return call_user_func($formatter, $self);
53791 }
53792
53793 return $matches[0];
53794 }, $this->format));
53795 }
53796
53797 private function determineBestFormat()
53798 {
53799 switch ($this->output->getVerbosity()) {
53800
53801  case OutputInterface::VERBOSITY_VERBOSE:
53802 return $this->output->isDecorated() ? 'verbose' : 'verbose_no_ansi';
53803 case OutputInterface::VERBOSITY_VERY_VERBOSE:
53804 case OutputInterface::VERBOSITY_DEBUG:
53805 return $this->output->isDecorated() ? 'very_verbose' : 'very_verbose_no_ansi';
53806 default:
53807 return $this->output->isDecorated() ? 'normal' : 'normal_no_ansi';
53808 }
53809 }
53810
53811
53812
53813
53814
53815
53816 private function overwrite($message)
53817 {
53818 if ($this->output->isDecorated()) {
53819 $this->output->write("\x0D\x1B[2K");
53820 $this->output->write($message);
53821 } else {
53822 $this->output->writeln($message);
53823 }
53824 }
53825
53826 private function getCurrentTimeInMilliseconds()
53827 {
53828 return round(microtime(true) * 1000);
53829 }
53830
53831 private static function initPlaceholderFormatters()
53832 {
53833 return array(
53834 'indicator' => function (ProgressIndicator $indicator) {
53835 return $indicator->getCurrentValue();
53836 },
53837 'message' => function (ProgressIndicator $indicator) {
53838 return $indicator->getMessage();
53839 },
53840 'elapsed' => function (ProgressIndicator $indicator) {
53841 return Helper::formatTime(time() - $indicator->getStartTime());
53842 },
53843 'memory' => function () {
53844 return Helper::formatMemory(memory_get_usage(true));
53845 },
53846 );
53847 }
53848
53849 private static function initFormats()
53850 {
53851 return array(
53852 'normal' => ' %indicator% %message%',
53853 'normal_no_ansi' => ' %message%',
53854
53855 'verbose' => ' %indicator% %message% (%elapsed:6s%)',
53856 'verbose_no_ansi' => ' %message% (%elapsed:6s%)',
53857
53858 'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)',
53859 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)',
53860 );
53861 }
53862 }
53863 <?php
53864
53865
53866
53867
53868
53869
53870
53871
53872
53873
53874 namespace Symfony\Component\Console\Helper;
53875
53876 use Symfony\Component\Console\Exception\InvalidArgumentException;
53877 use Symfony\Component\Console\Exception\RuntimeException;
53878 use Symfony\Component\Console\Input\InputInterface;
53879 use Symfony\Component\Console\Output\ConsoleOutputInterface;
53880 use Symfony\Component\Console\Output\OutputInterface;
53881 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
53882 use Symfony\Component\Console\Question\Question;
53883 use Symfony\Component\Console\Question\ChoiceQuestion;
53884
53885
53886
53887
53888
53889
53890 class QuestionHelper extends Helper
53891 {
53892 private $inputStream;
53893 private static $shell;
53894 private static $stty;
53895
53896
53897
53898
53899
53900
53901
53902
53903
53904
53905
53906
53907 public function ask(InputInterface $input, OutputInterface $output, Question $question)
53908 {
53909 if ($output instanceof ConsoleOutputInterface) {
53910 $output = $output->getErrorOutput();
53911 }
53912
53913 if (!$input->isInteractive()) {
53914 return $question->getDefault();
53915 }
53916
53917 if (!$question->getValidator()) {
53918 return $this->doAsk($output, $question);
53919 }
53920
53921 $that = $this;
53922
53923 $interviewer = function () use ($output, $question, $that) {
53924 return $that->doAsk($output, $question);
53925 };
53926
53927 return $this->validateAttempts($interviewer, $output, $question);
53928 }
53929
53930
53931
53932
53933
53934
53935
53936
53937
53938
53939 public function setInputStream($stream)
53940 {
53941 if (!is_resource($stream)) {
53942 throw new InvalidArgumentException('Input stream must be a valid resource.');
53943 }
53944
53945 $this->inputStream = $stream;
53946 }
53947
53948
53949
53950
53951
53952
53953 public function getInputStream()
53954 {
53955 return $this->inputStream;
53956 }
53957
53958
53959
53960
53961 public function getName()
53962 {
53963 return 'question';
53964 }
53965
53966
53967
53968
53969
53970
53971
53972
53973
53974
53975
53976
53977
53978 public function doAsk(OutputInterface $output, Question $question)
53979 {
53980 $this->writePrompt($output, $question);
53981
53982 $inputStream = $this->inputStream ?: STDIN;
53983 $autocomplete = $question->getAutocompleterValues();
53984
53985 if (null === $autocomplete || !$this->hasSttyAvailable()) {
53986 $ret = false;
53987 if ($question->isHidden()) {
53988 try {
53989 $ret = trim($this->getHiddenResponse($output, $inputStream));
53990 } catch (RuntimeException $e) {
53991 if (!$question->isHiddenFallback()) {
53992 throw $e;
53993 }
53994 }
53995 }
53996
53997 if (false === $ret) {
53998 $ret = fgets($inputStream, 4096);
53999 if (false === $ret) {
54000 throw new RuntimeException('Aborted');
54001 }
54002 $ret = trim($ret);
54003 }
54004 } else {
54005 $ret = trim($this->autocomplete($output, $question, $inputStream));
54006 }
54007
54008 $ret = strlen($ret) > 0 ? $ret : $question->getDefault();
54009
54010 if ($normalizer = $question->getNormalizer()) {
54011 return $normalizer($ret);
54012 }
54013
54014 return $ret;
54015 }
54016
54017
54018
54019
54020
54021
54022
54023 protected function writePrompt(OutputInterface $output, Question $question)
54024 {
54025 $message = $question->getQuestion();
54026
54027 if ($question instanceof ChoiceQuestion) {
54028 $maxWidth = max(array_map(array($this, 'strlen'), array_keys($question->getChoices())));
54029
54030 $messages = (array) $question->getQuestion();
54031 foreach ($question->getChoices() as $key => $value) {
54032 $width = $maxWidth - $this->strlen($key);
54033 $messages[] = '  [<info>'.$key.str_repeat(' ', $width).'</info>] '.$value;
54034 }
54035
54036 $output->writeln($messages);
54037
54038 $message = $question->getPrompt();
54039 }
54040
54041 $output->write($message);
54042 }
54043
54044
54045
54046
54047
54048
54049
54050 protected function writeError(OutputInterface $output, \Exception $error)
54051 {
54052 if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) {
54053 $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error');
54054 } else {
54055 $message = '<error>'.$error->getMessage().'</error>';
54056 }
54057
54058 $output->writeln($message);
54059 }
54060
54061
54062
54063
54064
54065
54066
54067
54068
54069
54070 private function autocomplete(OutputInterface $output, Question $question, $inputStream)
54071 {
54072 $autocomplete = $question->getAutocompleterValues();
54073 $ret = '';
54074
54075 $i = 0;
54076 $ofs = -1;
54077 $matches = $autocomplete;
54078 $numMatches = count($matches);
54079
54080 $sttyMode = shell_exec('stty -g');
54081
54082
54083  shell_exec('stty -icanon -echo');
54084
54085
54086  $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
54087
54088
54089  while (!feof($inputStream)) {
54090 $c = fread($inputStream, 1);
54091
54092
54093  if ("\177" === $c) {
54094 if (0 === $numMatches && 0 !== $i) {
54095 --$i;
54096
54097  $output->write("\033[1D");
54098 }
54099
54100 if ($i === 0) {
54101 $ofs = -1;
54102 $matches = $autocomplete;
54103 $numMatches = count($matches);
54104 } else {
54105 $numMatches = 0;
54106 }
54107
54108
54109  $ret = substr($ret, 0, $i);
54110 } elseif ("\033" === $c) {
54111
54112  $c .= fread($inputStream, 2);
54113
54114
54115  if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
54116 if ('A' === $c[2] && -1 === $ofs) {
54117 $ofs = 0;
54118 }
54119
54120 if (0 === $numMatches) {
54121 continue;
54122 }
54123
54124 $ofs += ('A' === $c[2]) ? -1 : 1;
54125 $ofs = ($numMatches + $ofs) % $numMatches;
54126 }
54127 } elseif (ord($c) < 32) {
54128 if ("\t" === $c || "\n" === $c) {
54129 if ($numMatches > 0 && -1 !== $ofs) {
54130 $ret = $matches[$ofs];
54131
54132  $output->write(substr($ret, $i));
54133 $i = strlen($ret);
54134 }
54135
54136 if ("\n" === $c) {
54137 $output->write($c);
54138 break;
54139 }
54140
54141 $numMatches = 0;
54142 }
54143
54144 continue;
54145 } else {
54146 $output->write($c);
54147 $ret .= $c;
54148 ++$i;
54149
54150 $numMatches = 0;
54151 $ofs = 0;
54152
54153 foreach ($autocomplete as $value) {
54154
54155  if (0 === strpos($value, $ret) && $i !== strlen($value)) {
54156 $matches[$numMatches++] = $value;
54157 }
54158 }
54159 }
54160
54161
54162  $output->write("\033[K");
54163
54164 if ($numMatches > 0 && -1 !== $ofs) {
54165
54166  $output->write("\0337");
54167
54168  $output->write('<hl>'.substr($matches[$ofs], $i).'</hl>');
54169
54170  $output->write("\0338");
54171 }
54172 }
54173
54174
54175  shell_exec(sprintf('stty %s', $sttyMode));
54176
54177 return $ret;
54178 }
54179
54180
54181
54182
54183
54184
54185
54186
54187
54188
54189
54190 private function getHiddenResponse(OutputInterface $output, $inputStream)
54191 {
54192 if ('\\' === DIRECTORY_SEPARATOR) {
54193 $exe = __DIR__.'/../Resources/bin/hiddeninput.exe';
54194
54195
54196  if ('phar:' === substr(__FILE__, 0, 5)) {
54197 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
54198 copy($exe, $tmpExe);
54199 $exe = $tmpExe;
54200 }
54201
54202 $value = rtrim(shell_exec($exe));
54203 $output->writeln('');
54204
54205 if (isset($tmpExe)) {
54206 unlink($tmpExe);
54207 }
54208
54209 return $value;
54210 }
54211
54212 if ($this->hasSttyAvailable()) {
54213 $sttyMode = shell_exec('stty -g');
54214
54215 shell_exec('stty -echo');
54216 $value = fgets($inputStream, 4096);
54217 shell_exec(sprintf('stty %s', $sttyMode));
54218
54219 if (false === $value) {
54220 throw new RuntimeException('Aborted');
54221 }
54222
54223 $value = trim($value);
54224 $output->writeln('');
54225
54226 return $value;
54227 }
54228
54229 if (false !== $shell = $this->getShell()) {
54230 $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword';
54231 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
54232 $value = rtrim(shell_exec($command));
54233 $output->writeln('');
54234
54235 return $value;
54236 }
54237
54238 throw new RuntimeException('Unable to hide the response.');
54239 }
54240
54241
54242
54243
54244
54245
54246
54247
54248
54249
54250
54251
54252 private function validateAttempts($interviewer, OutputInterface $output, Question $question)
54253 {
54254 $error = null;
54255 $attempts = $question->getMaxAttempts();
54256 while (null === $attempts || $attempts--) {
54257 if (null !== $error) {
54258 $this->writeError($output, $error);
54259 }
54260
54261 try {
54262 return call_user_func($question->getValidator(), $interviewer());
54263 } catch (RuntimeException $e) {
54264 throw $e;
54265 } catch (\Exception $error) {
54266 }
54267 }
54268
54269 throw $error;
54270 }
54271
54272
54273
54274
54275
54276
54277 private function getShell()
54278 {
54279 if (null !== self::$shell) {
54280 return self::$shell;
54281 }
54282
54283 self::$shell = false;
54284
54285 if (file_exists('/usr/bin/env')) {
54286
54287  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
54288 foreach (array('bash', 'zsh', 'ksh', 'csh') as $sh) {
54289 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
54290 self::$shell = $sh;
54291 break;
54292 }
54293 }
54294 }
54295
54296 return self::$shell;
54297 }
54298
54299
54300
54301
54302
54303
54304 private function hasSttyAvailable()
54305 {
54306 if (null !== self::$stty) {
54307 return self::$stty;
54308 }
54309
54310 exec('stty 2>&1', $output, $exitcode);
54311
54312 return self::$stty = $exitcode === 0;
54313 }
54314 }
54315 <?php
54316
54317
54318
54319
54320
54321
54322
54323
54324
54325
54326 namespace Symfony\Component\Console\Helper;
54327
54328 use Symfony\Component\Console\Exception\LogicException;
54329 use Symfony\Component\Console\Input\InputInterface;
54330 use Symfony\Component\Console\Output\OutputInterface;
54331 use Symfony\Component\Console\Question\ChoiceQuestion;
54332 use Symfony\Component\Console\Question\ConfirmationQuestion;
54333 use Symfony\Component\Console\Question\Question;
54334 use Symfony\Component\Console\Style\SymfonyStyle;
54335 use Symfony\Component\Console\Formatter\OutputFormatter;
54336
54337
54338
54339
54340
54341
54342 class SymfonyQuestionHelper extends QuestionHelper
54343 {
54344
54345
54346
54347 public function ask(InputInterface $input, OutputInterface $output, Question $question)
54348 {
54349 $validator = $question->getValidator();
54350 $question->setValidator(function ($value) use ($validator) {
54351 if (null !== $validator) {
54352 $value = $validator($value);
54353 } else {
54354
54355  if (!is_array($value) && !is_bool($value) && 0 === strlen($value)) {
54356 throw new LogicException('A value is required.');
54357 }
54358 }
54359
54360 return $value;
54361 });
54362
54363 return parent::ask($input, $output, $question);
54364 }
54365
54366
54367
54368
54369 protected function writePrompt(OutputInterface $output, Question $question)
54370 {
54371 $text = OutputFormatter::escapeTrailingBackslash($question->getQuestion());
54372 $default = $question->getDefault();
54373
54374 switch (true) {
54375 case null === $default:
54376 $text = sprintf(' <info>%s</info>:', $text);
54377
54378 break;
54379
54380 case $question instanceof ConfirmationQuestion:
54381 $text = sprintf(' <info>%s (yes/no)</info> [<comment>%s</comment>]:', $text, $default ? 'yes' : 'no');
54382
54383 break;
54384
54385 case $question instanceof ChoiceQuestion && $question->isMultiselect():
54386 $choices = $question->getChoices();
54387 $default = explode(',', $default);
54388
54389 foreach ($default as $key => $value) {
54390 $default[$key] = $choices[trim($value)];
54391 }
54392
54393 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape(implode(', ', $default)));
54394
54395 break;
54396
54397 case $question instanceof ChoiceQuestion:
54398 $choices = $question->getChoices();
54399 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($choices[$default]));
54400
54401 break;
54402
54403 default:
54404 $text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($default));
54405 }
54406
54407 $output->writeln($text);
54408
54409 if ($question instanceof ChoiceQuestion) {
54410 $width = max(array_map('strlen', array_keys($question->getChoices())));
54411
54412 foreach ($question->getChoices() as $key => $value) {
54413 $output->writeln(sprintf("  [<comment>%-${width}s</comment>] %s", $key, $value));
54414 }
54415 }
54416
54417 $output->write(' > ');
54418 }
54419
54420
54421
54422
54423 protected function writeError(OutputInterface $output, \Exception $error)
54424 {
54425 if ($output instanceof SymfonyStyle) {
54426 $output->newLine();
54427 $output->error($error->getMessage());
54428
54429 return;
54430 }
54431
54432 parent::writeError($output, $error);
54433 }
54434 }
54435 <?php
54436
54437
54438
54439
54440
54441
54442
54443
54444
54445
54446 namespace Symfony\Component\Console\Helper;
54447
54448 use Symfony\Component\Console\Output\OutputInterface;
54449 use Symfony\Component\Console\Exception\InvalidArgumentException;
54450
54451
54452
54453
54454
54455
54456
54457
54458
54459 class Table
54460 {
54461
54462
54463
54464
54465
54466 private $headers = array();
54467
54468
54469
54470
54471
54472
54473 private $rows = array();
54474
54475
54476
54477
54478
54479
54480 private $columnWidths = array();
54481
54482
54483
54484
54485
54486
54487 private $numberOfColumns;
54488
54489
54490
54491
54492 private $output;
54493
54494
54495
54496
54497 private $style;
54498
54499
54500
54501
54502 private $columnStyles = array();
54503
54504 private static $styles;
54505
54506 public function __construct(OutputInterface $output)
54507 {
54508 $this->output = $output;
54509
54510 if (!self::$styles) {
54511 self::$styles = self::initStyles();
54512 }
54513
54514 $this->setStyle('default');
54515 }
54516
54517
54518
54519
54520
54521
54522
54523 public static function setStyleDefinition($name, TableStyle $style)
54524 {
54525 if (!self::$styles) {
54526 self::$styles = self::initStyles();
54527 }
54528
54529 self::$styles[$name] = $style;
54530 }
54531
54532
54533
54534
54535
54536
54537
54538
54539 public static function getStyleDefinition($name)
54540 {
54541 if (!self::$styles) {
54542 self::$styles = self::initStyles();
54543 }
54544
54545 if (isset(self::$styles[$name])) {
54546 return self::$styles[$name];
54547 }
54548
54549 throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
54550 }
54551
54552
54553
54554
54555
54556
54557
54558
54559 public function setStyle($name)
54560 {
54561 $this->style = $this->resolveStyle($name);
54562
54563 return $this;
54564 }
54565
54566
54567
54568
54569
54570
54571 public function getStyle()
54572 {
54573 return $this->style;
54574 }
54575
54576
54577
54578
54579
54580
54581
54582
54583
54584 public function setColumnStyle($columnIndex, $name)
54585 {
54586 $columnIndex = (int) $columnIndex;
54587
54588 $this->columnStyles[$columnIndex] = $this->resolveStyle($name);
54589
54590 return $this;
54591 }
54592
54593
54594
54595
54596
54597
54598
54599
54600
54601
54602 public function getColumnStyle($columnIndex)
54603 {
54604 if (isset($this->columnStyles[$columnIndex])) {
54605 return $this->columnStyles[$columnIndex];
54606 }
54607
54608 return $this->getStyle();
54609 }
54610
54611 public function setHeaders(array $headers)
54612 {
54613 $headers = array_values($headers);
54614 if (!empty($headers) && !is_array($headers[0])) {
54615 $headers = array($headers);
54616 }
54617
54618 $this->headers = $headers;
54619
54620 return $this;
54621 }
54622
54623 public function setRows(array $rows)
54624 {
54625 $this->rows = array();
54626
54627 return $this->addRows($rows);
54628 }
54629
54630 public function addRows(array $rows)
54631 {
54632 foreach ($rows as $row) {
54633 $this->addRow($row);
54634 }
54635
54636 return $this;
54637 }
54638
54639 public function addRow($row)
54640 {
54641 if ($row instanceof TableSeparator) {
54642 $this->rows[] = $row;
54643
54644 return $this;
54645 }
54646
54647 if (!is_array($row)) {
54648 throw new InvalidArgumentException('A row must be an array or a TableSeparator instance.');
54649 }
54650
54651 $this->rows[] = array_values($row);
54652
54653 return $this;
54654 }
54655
54656 public function setRow($column, array $row)
54657 {
54658 $this->rows[$column] = $row;
54659
54660 return $this;
54661 }
54662
54663
54664
54665
54666
54667
54668
54669
54670
54671
54672
54673
54674
54675 public function render()
54676 {
54677 $this->calculateNumberOfColumns();
54678 $rows = $this->buildTableRows($this->rows);
54679 $headers = $this->buildTableRows($this->headers);
54680
54681 $this->calculateColumnsWidth(array_merge($headers, $rows));
54682
54683 $this->renderRowSeparator();
54684 if (!empty($headers)) {
54685 foreach ($headers as $header) {
54686 $this->renderRow($header, $this->style->getCellHeaderFormat());
54687 $this->renderRowSeparator();
54688 }
54689 }
54690 foreach ($rows as $row) {
54691 if ($row instanceof TableSeparator) {
54692 $this->renderRowSeparator();
54693 } else {
54694 $this->renderRow($row, $this->style->getCellRowFormat());
54695 }
54696 }
54697 if (!empty($rows)) {
54698 $this->renderRowSeparator();
54699 }
54700
54701 $this->cleanup();
54702 }
54703
54704
54705
54706
54707
54708
54709 private function renderRowSeparator()
54710 {
54711 if (0 === $count = $this->numberOfColumns) {
54712 return;
54713 }
54714
54715 if (!$this->style->getHorizontalBorderChar() && !$this->style->getCrossingChar()) {
54716 return;
54717 }
54718
54719 $markup = $this->style->getCrossingChar();
54720 for ($column = 0; $column < $count; ++$column) {
54721 $markup .= str_repeat($this->style->getHorizontalBorderChar(), $this->columnWidths[$column]).$this->style->getCrossingChar();
54722 }
54723
54724 $this->output->writeln(sprintf($this->style->getBorderFormat(), $markup));
54725 }
54726
54727
54728
54729
54730 private function renderColumnSeparator()
54731 {
54732 return sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar());
54733 }
54734
54735
54736
54737
54738
54739
54740
54741
54742
54743 private function renderRow(array $row, $cellFormat)
54744 {
54745 if (empty($row)) {
54746 return;
54747 }
54748
54749 $rowContent = $this->renderColumnSeparator();
54750 foreach ($this->getRowColumns($row) as $column) {
54751 $rowContent .= $this->renderCell($row, $column, $cellFormat);
54752 $rowContent .= $this->renderColumnSeparator();
54753 }
54754 $this->output->writeln($rowContent);
54755 }
54756
54757
54758
54759
54760
54761
54762
54763
54764 private function renderCell(array $row, $column, $cellFormat)
54765 {
54766 $cell = isset($row[$column]) ? $row[$column] : '';
54767 $width = $this->columnWidths[$column];
54768 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
54769
54770  foreach (range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) {
54771 $width += $this->getColumnSeparatorWidth() + $this->columnWidths[$nextColumn];
54772 }
54773 }
54774
54775
54776  if (false !== $encoding = mb_detect_encoding($cell, null, true)) {
54777 $width += strlen($cell) - mb_strwidth($cell, $encoding);
54778 }
54779
54780 $style = $this->getColumnStyle($column);
54781
54782 if ($cell instanceof TableSeparator) {
54783 return sprintf($style->getBorderFormat(), str_repeat($style->getHorizontalBorderChar(), $width));
54784 }
54785
54786 $width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
54787 $content = sprintf($style->getCellRowContentFormat(), $cell);
54788
54789 return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType()));
54790 }
54791
54792
54793
54794
54795 private function calculateNumberOfColumns()
54796 {
54797 if (null !== $this->numberOfColumns) {
54798 return;
54799 }
54800
54801 $columns = array(0);
54802 foreach (array_merge($this->headers, $this->rows) as $row) {
54803 if ($row instanceof TableSeparator) {
54804 continue;
54805 }
54806
54807 $columns[] = $this->getNumberOfColumns($row);
54808 }
54809
54810 $this->numberOfColumns = max($columns);
54811 }
54812
54813 private function buildTableRows($rows)
54814 {
54815 $unmergedRows = array();
54816 for ($rowKey = 0; $rowKey < count($rows); ++$rowKey) {
54817 $rows = $this->fillNextRows($rows, $rowKey);
54818
54819
54820  foreach ($rows[$rowKey] as $column => $cell) {
54821 if (!strstr($cell, "\n")) {
54822 continue;
54823 }
54824 $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
54825 foreach ($lines as $lineKey => $line) {
54826 if ($cell instanceof TableCell) {
54827 $line = new TableCell($line, array('colspan' => $cell->getColspan()));
54828 }
54829 if (0 === $lineKey) {
54830 $rows[$rowKey][$column] = $line;
54831 } else {
54832 $unmergedRows[$rowKey][$lineKey][$column] = $line;
54833 }
54834 }
54835 }
54836 }
54837
54838 $tableRows = array();
54839 foreach ($rows as $rowKey => $row) {
54840 $tableRows[] = $this->fillCells($row);
54841 if (isset($unmergedRows[$rowKey])) {
54842 $tableRows = array_merge($tableRows, $unmergedRows[$rowKey]);
54843 }
54844 }
54845
54846 return $tableRows;
54847 }
54848
54849
54850
54851
54852
54853
54854
54855
54856
54857 private function fillNextRows($rows, $line)
54858 {
54859 $unmergedRows = array();
54860 foreach ($rows[$line] as $column => $cell) {
54861 if ($cell instanceof TableCell && $cell->getRowspan() > 1) {
54862 $nbLines = $cell->getRowspan() - 1;
54863 $lines = array($cell);
54864 if (strstr($cell, "\n")) {
54865 $lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
54866 $nbLines = count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines;
54867
54868 $rows[$line][$column] = new TableCell($lines[0], array('colspan' => $cell->getColspan()));
54869 unset($lines[0]);
54870 }
54871
54872
54873  $unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, array()), $unmergedRows);
54874 foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
54875 $value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : '';
54876 $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, array('colspan' => $cell->getColspan()));
54877 if ($nbLines === $unmergedRowKey - $line) {
54878 break;
54879 }
54880 }
54881 }
54882 }
54883
54884 foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
54885
54886  if (isset($rows[$unmergedRowKey]) && is_array($rows[$unmergedRowKey]) && ($this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns)) {
54887 foreach ($unmergedRow as $cellKey => $cell) {
54888
54889  array_splice($rows[$unmergedRowKey], $cellKey, 0, array($cell));
54890 }
54891 } else {
54892 $row = $this->copyRow($rows, $unmergedRowKey - 1);
54893 foreach ($unmergedRow as $column => $cell) {
54894 if (!empty($cell)) {
54895 $row[$column] = $unmergedRow[$column];
54896 }
54897 }
54898 array_splice($rows, $unmergedRowKey, 0, array($row));
54899 }
54900 }
54901
54902 return $rows;
54903 }
54904
54905
54906
54907
54908
54909
54910
54911
54912 private function fillCells($row)
54913 {
54914 $newRow = array();
54915 foreach ($row as $column => $cell) {
54916 $newRow[] = $cell;
54917 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
54918 foreach (range($column + 1, $column + $cell->getColspan() - 1) as $position) {
54919
54920  $newRow[] = '';
54921 }
54922 }
54923 }
54924
54925 return $newRow ?: $row;
54926 }
54927
54928
54929
54930
54931
54932
54933
54934 private function copyRow($rows, $line)
54935 {
54936 $row = $rows[$line];
54937 foreach ($row as $cellKey => $cellValue) {
54938 $row[$cellKey] = '';
54939 if ($cellValue instanceof TableCell) {
54940 $row[$cellKey] = new TableCell('', array('colspan' => $cellValue->getColspan()));
54941 }
54942 }
54943
54944 return $row;
54945 }
54946
54947
54948
54949
54950
54951
54952
54953
54954 private function getNumberOfColumns(array $row)
54955 {
54956 $columns = count($row);
54957 foreach ($row as $column) {
54958 $columns += $column instanceof TableCell ? ($column->getColspan() - 1) : 0;
54959 }
54960
54961 return $columns;
54962 }
54963
54964
54965
54966
54967
54968
54969
54970
54971 private function getRowColumns($row)
54972 {
54973 $columns = range(0, $this->numberOfColumns - 1);
54974 foreach ($row as $cellKey => $cell) {
54975 if ($cell instanceof TableCell && $cell->getColspan() > 1) {
54976
54977  $columns = array_diff($columns, range($cellKey + 1, $cellKey + $cell->getColspan() - 1));
54978 }
54979 }
54980
54981 return $columns;
54982 }
54983
54984
54985
54986
54987
54988
54989 private function calculateColumnsWidth($rows)
54990 {
54991 for ($column = 0; $column < $this->numberOfColumns; ++$column) {
54992 $lengths = array();
54993 foreach ($rows as $row) {
54994 if ($row instanceof TableSeparator) {
54995 continue;
54996 }
54997
54998 foreach ($row as $i => $cell) {
54999 if ($cell instanceof TableCell) {
55000 $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell);
55001 $textLength = Helper::strlen($textContent);
55002 if ($textLength > 0) {
55003 $contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan()));
55004 foreach ($contentColumns as $position => $content) {
55005 $row[$i + $position] = $content;
55006 }
55007 }
55008 }
55009 }
55010
55011 $lengths[] = $this->getCellWidth($row, $column);
55012 }
55013
55014 $this->columnWidths[$column] = max($lengths) + strlen($this->style->getCellRowContentFormat()) - 2;
55015 }
55016 }
55017
55018
55019
55020
55021
55022
55023 private function getColumnSeparatorWidth()
55024 {
55025 return strlen(sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar()));
55026 }
55027
55028
55029
55030
55031
55032
55033
55034
55035
55036 private function getCellWidth(array $row, $column)
55037 {
55038 if (isset($row[$column])) {
55039 $cell = $row[$column];
55040 $cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
55041
55042 return $cellWidth;
55043 }
55044
55045 return 0;
55046 }
55047
55048
55049
55050
55051 private function cleanup()
55052 {
55053 $this->columnWidths = array();
55054 $this->numberOfColumns = null;
55055 }
55056
55057 private static function initStyles()
55058 {
55059 $borderless = new TableStyle();
55060 $borderless
55061 ->setHorizontalBorderChar('=')
55062 ->setVerticalBorderChar(' ')
55063 ->setCrossingChar(' ')
55064 ;
55065
55066 $compact = new TableStyle();
55067 $compact
55068 ->setHorizontalBorderChar('')
55069 ->setVerticalBorderChar(' ')
55070 ->setCrossingChar('')
55071 ->setCellRowContentFormat('%s')
55072 ;
55073
55074 $styleGuide = new TableStyle();
55075 $styleGuide
55076 ->setHorizontalBorderChar('-')
55077 ->setVerticalBorderChar(' ')
55078 ->setCrossingChar(' ')
55079 ->setCellHeaderFormat('%s')
55080 ;
55081
55082 return array(
55083 'default' => new TableStyle(),
55084 'borderless' => $borderless,
55085 'compact' => $compact,
55086 'symfony-style-guide' => $styleGuide,
55087 );
55088 }
55089
55090 private function resolveStyle($name)
55091 {
55092 if ($name instanceof TableStyle) {
55093 return $name;
55094 }
55095
55096 if (isset(self::$styles[$name])) {
55097 return self::$styles[$name];
55098 }
55099
55100 throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
55101 }
55102 }
55103 <?php
55104
55105
55106
55107
55108
55109
55110
55111
55112
55113
55114 namespace Symfony\Component\Console\Helper;
55115
55116 use Symfony\Component\Console\Exception\InvalidArgumentException;
55117
55118
55119
55120
55121 class TableCell
55122 {
55123
55124
55125
55126 private $value;
55127
55128
55129
55130
55131 private $options = array(
55132 'rowspan' => 1,
55133 'colspan' => 1,
55134 );
55135
55136
55137
55138
55139
55140 public function __construct($value = '', array $options = array())
55141 {
55142 if (is_numeric($value) && !is_string($value)) {
55143 $value = (string) $value;
55144 }
55145
55146 $this->value = $value;
55147
55148
55149  if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
55150 throw new InvalidArgumentException(sprintf('The TableCell does not support the following options: \'%s\'.', implode('\', \'', $diff)));
55151 }
55152
55153 $this->options = array_merge($this->options, $options);
55154 }
55155
55156
55157
55158
55159
55160
55161 public function __toString()
55162 {
55163 return $this->value;
55164 }
55165
55166
55167
55168
55169
55170
55171 public function getColspan()
55172 {
55173 return (int) $this->options['colspan'];
55174 }
55175
55176
55177
55178
55179
55180
55181 public function getRowspan()
55182 {
55183 return (int) $this->options['rowspan'];
55184 }
55185 }
55186 <?php
55187
55188
55189
55190
55191
55192
55193
55194
55195
55196
55197 namespace Symfony\Component\Console\Helper;
55198
55199 use Symfony\Component\Console\Output\OutputInterface;
55200 use Symfony\Component\Console\Output\NullOutput;
55201 use Symfony\Component\Console\Exception\InvalidArgumentException;
55202
55203
55204
55205
55206
55207
55208
55209
55210
55211
55212 class TableHelper extends Helper
55213 {
55214 const LAYOUT_DEFAULT = 0;
55215 const LAYOUT_BORDERLESS = 1;
55216 const LAYOUT_COMPACT = 2;
55217
55218
55219
55220
55221 private $table;
55222
55223 public function __construct($triggerDeprecationError = true)
55224 {
55225 if ($triggerDeprecationError) {
55226 @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);
55227 }
55228
55229 $this->table = new Table(new NullOutput());
55230 }
55231
55232
55233
55234
55235
55236
55237
55238
55239
55240
55241 public function setLayout($layout)
55242 {
55243 switch ($layout) {
55244 case self::LAYOUT_BORDERLESS:
55245 $this->table->setStyle('borderless');
55246 break;
55247
55248 case self::LAYOUT_COMPACT:
55249 $this->table->setStyle('compact');
55250 break;
55251
55252 case self::LAYOUT_DEFAULT:
55253 $this->table->setStyle('default');
55254 break;
55255
55256 default:
55257 throw new InvalidArgumentException(sprintf('Invalid table layout "%s".', $layout));
55258 }
55259
55260 return $this;
55261 }
55262
55263 public function setHeaders(array $headers)
55264 {
55265 $this->table->setHeaders($headers);
55266
55267 return $this;
55268 }
55269
55270 public function setRows(array $rows)
55271 {
55272 $this->table->setRows($rows);
55273
55274 return $this;
55275 }
55276
55277 public function addRows(array $rows)
55278 {
55279 $this->table->addRows($rows);
55280
55281 return $this;
55282 }
55283
55284 public function addRow(array $row)
55285 {
55286 $this->table->addRow($row);
55287
55288 return $this;
55289 }
55290
55291 public function setRow($column, array $row)
55292 {
55293 $this->table->setRow($column, $row);
55294
55295 return $this;
55296 }
55297
55298
55299
55300
55301
55302
55303
55304
55305 public function setPaddingChar($paddingChar)
55306 {
55307 $this->table->getStyle()->setPaddingChar($paddingChar);
55308
55309 return $this;
55310 }
55311
55312
55313
55314
55315
55316
55317
55318
55319 public function setHorizontalBorderChar($horizontalBorderChar)
55320 {
55321 $this->table->getStyle()->setHorizontalBorderChar($horizontalBorderChar);
55322
55323 return $this;
55324 }
55325
55326
55327
55328
55329
55330
55331
55332
55333 public function setVerticalBorderChar($verticalBorderChar)
55334 {
55335 $this->table->getStyle()->setVerticalBorderChar($verticalBorderChar);
55336
55337 return $this;
55338 }
55339
55340
55341
55342
55343
55344
55345
55346
55347 public function setCrossingChar($crossingChar)
55348 {
55349 $this->table->getStyle()->setCrossingChar($crossingChar);
55350
55351 return $this;
55352 }
55353
55354
55355
55356
55357
55358
55359
55360
55361 public function setCellHeaderFormat($cellHeaderFormat)
55362 {
55363 $this->table->getStyle()->setCellHeaderFormat($cellHeaderFormat);
55364
55365 return $this;
55366 }
55367
55368
55369
55370
55371
55372
55373
55374
55375 public function setCellRowFormat($cellRowFormat)
55376 {
55377 $this->table->getStyle()->setCellHeaderFormat($cellRowFormat);
55378
55379 return $this;
55380 }
55381
55382
55383
55384
55385
55386
55387
55388
55389 public function setCellRowContentFormat($cellRowContentFormat)
55390 {
55391 $this->table->getStyle()->setCellRowContentFormat($cellRowContentFormat);
55392
55393 return $this;
55394 }
55395
55396
55397
55398
55399
55400
55401
55402
55403 public function setBorderFormat($borderFormat)
55404 {
55405 $this->table->getStyle()->setBorderFormat($borderFormat);
55406
55407 return $this;
55408 }
55409
55410
55411
55412
55413
55414
55415
55416
55417 public function setPadType($padType)
55418 {
55419 $this->table->getStyle()->setPadType($padType);
55420
55421 return $this;
55422 }
55423
55424
55425
55426
55427
55428
55429
55430
55431
55432
55433
55434
55435
55436
55437
55438 public function render(OutputInterface $output)
55439 {
55440 $p = new \ReflectionProperty($this->table, 'output');
55441 $p->setAccessible(true);
55442 $p->setValue($this->table, $output);
55443
55444 $this->table->render();
55445 }
55446
55447
55448
55449
55450 public function getName()
55451 {
55452 return 'table';
55453 }
55454 }
55455 <?php
55456
55457
55458
55459
55460
55461
55462
55463
55464
55465
55466 namespace Symfony\Component\Console\Helper;
55467
55468
55469
55470
55471
55472
55473 class TableSeparator extends TableCell
55474 {
55475
55476
55477
55478 public function __construct(array $options = array())
55479 {
55480 parent::__construct('', $options);
55481 }
55482 }
55483 <?php
55484
55485
55486
55487
55488
55489
55490
55491
55492
55493
55494 namespace Symfony\Component\Console\Helper;
55495
55496 use Symfony\Component\Console\Exception\InvalidArgumentException;
55497 use Symfony\Component\Console\Exception\LogicException;
55498
55499
55500
55501
55502
55503
55504
55505 class TableStyle
55506 {
55507 private $paddingChar = ' ';
55508 private $horizontalBorderChar = '-';
55509 private $verticalBorderChar = '|';
55510 private $crossingChar = '+';
55511 private $cellHeaderFormat = '<info>%s</info>';
55512 private $cellRowFormat = '%s';
55513 private $cellRowContentFormat = ' %s ';
55514 private $borderFormat = '%s';
55515 private $padType = STR_PAD_RIGHT;
55516
55517
55518
55519
55520
55521
55522
55523
55524 public function setPaddingChar($paddingChar)
55525 {
55526 if (!$paddingChar) {
55527 throw new LogicException('The padding char must not be empty');
55528 }
55529
55530 $this->paddingChar = $paddingChar;
55531
55532 return $this;
55533 }
55534
55535
55536
55537
55538
55539
55540 public function getPaddingChar()
55541 {
55542 return $this->paddingChar;
55543 }
55544
55545
55546
55547
55548
55549
55550
55551
55552 public function setHorizontalBorderChar($horizontalBorderChar)
55553 {
55554 $this->horizontalBorderChar = $horizontalBorderChar;
55555
55556 return $this;
55557 }
55558
55559
55560
55561
55562
55563
55564 public function getHorizontalBorderChar()
55565 {
55566 return $this->horizontalBorderChar;
55567 }
55568
55569
55570
55571
55572
55573
55574
55575
55576 public function setVerticalBorderChar($verticalBorderChar)
55577 {
55578 $this->verticalBorderChar = $verticalBorderChar;
55579
55580 return $this;
55581 }
55582
55583
55584
55585
55586
55587
55588 public function getVerticalBorderChar()
55589 {
55590 return $this->verticalBorderChar;
55591 }
55592
55593
55594
55595
55596
55597
55598
55599
55600 public function setCrossingChar($crossingChar)
55601 {
55602 $this->crossingChar = $crossingChar;
55603
55604 return $this;
55605 }
55606
55607
55608
55609
55610
55611
55612 public function getCrossingChar()
55613 {
55614 return $this->crossingChar;
55615 }
55616
55617
55618
55619
55620
55621
55622
55623
55624 public function setCellHeaderFormat($cellHeaderFormat)
55625 {
55626 $this->cellHeaderFormat = $cellHeaderFormat;
55627
55628 return $this;
55629 }
55630
55631
55632
55633
55634
55635
55636 public function getCellHeaderFormat()
55637 {
55638 return $this->cellHeaderFormat;
55639 }
55640
55641
55642
55643
55644
55645
55646
55647
55648 public function setCellRowFormat($cellRowFormat)
55649 {
55650 $this->cellRowFormat = $cellRowFormat;
55651
55652 return $this;
55653 }
55654
55655
55656
55657
55658
55659
55660 public function getCellRowFormat()
55661 {
55662 return $this->cellRowFormat;
55663 }
55664
55665
55666
55667
55668
55669
55670
55671
55672 public function setCellRowContentFormat($cellRowContentFormat)
55673 {
55674 $this->cellRowContentFormat = $cellRowContentFormat;
55675
55676 return $this;
55677 }
55678
55679
55680
55681
55682
55683
55684 public function getCellRowContentFormat()
55685 {
55686 return $this->cellRowContentFormat;
55687 }
55688
55689
55690
55691
55692
55693
55694
55695
55696 public function setBorderFormat($borderFormat)
55697 {
55698 $this->borderFormat = $borderFormat;
55699
55700 return $this;
55701 }
55702
55703
55704
55705
55706
55707
55708 public function getBorderFormat()
55709 {
55710 return $this->borderFormat;
55711 }
55712
55713
55714
55715
55716
55717
55718
55719
55720 public function setPadType($padType)
55721 {
55722 if (!in_array($padType, array(STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH), true)) {
55723 throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).');
55724 }
55725
55726 $this->padType = $padType;
55727
55728 return $this;
55729 }
55730
55731
55732
55733
55734
55735
55736 public function getPadType()
55737 {
55738 return $this->padType;
55739 }
55740 }
55741 <?php
55742
55743
55744
55745
55746
55747
55748
55749
55750
55751
55752 namespace Symfony\Component\Console\Input;
55753
55754 use Symfony\Component\Console\Exception\RuntimeException;
55755
55756
55757
55758
55759
55760
55761
55762
55763
55764
55765
55766
55767
55768
55769
55770
55771
55772
55773
55774
55775
55776
55777
55778
55779
55780
55781 class ArgvInput extends Input
55782 {
55783 private $tokens;
55784 private $parsed;
55785
55786
55787
55788
55789
55790
55791
55792 public function __construct(array $argv = null, InputDefinition $definition = null)
55793 {
55794 if (null === $argv) {
55795 $argv = $_SERVER['argv'];
55796 }
55797
55798
55799  array_shift($argv);
55800
55801 $this->tokens = $argv;
55802
55803 parent::__construct($definition);
55804 }
55805
55806 protected function setTokens(array $tokens)
55807 {
55808 $this->tokens = $tokens;
55809 }
55810
55811
55812
55813
55814 protected function parse()
55815 {
55816 $parseOptions = true;
55817 $this->parsed = $this->tokens;
55818 while (null !== $token = array_shift($this->parsed)) {
55819 if ($parseOptions && '' == $token) {
55820 $this->parseArgument($token);
55821 } elseif ($parseOptions && '--' == $token) {
55822 $parseOptions = false;
55823 } elseif ($parseOptions && 0 === strpos($token, '--')) {
55824 $this->parseLongOption($token);
55825 } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
55826 $this->parseShortOption($token);
55827 } else {
55828 $this->parseArgument($token);
55829 }
55830 }
55831 }
55832
55833
55834
55835
55836
55837
55838 private function parseShortOption($token)
55839 {
55840 $name = substr($token, 1);
55841
55842 if (strlen($name) > 1) {
55843 if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) {
55844
55845  $this->addShortOption($name[0], substr($name, 1));
55846 } else {
55847 $this->parseShortOptionSet($name);
55848 }
55849 } else {
55850 $this->addShortOption($name, null);
55851 }
55852 }
55853
55854
55855
55856
55857
55858
55859
55860
55861 private function parseShortOptionSet($name)
55862 {
55863 $len = strlen($name);
55864 for ($i = 0; $i < $len; ++$i) {
55865 if (!$this->definition->hasShortcut($name[$i])) {
55866 throw new RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i]));
55867 }
55868
55869 $option = $this->definition->getOptionForShortcut($name[$i]);
55870 if ($option->acceptValue()) {
55871 $this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));
55872
55873 break;
55874 } else {
55875 $this->addLongOption($option->getName(), null);
55876 }
55877 }
55878 }
55879
55880
55881
55882
55883
55884
55885 private function parseLongOption($token)
55886 {
55887 $name = substr($token, 2);
55888
55889 if (false !== $pos = strpos($name, '=')) {
55890 if (0 === strlen($value = substr($name, $pos + 1))) {
55891 array_unshift($this->parsed, null);
55892 }
55893 $this->addLongOption(substr($name, 0, $pos), $value);
55894 } else {
55895 $this->addLongOption($name, null);
55896 }
55897 }
55898
55899
55900
55901
55902
55903
55904
55905
55906 private function parseArgument($token)
55907 {
55908 $c = count($this->arguments);
55909
55910
55911  if ($this->definition->hasArgument($c)) {
55912 $arg = $this->definition->getArgument($c);
55913 $this->arguments[$arg->getName()] = $arg->isArray() ? array($token) : $token;
55914
55915
55916  } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
55917 $arg = $this->definition->getArgument($c - 1);
55918 $this->arguments[$arg->getName()][] = $token;
55919
55920
55921  } else {
55922 $all = $this->definition->getArguments();
55923 if (count($all)) {
55924 throw new RuntimeException(sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all))));
55925 }
55926
55927 throw new RuntimeException(sprintf('No arguments expected, got "%s".', $token));
55928 }
55929 }
55930
55931
55932
55933
55934
55935
55936
55937
55938
55939 private function addShortOption($shortcut, $value)
55940 {
55941 if (!$this->definition->hasShortcut($shortcut)) {
55942 throw new RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
55943 }
55944
55945 $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
55946 }
55947
55948
55949
55950
55951
55952
55953
55954
55955
55956 private function addLongOption($name, $value)
55957 {
55958 if (!$this->definition->hasOption($name)) {
55959 throw new RuntimeException(sprintf('The "--%s" option does not exist.', $name));
55960 }
55961
55962 $option = $this->definition->getOption($name);
55963
55964
55965  if (!isset($value[0])) {
55966 $value = null;
55967 }
55968
55969 if (null !== $value && !$option->acceptValue()) {
55970 throw new RuntimeException(sprintf('The "--%s" option does not accept a value.', $name));
55971 }
55972
55973 if (null === $value && $option->acceptValue() && count($this->parsed)) {
55974
55975  
55976  $next = array_shift($this->parsed);
55977 if (isset($next[0]) && '-' !== $next[0]) {
55978 $value = $next;
55979 } elseif (empty($next)) {
55980 $value = null;
55981 } else {
55982 array_unshift($this->parsed, $next);
55983 }
55984 }
55985
55986 if (null === $value) {
55987 if ($option->isValueRequired()) {
55988 throw new RuntimeException(sprintf('The "--%s" option requires a value.', $name));
55989 }
55990
55991 if (!$option->isArray()) {
55992 $value = $option->isValueOptional() ? $option->getDefault() : true;
55993 }
55994 }
55995
55996 if ($option->isArray()) {
55997 $this->options[$name][] = $value;
55998 } else {
55999 $this->options[$name] = $value;
56000 }
56001 }
56002
56003
56004
56005
56006 public function getFirstArgument()
56007 {
56008 foreach ($this->tokens as $token) {
56009 if ($token && '-' === $token[0]) {
56010 continue;
56011 }
56012
56013 return $token;
56014 }
56015 }
56016
56017
56018
56019
56020 public function hasParameterOption($values)
56021 {
56022 $values = (array) $values;
56023
56024 foreach ($this->tokens as $token) {
56025 foreach ($values as $value) {
56026 if ($token === $value || 0 === strpos($token, $value.'=')) {
56027 return true;
56028 }
56029 }
56030 }
56031
56032 return false;
56033 }
56034
56035
56036
56037
56038 public function getParameterOption($values, $default = false)
56039 {
56040 $values = (array) $values;
56041 $tokens = $this->tokens;
56042
56043 while (0 < count($tokens)) {
56044 $token = array_shift($tokens);
56045
56046 foreach ($values as $value) {
56047 if ($token === $value || 0 === strpos($token, $value.'=')) {
56048 if (false !== $pos = strpos($token, '=')) {
56049 return substr($token, $pos + 1);
56050 }
56051
56052 return array_shift($tokens);
56053 }
56054 }
56055 }
56056
56057 return $default;
56058 }
56059
56060
56061
56062
56063
56064
56065 public function __toString()
56066 {
56067 $self = $this;
56068 $tokens = array_map(function ($token) use ($self) {
56069 if (preg_match('{^(-[^=]+=)(.+)}', $token, $match)) {
56070 return $match[1].$self->escapeToken($match[2]);
56071 }
56072
56073 if ($token && $token[0] !== '-') {
56074 return $self->escapeToken($token);
56075 }
56076
56077 return $token;
56078 }, $this->tokens);
56079
56080 return implode(' ', $tokens);
56081 }
56082 }
56083 <?php
56084
56085
56086
56087
56088
56089
56090
56091
56092
56093
56094 namespace Symfony\Component\Console\Input;
56095
56096 use Symfony\Component\Console\Exception\InvalidArgumentException;
56097 use Symfony\Component\Console\Exception\InvalidOptionException;
56098
56099
56100
56101
56102
56103
56104
56105
56106
56107
56108 class ArrayInput extends Input
56109 {
56110 private $parameters;
56111
56112
56113
56114
56115
56116
56117
56118 public function __construct(array $parameters, InputDefinition $definition = null)
56119 {
56120 $this->parameters = $parameters;
56121
56122 parent::__construct($definition);
56123 }
56124
56125
56126
56127
56128 public function getFirstArgument()
56129 {
56130 foreach ($this->parameters as $key => $value) {
56131 if ($key && '-' === $key[0]) {
56132 continue;
56133 }
56134
56135 return $value;
56136 }
56137 }
56138
56139
56140
56141
56142 public function hasParameterOption($values)
56143 {
56144 $values = (array) $values;
56145
56146 foreach ($this->parameters as $k => $v) {
56147 if (!is_int($k)) {
56148 $v = $k;
56149 }
56150
56151 if (in_array($v, $values)) {
56152 return true;
56153 }
56154 }
56155
56156 return false;
56157 }
56158
56159
56160
56161
56162 public function getParameterOption($values, $default = false)
56163 {
56164 $values = (array) $values;
56165
56166 foreach ($this->parameters as $k => $v) {
56167 if (is_int($k)) {
56168 if (in_array($v, $values)) {
56169 return true;
56170 }
56171 } elseif (in_array($k, $values)) {
56172 return $v;
56173 }
56174 }
56175
56176 return $default;
56177 }
56178
56179
56180
56181
56182
56183
56184 public function __toString()
56185 {
56186 $params = array();
56187 foreach ($this->parameters as $param => $val) {
56188 if ($param && '-' === $param[0]) {
56189 $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : '');
56190 } else {
56191 $params[] = $this->escapeToken($val);
56192 }
56193 }
56194
56195 return implode(' ', $params);
56196 }
56197
56198
56199
56200
56201 protected function parse()
56202 {
56203 foreach ($this->parameters as $key => $value) {
56204 if (0 === strpos($key, '--')) {
56205 $this->addLongOption(substr($key, 2), $value);
56206 } elseif ('-' === $key[0]) {
56207 $this->addShortOption(substr($key, 1), $value);
56208 } else {
56209 $this->addArgument($key, $value);
56210 }
56211 }
56212 }
56213
56214
56215
56216
56217
56218
56219
56220
56221
56222 private function addShortOption($shortcut, $value)
56223 {
56224 if (!$this->definition->hasShortcut($shortcut)) {
56225 throw new InvalidOptionException(sprintf('The "-%s" option does not exist.', $shortcut));
56226 }
56227
56228 $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
56229 }
56230
56231
56232
56233
56234
56235
56236
56237
56238
56239
56240 private function addLongOption($name, $value)
56241 {
56242 if (!$this->definition->hasOption($name)) {
56243 throw new InvalidOptionException(sprintf('The "--%s" option does not exist.', $name));
56244 }
56245
56246 $option = $this->definition->getOption($name);
56247
56248 if (null === $value) {
56249 if ($option->isValueRequired()) {
56250 throw new InvalidOptionException(sprintf('The "--%s" option requires a value.', $name));
56251 }
56252
56253 $value = $option->isValueOptional() ? $option->getDefault() : true;
56254 }
56255
56256 $this->options[$name] = $value;
56257 }
56258
56259
56260
56261
56262
56263
56264
56265
56266
56267 private function addArgument($name, $value)
56268 {
56269 if (!$this->definition->hasArgument($name)) {
56270 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
56271 }
56272
56273 $this->arguments[$name] = $value;
56274 }
56275 }
56276 <?php
56277
56278
56279
56280
56281
56282
56283
56284
56285
56286
56287 namespace Symfony\Component\Console\Input;
56288
56289 use Symfony\Component\Console\Exception\InvalidArgumentException;
56290 use Symfony\Component\Console\Exception\RuntimeException;
56291
56292
56293
56294
56295
56296
56297
56298
56299
56300
56301
56302
56303 abstract class Input implements InputInterface
56304 {
56305
56306
56307
56308 protected $definition;
56309 protected $options = array();
56310 protected $arguments = array();
56311 protected $interactive = true;
56312
56313
56314
56315
56316
56317
56318 public function __construct(InputDefinition $definition = null)
56319 {
56320 if (null === $definition) {
56321 $this->definition = new InputDefinition();
56322 } else {
56323 $this->bind($definition);
56324 $this->validate();
56325 }
56326 }
56327
56328
56329
56330
56331 public function bind(InputDefinition $definition)
56332 {
56333 $this->arguments = array();
56334 $this->options = array();
56335 $this->definition = $definition;
56336
56337 $this->parse();
56338 }
56339
56340
56341
56342
56343 abstract protected function parse();
56344
56345
56346
56347
56348 public function validate()
56349 {
56350 $definition = $this->definition;
56351 $givenArguments = $this->arguments;
56352
56353 $missingArguments = array_filter(array_keys($definition->getArguments()), function ($argument) use ($definition, $givenArguments) {
56354 return !array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired();
56355 });
56356
56357 if (count($missingArguments) > 0) {
56358 throw new RuntimeException(sprintf('Not enough arguments (missing: "%s").', implode(', ', $missingArguments)));
56359 }
56360 }
56361
56362
56363
56364
56365 public function isInteractive()
56366 {
56367 return $this->interactive;
56368 }
56369
56370
56371
56372
56373 public function setInteractive($interactive)
56374 {
56375 $this->interactive = (bool) $interactive;
56376 }
56377
56378
56379
56380
56381 public function getArguments()
56382 {
56383 return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
56384 }
56385
56386
56387
56388
56389 public function getArgument($name)
56390 {
56391 if (!$this->definition->hasArgument($name)) {
56392 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
56393 }
56394
56395 return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault();
56396 }
56397
56398
56399
56400
56401 public function setArgument($name, $value)
56402 {
56403 if (!$this->definition->hasArgument($name)) {
56404 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
56405 }
56406
56407 $this->arguments[$name] = $value;
56408 }
56409
56410
56411
56412
56413 public function hasArgument($name)
56414 {
56415 return $this->definition->hasArgument($name);
56416 }
56417
56418
56419
56420
56421 public function getOptions()
56422 {
56423 return array_merge($this->definition->getOptionDefaults(), $this->options);
56424 }
56425
56426
56427
56428
56429 public function getOption($name)
56430 {
56431 if (!$this->definition->hasOption($name)) {
56432 throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
56433 }
56434
56435 return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
56436 }
56437
56438
56439
56440
56441 public function setOption($name, $value)
56442 {
56443 if (!$this->definition->hasOption($name)) {
56444 throw new InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
56445 }
56446
56447 $this->options[$name] = $value;
56448 }
56449
56450
56451
56452
56453 public function hasOption($name)
56454 {
56455 return $this->definition->hasOption($name);
56456 }
56457
56458
56459
56460
56461
56462
56463
56464
56465 public function escapeToken($token)
56466 {
56467 return preg_match('{^[\w-]+$}', $token) ? $token : escapeshellarg($token);
56468 }
56469 }
56470 <?php
56471
56472
56473
56474
56475
56476
56477
56478
56479
56480
56481 namespace Symfony\Component\Console\Input;
56482
56483 use Symfony\Component\Console\Exception\InvalidArgumentException;
56484 use Symfony\Component\Console\Exception\LogicException;
56485
56486
56487
56488
56489
56490
56491 class InputArgument
56492 {
56493 const REQUIRED = 1;
56494 const OPTIONAL = 2;
56495 const IS_ARRAY = 4;
56496
56497 private $name;
56498 private $mode;
56499 private $default;
56500 private $description;
56501
56502
56503
56504
56505
56506
56507
56508
56509
56510
56511
56512 public function __construct($name, $mode = null, $description = '', $default = null)
56513 {
56514 if (null === $mode) {
56515 $mode = self::OPTIONAL;
56516 } elseif (!is_int($mode) || $mode > 7 || $mode < 1) {
56517 throw new InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode));
56518 }
56519
56520 $this->name = $name;
56521 $this->mode = $mode;
56522 $this->description = $description;
56523
56524 $this->setDefault($default);
56525 }
56526
56527
56528
56529
56530
56531
56532 public function getName()
56533 {
56534 return $this->name;
56535 }
56536
56537
56538
56539
56540
56541
56542 public function isRequired()
56543 {
56544 return self::REQUIRED === (self::REQUIRED & $this->mode);
56545 }
56546
56547
56548
56549
56550
56551
56552 public function isArray()
56553 {
56554 return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
56555 }
56556
56557
56558
56559
56560
56561
56562
56563
56564 public function setDefault($default = null)
56565 {
56566 if (self::REQUIRED === $this->mode && null !== $default) {
56567 throw new LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.');
56568 }
56569
56570 if ($this->isArray()) {
56571 if (null === $default) {
56572 $default = array();
56573 } elseif (!is_array($default)) {
56574 throw new LogicException('A default value for an array argument must be an array.');
56575 }
56576 }
56577
56578 $this->default = $default;
56579 }
56580
56581
56582
56583
56584
56585
56586 public function getDefault()
56587 {
56588 return $this->default;
56589 }
56590
56591
56592
56593
56594
56595
56596 public function getDescription()
56597 {
56598 return $this->description;
56599 }
56600 }
56601 <?php
56602
56603
56604
56605
56606
56607
56608
56609
56610
56611
56612 namespace Symfony\Component\Console\Input;
56613
56614
56615
56616
56617
56618
56619
56620 interface InputAwareInterface
56621 {
56622
56623
56624
56625
56626
56627 public function setInput(InputInterface $input);
56628 }
56629 <?php
56630
56631
56632
56633
56634
56635
56636
56637
56638
56639
56640 namespace Symfony\Component\Console\Input;
56641
56642 use Symfony\Component\Console\Descriptor\TextDescriptor;
56643 use Symfony\Component\Console\Descriptor\XmlDescriptor;
56644 use Symfony\Component\Console\Output\BufferedOutput;
56645 use Symfony\Component\Console\Exception\InvalidArgumentException;
56646 use Symfony\Component\Console\Exception\LogicException;
56647
56648
56649
56650
56651
56652
56653
56654
56655
56656
56657
56658
56659
56660 class InputDefinition
56661 {
56662 private $arguments;
56663 private $requiredCount;
56664 private $hasAnArrayArgument = false;
56665 private $hasOptional;
56666 private $options;
56667 private $shortcuts;
56668
56669
56670
56671
56672
56673
56674 public function __construct(array $definition = array())
56675 {
56676 $this->setDefinition($definition);
56677 }
56678
56679
56680
56681
56682
56683
56684 public function setDefinition(array $definition)
56685 {
56686 $arguments = array();
56687 $options = array();
56688 foreach ($definition as $item) {
56689 if ($item instanceof InputOption) {
56690 $options[] = $item;
56691 } else {
56692 $arguments[] = $item;
56693 }
56694 }
56695
56696 $this->setArguments($arguments);
56697 $this->setOptions($options);
56698 }
56699
56700
56701
56702
56703
56704
56705 public function setArguments($arguments = array())
56706 {
56707 $this->arguments = array();
56708 $this->requiredCount = 0;
56709 $this->hasOptional = false;
56710 $this->hasAnArrayArgument = false;
56711 $this->addArguments($arguments);
56712 }
56713
56714
56715
56716
56717
56718
56719 public function addArguments($arguments = array())
56720 {
56721 if (null !== $arguments) {
56722 foreach ($arguments as $argument) {
56723 $this->addArgument($argument);
56724 }
56725 }
56726 }
56727
56728
56729
56730
56731
56732
56733
56734
56735 public function addArgument(InputArgument $argument)
56736 {
56737 if (isset($this->arguments[$argument->getName()])) {
56738 throw new LogicException(sprintf('An argument with name "%s" already exists.', $argument->getName()));
56739 }
56740
56741 if ($this->hasAnArrayArgument) {
56742 throw new LogicException('Cannot add an argument after an array argument.');
56743 }
56744
56745 if ($argument->isRequired() && $this->hasOptional) {
56746 throw new LogicException('Cannot add a required argument after an optional one.');
56747 }
56748
56749 if ($argument->isArray()) {
56750 $this->hasAnArrayArgument = true;
56751 }
56752
56753 if ($argument->isRequired()) {
56754 ++$this->requiredCount;
56755 } else {
56756 $this->hasOptional = true;
56757 }
56758
56759 $this->arguments[$argument->getName()] = $argument;
56760 }
56761
56762
56763
56764
56765
56766
56767
56768
56769
56770
56771 public function getArgument($name)
56772 {
56773 if (!$this->hasArgument($name)) {
56774 throw new InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
56775 }
56776
56777 $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
56778
56779 return $arguments[$name];
56780 }
56781
56782
56783
56784
56785
56786
56787
56788
56789 public function hasArgument($name)
56790 {
56791 $arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
56792
56793 return isset($arguments[$name]);
56794 }
56795
56796
56797
56798
56799
56800
56801 public function getArguments()
56802 {
56803 return $this->arguments;
56804 }
56805
56806
56807
56808
56809
56810
56811 public function getArgumentCount()
56812 {
56813 return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments);
56814 }
56815
56816
56817
56818
56819
56820
56821 public function getArgumentRequiredCount()
56822 {
56823 return $this->requiredCount;
56824 }
56825
56826
56827
56828
56829
56830
56831 public function getArgumentDefaults()
56832 {
56833 $values = array();
56834 foreach ($this->arguments as $argument) {
56835 $values[$argument->getName()] = $argument->getDefault();
56836 }
56837
56838 return $values;
56839 }
56840
56841
56842
56843
56844
56845
56846 public function setOptions($options = array())
56847 {
56848 $this->options = array();
56849 $this->shortcuts = array();
56850 $this->addOptions($options);
56851 }
56852
56853
56854
56855
56856
56857
56858 public function addOptions($options = array())
56859 {
56860 foreach ($options as $option) {
56861 $this->addOption($option);
56862 }
56863 }
56864
56865
56866
56867
56868
56869
56870
56871
56872 public function addOption(InputOption $option)
56873 {
56874 if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
56875 throw new LogicException(sprintf('An option named "%s" already exists.', $option->getName()));
56876 }
56877
56878 if ($option->getShortcut()) {
56879 foreach (explode('|', $option->getShortcut()) as $shortcut) {
56880 if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) {
56881 throw new LogicException(sprintf('An option with shortcut "%s" already exists.', $shortcut));
56882 }
56883 }
56884 }
56885
56886 $this->options[$option->getName()] = $option;
56887 if ($option->getShortcut()) {
56888 foreach (explode('|', $option->getShortcut()) as $shortcut) {
56889 $this->shortcuts[$shortcut] = $option->getName();
56890 }
56891 }
56892 }
56893
56894
56895
56896
56897
56898
56899
56900
56901
56902
56903 public function getOption($name)
56904 {
56905 if (!$this->hasOption($name)) {
56906 throw new InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
56907 }
56908
56909 return $this->options[$name];
56910 }
56911
56912
56913
56914
56915
56916
56917
56918
56919
56920
56921
56922 public function hasOption($name)
56923 {
56924 return isset($this->options[$name]);
56925 }
56926
56927
56928
56929
56930
56931
56932 public function getOptions()
56933 {
56934 return $this->options;
56935 }
56936
56937
56938
56939
56940
56941
56942
56943
56944 public function hasShortcut($name)
56945 {
56946 return isset($this->shortcuts[$name]);
56947 }
56948
56949
56950
56951
56952
56953
56954
56955
56956 public function getOptionForShortcut($shortcut)
56957 {
56958 return $this->getOption($this->shortcutToName($shortcut));
56959 }
56960
56961
56962
56963
56964
56965
56966 public function getOptionDefaults()
56967 {
56968 $values = array();
56969 foreach ($this->options as $option) {
56970 $values[$option->getName()] = $option->getDefault();
56971 }
56972
56973 return $values;
56974 }
56975
56976
56977
56978
56979
56980
56981
56982
56983
56984
56985 private function shortcutToName($shortcut)
56986 {
56987 if (!isset($this->shortcuts[$shortcut])) {
56988 throw new InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
56989 }
56990
56991 return $this->shortcuts[$shortcut];
56992 }
56993
56994
56995
56996
56997
56998
56999
57000
57001 public function getSynopsis($short = false)
57002 {
57003 $elements = array();
57004
57005 if ($short && $this->getOptions()) {
57006 $elements[] = '[options]';
57007 } elseif (!$short) {
57008 foreach ($this->getOptions() as $option) {
57009 $value = '';
57010 if ($option->acceptValue()) {
57011 $value = sprintf(
57012 ' %s%s%s',
57013 $option->isValueOptional() ? '[' : '',
57014 strtoupper($option->getName()),
57015 $option->isValueOptional() ? ']' : ''
57016 );
57017 }
57018
57019 $shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
57020 $elements[] = sprintf('[%s--%s%s]', $shortcut, $option->getName(), $value);
57021 }
57022 }
57023
57024 if (count($elements) && $this->getArguments()) {
57025 $elements[] = '[--]';
57026 }
57027
57028 foreach ($this->getArguments() as $argument) {
57029 $element = '<'.$argument->getName().'>';
57030 if (!$argument->isRequired()) {
57031 $element = '['.$element.']';
57032 } elseif ($argument->isArray()) {
57033 $element = $element.' ('.$element.')';
57034 }
57035
57036 if ($argument->isArray()) {
57037 $element .= '...';
57038 }
57039
57040 $elements[] = $element;
57041 }
57042
57043 return implode(' ', $elements);
57044 }
57045
57046
57047
57048
57049
57050
57051
57052
57053 public function asText()
57054 {
57055 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
57056
57057 $descriptor = new TextDescriptor();
57058 $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true);
57059 $descriptor->describe($output, $this, array('raw_output' => true));
57060
57061 return $output->fetch();
57062 }
57063
57064
57065
57066
57067
57068
57069
57070
57071
57072
57073 public function asXml($asDom = false)
57074 {
57075 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.3 and will be removed in 3.0.', E_USER_DEPRECATED);
57076
57077 $descriptor = new XmlDescriptor();
57078
57079 if ($asDom) {
57080 return $descriptor->getInputDefinitionDocument($this);
57081 }
57082
57083 $output = new BufferedOutput();
57084 $descriptor->describe($output, $this);
57085
57086 return $output->fetch();
57087 }
57088 }
57089 <?php
57090
57091
57092
57093
57094
57095
57096
57097
57098
57099
57100 namespace Symfony\Component\Console\Input;
57101
57102 use Symfony\Component\Console\Exception\InvalidArgumentException;
57103 use Symfony\Component\Console\Exception\RuntimeException;
57104
57105
57106
57107
57108
57109
57110 interface InputInterface
57111 {
57112
57113
57114
57115
57116
57117 public function getFirstArgument();
57118
57119
57120
57121
57122
57123
57124
57125
57126
57127
57128
57129 public function hasParameterOption($values);
57130
57131
57132
57133
57134
57135
57136
57137
57138
57139
57140
57141
57142 public function getParameterOption($values, $default = false);
57143
57144
57145
57146
57147
57148
57149 public function bind(InputDefinition $definition);
57150
57151
57152
57153
57154
57155
57156 public function validate();
57157
57158
57159
57160
57161
57162
57163 public function getArguments();
57164
57165
57166
57167
57168
57169
57170
57171
57172
57173
57174 public function getArgument($name);
57175
57176
57177
57178
57179
57180
57181
57182
57183
57184 public function setArgument($name, $value);
57185
57186
57187
57188
57189
57190
57191
57192
57193 public function hasArgument($name);
57194
57195
57196
57197
57198
57199
57200 public function getOptions();
57201
57202
57203
57204
57205
57206
57207
57208
57209
57210
57211 public function getOption($name);
57212
57213
57214
57215
57216
57217
57218
57219
57220
57221 public function setOption($name, $value);
57222
57223
57224
57225
57226
57227
57228
57229
57230 public function hasOption($name);
57231
57232
57233
57234
57235
57236
57237 public function isInteractive();
57238
57239
57240
57241
57242
57243
57244 public function setInteractive($interactive);
57245 }
57246 <?php
57247
57248
57249
57250
57251
57252
57253
57254
57255
57256
57257 namespace Symfony\Component\Console\Input;
57258
57259 use Symfony\Component\Console\Exception\InvalidArgumentException;
57260 use Symfony\Component\Console\Exception\LogicException;
57261
57262
57263
57264
57265
57266
57267 class InputOption
57268 {
57269 const VALUE_NONE = 1;
57270 const VALUE_REQUIRED = 2;
57271 const VALUE_OPTIONAL = 4;
57272 const VALUE_IS_ARRAY = 8;
57273
57274 private $name;
57275 private $shortcut;
57276 private $mode;
57277 private $default;
57278 private $description;
57279
57280
57281
57282
57283
57284
57285
57286
57287
57288
57289
57290
57291 public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null)
57292 {
57293 if (0 === strpos($name, '--')) {
57294 $name = substr($name, 2);
57295 }
57296
57297 if (empty($name)) {
57298 throw new InvalidArgumentException('An option name cannot be empty.');
57299 }
57300
57301 if (empty($shortcut)) {
57302 $shortcut = null;
57303 }
57304
57305 if (null !== $shortcut) {
57306 if (is_array($shortcut)) {
57307 $shortcut = implode('|', $shortcut);
57308 }
57309 $shortcuts = preg_split('{(\|)-?}', ltrim($shortcut, '-'));
57310 $shortcuts = array_filter($shortcuts);
57311 $shortcut = implode('|', $shortcuts);
57312
57313 if (empty($shortcut)) {
57314 throw new InvalidArgumentException('An option shortcut cannot be empty.');
57315 }
57316 }
57317
57318 if (null === $mode) {
57319 $mode = self::VALUE_NONE;
57320 } elseif (!is_int($mode) || $mode > 15 || $mode < 1) {
57321 throw new InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
57322 }
57323
57324 $this->name = $name;
57325 $this->shortcut = $shortcut;
57326 $this->mode = $mode;
57327 $this->description = $description;
57328
57329 if ($this->isArray() && !$this->acceptValue()) {
57330 throw new InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.');
57331 }
57332
57333 $this->setDefault($default);
57334 }
57335
57336
57337
57338
57339
57340
57341 public function getShortcut()
57342 {
57343 return $this->shortcut;
57344 }
57345
57346
57347
57348
57349
57350
57351 public function getName()
57352 {
57353 return $this->name;
57354 }
57355
57356
57357
57358
57359
57360
57361 public function acceptValue()
57362 {
57363 return $this->isValueRequired() || $this->isValueOptional();
57364 }
57365
57366
57367
57368
57369
57370
57371 public function isValueRequired()
57372 {
57373 return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode);
57374 }
57375
57376
57377
57378
57379
57380
57381 public function isValueOptional()
57382 {
57383 return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode);
57384 }
57385
57386
57387
57388
57389
57390
57391 public function isArray()
57392 {
57393 return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
57394 }
57395
57396
57397
57398
57399
57400
57401
57402
57403 public function setDefault($default = null)
57404 {
57405 if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
57406 throw new LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
57407 }
57408
57409 if ($this->isArray()) {
57410 if (null === $default) {
57411 $default = array();
57412 } elseif (!is_array($default)) {
57413 throw new LogicException('A default value for an array option must be an array.');
57414 }
57415 }
57416
57417 $this->default = $this->acceptValue() ? $default : false;
57418 }
57419
57420
57421
57422
57423
57424
57425 public function getDefault()
57426 {
57427 return $this->default;
57428 }
57429
57430
57431
57432
57433
57434
57435 public function getDescription()
57436 {
57437 return $this->description;
57438 }
57439
57440
57441
57442
57443
57444
57445
57446
57447 public function equals(InputOption $option)
57448 {
57449 return $option->getName() === $this->getName()
57450 && $option->getShortcut() === $this->getShortcut()
57451 && $option->getDefault() === $this->getDefault()
57452 && $option->isArray() === $this->isArray()
57453 && $option->isValueRequired() === $this->isValueRequired()
57454 && $option->isValueOptional() === $this->isValueOptional()
57455 ;
57456 }
57457 }
57458 <?php
57459
57460
57461
57462
57463
57464
57465
57466
57467
57468
57469 namespace Symfony\Component\Console\Input;
57470
57471 use Symfony\Component\Console\Exception\InvalidArgumentException;
57472
57473
57474
57475
57476
57477
57478
57479
57480
57481
57482 class StringInput extends ArgvInput
57483 {
57484 const REGEX_STRING = '([^\s]+?)(?:\s|(?<!\\\\)"|(?<!\\\\)\'|$)';
57485 const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
57486
57487
57488
57489
57490
57491
57492
57493
57494
57495 public function __construct($input, InputDefinition $definition = null)
57496 {
57497 if ($definition) {
57498 @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);
57499 }
57500
57501 parent::__construct(array(), null);
57502
57503 $this->setTokens($this->tokenize($input));
57504
57505 if (null !== $definition) {
57506 $this->bind($definition);
57507 }
57508 }
57509
57510
57511
57512
57513
57514
57515
57516
57517
57518
57519 private function tokenize($input)
57520 {
57521 $tokens = array();
57522 $length = strlen($input);
57523 $cursor = 0;
57524 while ($cursor < $length) {
57525 if (preg_match('/\s+/A', $input, $match, null, $cursor)) {
57526 } elseif (preg_match('/([^="\'\s]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor)) {
57527 $tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2)));
57528 } elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor)) {
57529 $tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2));
57530 } elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor)) {
57531 $tokens[] = stripcslashes($match[1]);
57532 } else {
57533
57534  throw new InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10)));
57535 }
57536
57537 $cursor += strlen($match[0]);
57538 }
57539
57540 return $tokens;
57541 }
57542 }
57543 Copyright (c) 2004-2017 Fabien Potencier
57544
57545 Permission is hereby granted, free of charge, to any person obtaining a copy
57546 of this software and associated documentation files (the "Software"), to deal
57547 in the Software without restriction, including without limitation the rights
57548 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
57549 copies of the Software, and to permit persons to whom the Software is furnished
57550 to do so, subject to the following conditions:
57551
57552 The above copyright notice and this permission notice shall be included in all
57553 copies or substantial portions of the Software.
57554
57555 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
57556 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
57557 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
57558 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
57559 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
57560 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
57561 THE SOFTWARE.
57562 <?php
57563
57564
57565
57566
57567
57568
57569
57570
57571
57572
57573 namespace Symfony\Component\Console\Logger;
57574
57575 use Psr\Log\AbstractLogger;
57576 use Psr\Log\InvalidArgumentException;
57577 use Psr\Log\LogLevel;
57578 use Symfony\Component\Console\Output\OutputInterface;
57579 use Symfony\Component\Console\Output\ConsoleOutputInterface;
57580
57581
57582
57583
57584
57585
57586
57587
57588 class ConsoleLogger extends AbstractLogger
57589 {
57590 const INFO = 'info';
57591 const ERROR = 'error';
57592
57593
57594
57595
57596 private $output;
57597
57598
57599
57600 private $verbosityLevelMap = array(
57601 LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL,
57602 LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL,
57603 LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL,
57604 LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL,
57605 LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL,
57606 LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE,
57607 LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE,
57608 LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG,
57609 );
57610
57611
57612
57613 private $formatLevelMap = array(
57614 LogLevel::EMERGENCY => self::ERROR,
57615 LogLevel::ALERT => self::ERROR,
57616 LogLevel::CRITICAL => self::ERROR,
57617 LogLevel::ERROR => self::ERROR,
57618 LogLevel::WARNING => self::INFO,
57619 LogLevel::NOTICE => self::INFO,
57620 LogLevel::INFO => self::INFO,
57621 LogLevel::DEBUG => self::INFO,
57622 );
57623
57624
57625
57626
57627
57628
57629 public function __construct(OutputInterface $output, array $verbosityLevelMap = array(), array $formatLevelMap = array())
57630 {
57631 $this->output = $output;
57632 $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
57633 $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap;
57634 }
57635
57636
57637
57638
57639 public function log($level, $message, array $context = array())
57640 {
57641 if (!isset($this->verbosityLevelMap[$level])) {
57642 throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level));
57643 }
57644
57645
57646  if ($this->formatLevelMap[$level] === self::ERROR && $this->output instanceof ConsoleOutputInterface) {
57647 $output = $this->output->getErrorOutput();
57648 } else {
57649 $output = $this->output;
57650 }
57651
57652 if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) {
57653 $output->writeln(sprintf('<%1$s>[%2$s] %3$s</%1$s>', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)));
57654 }
57655 }
57656
57657
57658
57659
57660
57661
57662
57663
57664
57665
57666
57667 private function interpolate($message, array $context)
57668 {
57669
57670  $replace = array();
57671 foreach ($context as $key => $val) {
57672 if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) {
57673 $replace[sprintf('{%s}', $key)] = $val;
57674 }
57675 }
57676
57677
57678  return strtr($message, $replace);
57679 }
57680 }
57681 <?php
57682
57683
57684
57685
57686
57687
57688
57689
57690
57691
57692 namespace Symfony\Component\Console\Output;
57693
57694
57695
57696
57697 class BufferedOutput extends Output
57698 {
57699
57700
57701
57702 private $buffer = '';
57703
57704
57705
57706
57707
57708
57709 public function fetch()
57710 {
57711 $content = $this->buffer;
57712 $this->buffer = '';
57713
57714 return $content;
57715 }
57716
57717
57718
57719
57720 protected function doWrite($message, $newline)
57721 {
57722 $this->buffer .= $message;
57723
57724 if ($newline) {
57725 $this->buffer .= PHP_EOL;
57726 }
57727 }
57728 }
57729 <?php
57730
57731
57732
57733
57734
57735
57736
57737
57738
57739
57740 namespace Symfony\Component\Console\Output;
57741
57742 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
57743
57744
57745
57746
57747
57748
57749
57750
57751
57752
57753
57754
57755
57756
57757 class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
57758 {
57759
57760
57761
57762 private $stderr;
57763
57764
57765
57766
57767
57768
57769
57770
57771 public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
57772 {
57773 parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter);
57774
57775 $actualDecorated = $this->isDecorated();
57776 $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter());
57777
57778 if (null === $decorated) {
57779 $this->setDecorated($actualDecorated && $this->stderr->isDecorated());
57780 }
57781 }
57782
57783
57784
57785
57786 public function setDecorated($decorated)
57787 {
57788 parent::setDecorated($decorated);
57789 $this->stderr->setDecorated($decorated);
57790 }
57791
57792
57793
57794
57795 public function setFormatter(OutputFormatterInterface $formatter)
57796 {
57797 parent::setFormatter($formatter);
57798 $this->stderr->setFormatter($formatter);
57799 }
57800
57801
57802
57803
57804 public function setVerbosity($level)
57805 {
57806 parent::setVerbosity($level);
57807 $this->stderr->setVerbosity($level);
57808 }
57809
57810
57811
57812
57813 public function getErrorOutput()
57814 {
57815 return $this->stderr;
57816 }
57817
57818
57819
57820
57821 public function setErrorOutput(OutputInterface $error)
57822 {
57823 $this->stderr = $error;
57824 }
57825
57826
57827
57828
57829
57830
57831
57832 protected function hasStdoutSupport()
57833 {
57834 return false === $this->isRunningOS400();
57835 }
57836
57837
57838
57839
57840
57841
57842
57843 protected function hasStderrSupport()
57844 {
57845 return false === $this->isRunningOS400();
57846 }
57847
57848
57849
57850
57851
57852
57853
57854 private function isRunningOS400()
57855 {
57856 $checks = array(
57857 function_exists('php_uname') ? php_uname('s') : '',
57858 getenv('OSTYPE'),
57859 PHP_OS,
57860 );
57861
57862 return false !== stripos(implode(';', $checks), 'OS400');
57863 }
57864
57865
57866
57867
57868 private function openOutputStream()
57869 {
57870 $outputStream = $this->hasStdoutSupport() ? 'php://stdout' : 'php://output';
57871
57872 return @fopen($outputStream, 'w') ?: fopen('php://output', 'w');
57873 }
57874
57875
57876
57877
57878 private function openErrorStream()
57879 {
57880 $errorStream = $this->hasStderrSupport() ? 'php://stderr' : 'php://output';
57881
57882 return fopen($errorStream, 'w');
57883 }
57884 }
57885 <?php
57886
57887
57888
57889
57890
57891
57892
57893
57894
57895
57896 namespace Symfony\Component\Console\Output;
57897
57898
57899
57900
57901
57902
57903
57904 interface ConsoleOutputInterface extends OutputInterface
57905 {
57906
57907
57908
57909
57910
57911 public function getErrorOutput();
57912
57913
57914
57915
57916
57917
57918 public function setErrorOutput(OutputInterface $error);
57919 }
57920 <?php
57921
57922
57923
57924
57925
57926
57927
57928
57929
57930
57931 namespace Symfony\Component\Console\Output;
57932
57933 use Symfony\Component\Console\Formatter\OutputFormatter;
57934 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
57935
57936
57937
57938
57939
57940
57941
57942
57943
57944 class NullOutput implements OutputInterface
57945 {
57946
57947
57948
57949 public function setFormatter(OutputFormatterInterface $formatter)
57950 {
57951
57952  }
57953
57954
57955
57956
57957 public function getFormatter()
57958 {
57959
57960  return new OutputFormatter();
57961 }
57962
57963
57964
57965
57966 public function setDecorated($decorated)
57967 {
57968
57969  }
57970
57971
57972
57973
57974 public function isDecorated()
57975 {
57976 return false;
57977 }
57978
57979
57980
57981
57982 public function setVerbosity($level)
57983 {
57984
57985  }
57986
57987
57988
57989
57990 public function getVerbosity()
57991 {
57992 return self::VERBOSITY_QUIET;
57993 }
57994
57995
57996
57997
57998 public function isQuiet()
57999 {
58000 return true;
58001 }
58002
58003
58004
58005
58006 public function isVerbose()
58007 {
58008 return false;
58009 }
58010
58011
58012
58013
58014 public function isVeryVerbose()
58015 {
58016 return false;
58017 }
58018
58019
58020
58021
58022 public function isDebug()
58023 {
58024 return false;
58025 }
58026
58027
58028
58029
58030 public function writeln($messages, $options = self::OUTPUT_NORMAL)
58031 {
58032
58033  }
58034
58035
58036
58037
58038 public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
58039 {
58040
58041  }
58042 }
58043 <?php
58044
58045
58046
58047
58048
58049
58050
58051
58052
58053
58054 namespace Symfony\Component\Console\Output;
58055
58056 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
58057 use Symfony\Component\Console\Formatter\OutputFormatter;
58058
58059
58060
58061
58062
58063
58064
58065
58066
58067
58068
58069
58070
58071
58072 abstract class Output implements OutputInterface
58073 {
58074 private $verbosity;
58075 private $formatter;
58076
58077
58078
58079
58080
58081
58082
58083
58084 public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = false, OutputFormatterInterface $formatter = null)
58085 {
58086 $this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity;
58087 $this->formatter = $formatter ?: new OutputFormatter();
58088 $this->formatter->setDecorated($decorated);
58089 }
58090
58091
58092
58093
58094 public function setFormatter(OutputFormatterInterface $formatter)
58095 {
58096 $this->formatter = $formatter;
58097 }
58098
58099
58100
58101
58102 public function getFormatter()
58103 {
58104 return $this->formatter;
58105 }
58106
58107
58108
58109
58110 public function setDecorated($decorated)
58111 {
58112 $this->formatter->setDecorated($decorated);
58113 }
58114
58115
58116
58117
58118 public function isDecorated()
58119 {
58120 return $this->formatter->isDecorated();
58121 }
58122
58123
58124
58125
58126 public function setVerbosity($level)
58127 {
58128 $this->verbosity = (int) $level;
58129 }
58130
58131
58132
58133
58134 public function getVerbosity()
58135 {
58136 return $this->verbosity;
58137 }
58138
58139
58140
58141
58142 public function isQuiet()
58143 {
58144 return self::VERBOSITY_QUIET === $this->verbosity;
58145 }
58146
58147
58148
58149
58150 public function isVerbose()
58151 {
58152 return self::VERBOSITY_VERBOSE <= $this->verbosity;
58153 }
58154
58155
58156
58157
58158 public function isVeryVerbose()
58159 {
58160 return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
58161 }
58162
58163
58164
58165
58166 public function isDebug()
58167 {
58168 return self::VERBOSITY_DEBUG <= $this->verbosity;
58169 }
58170
58171
58172
58173
58174 public function writeln($messages, $options = self::OUTPUT_NORMAL)
58175 {
58176 $this->write($messages, true, $options);
58177 }
58178
58179
58180
58181
58182 public function write($messages, $newline = false, $options = self::OUTPUT_NORMAL)
58183 {
58184 $messages = (array) $messages;
58185
58186 $types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN;
58187 $type = $types & $options ?: self::OUTPUT_NORMAL;
58188
58189 $verbosities = self::VERBOSITY_QUIET | self::VERBOSITY_NORMAL | self::VERBOSITY_VERBOSE | self::VERBOSITY_VERY_VERBOSE | self::VERBOSITY_DEBUG;
58190 $verbosity = $verbosities & $options ?: self::VERBOSITY_NORMAL;
58191
58192 if ($verbosity > $this->getVerbosity()) {
58193 return;
58194 }
58195
58196 foreach ($messages as $message) {
58197 switch ($type) {
58198 case OutputInterface::OUTPUT_NORMAL:
58199 $message = $this->formatter->format($message);
58200 break;
58201 case OutputInterface::OUTPUT_RAW:
58202 break;
58203 case OutputInterface::OUTPUT_PLAIN:
58204 $message = strip_tags($this->formatter->format($message));
58205 break;
58206 }
58207
58208 $this->doWrite($message, $newline);
58209 }
58210 }
58211
58212
58213
58214
58215
58216
58217
58218 abstract protected function doWrite($message, $newline);
58219 }
58220 <?php
58221
58222
58223
58224
58225
58226
58227
58228
58229
58230
58231 namespace Symfony\Component\Console\Output;
58232
58233 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
58234
58235
58236
58237
58238
58239
58240 interface OutputInterface
58241 {
58242 const VERBOSITY_QUIET = 16;
58243 const VERBOSITY_NORMAL = 32;
58244 const VERBOSITY_VERBOSE = 64;
58245 const VERBOSITY_VERY_VERBOSE = 128;
58246 const VERBOSITY_DEBUG = 256;
58247
58248 const OUTPUT_NORMAL = 1;
58249 const OUTPUT_RAW = 2;
58250 const OUTPUT_PLAIN = 4;
58251
58252
58253
58254
58255
58256
58257
58258
58259 public function write($messages, $newline = false, $options = 0);
58260
58261
58262
58263
58264
58265
58266
58267 public function writeln($messages, $options = 0);
58268
58269
58270
58271
58272
58273
58274 public function setVerbosity($level);
58275
58276
58277
58278
58279
58280
58281 public function getVerbosity();
58282
58283
58284
58285
58286
58287
58288 public function setDecorated($decorated);
58289
58290
58291
58292
58293
58294
58295 public function isDecorated();
58296
58297
58298
58299
58300
58301
58302 public function setFormatter(OutputFormatterInterface $formatter);
58303
58304
58305
58306
58307
58308
58309 public function getFormatter();
58310 }
58311 <?php
58312
58313
58314
58315
58316
58317
58318
58319
58320
58321
58322 namespace Symfony\Component\Console\Output;
58323
58324 use Symfony\Component\Console\Exception\InvalidArgumentException;
58325 use Symfony\Component\Console\Exception\RuntimeException;
58326 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
58327
58328
58329
58330
58331
58332
58333
58334
58335
58336
58337
58338
58339
58340
58341 class StreamOutput extends Output
58342 {
58343 private $stream;
58344
58345
58346
58347
58348
58349
58350
58351
58352
58353
58354
58355 public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null, OutputFormatterInterface $formatter = null)
58356 {
58357 if (!is_resource($stream) || 'stream' !== get_resource_type($stream)) {
58358 throw new InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
58359 }
58360
58361 $this->stream = $stream;
58362
58363 if (null === $decorated) {
58364 $decorated = $this->hasColorSupport();
58365 }
58366
58367 parent::__construct($verbosity, $decorated, $formatter);
58368 }
58369
58370
58371
58372
58373
58374
58375 public function getStream()
58376 {
58377 return $this->stream;
58378 }
58379
58380
58381
58382
58383 protected function doWrite($message, $newline)
58384 {
58385 if (false === @fwrite($this->stream, $message) || ($newline && (false === @fwrite($this->stream, PHP_EOL)))) {
58386
58387  throw new RuntimeException('Unable to write output.');
58388 }
58389
58390 fflush($this->stream);
58391 }
58392
58393
58394
58395
58396
58397
58398
58399
58400
58401
58402
58403 protected function hasColorSupport()
58404 {
58405 if (DIRECTORY_SEPARATOR === '\\') {
58406 return
58407 '10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD
58408 || false !== getenv('ANSICON')
58409 || 'ON' === getenv('ConEmuANSI')
58410 || 'xterm' === getenv('TERM');
58411 }
58412
58413 return function_exists('posix_isatty') && @posix_isatty($this->stream);
58414 }
58415 }
58416 <?php
58417
58418
58419
58420
58421
58422
58423
58424
58425
58426
58427 namespace Symfony\Component\Console\Question;
58428
58429 use Symfony\Component\Console\Exception\InvalidArgumentException;
58430
58431
58432
58433
58434
58435
58436 class ChoiceQuestion extends Question
58437 {
58438 private $choices;
58439 private $multiselect = false;
58440 private $prompt = ' > ';
58441 private $errorMessage = 'Value "%s" is invalid';
58442
58443
58444
58445
58446
58447
58448
58449
58450 public function __construct($question, array $choices, $default = null)
58451 {
58452 if (!$choices) {
58453 throw new \LogicException('Choice question must have at least 1 choice available.');
58454 }
58455
58456 parent::__construct($question, $default);
58457
58458 $this->choices = $choices;
58459 $this->setValidator($this->getDefaultValidator());
58460 $this->setAutocompleterValues($choices);
58461 }
58462
58463
58464
58465
58466
58467
58468 public function getChoices()
58469 {
58470 return $this->choices;
58471 }
58472
58473
58474
58475
58476
58477
58478
58479
58480
58481
58482 public function setMultiselect($multiselect)
58483 {
58484 $this->multiselect = $multiselect;
58485 $this->setValidator($this->getDefaultValidator());
58486
58487 return $this;
58488 }
58489
58490
58491
58492
58493
58494
58495 public function isMultiselect()
58496 {
58497 return $this->multiselect;
58498 }
58499
58500
58501
58502
58503
58504
58505 public function getPrompt()
58506 {
58507 return $this->prompt;
58508 }
58509
58510
58511
58512
58513
58514
58515
58516
58517 public function setPrompt($prompt)
58518 {
58519 $this->prompt = $prompt;
58520
58521 return $this;
58522 }
58523
58524
58525
58526
58527
58528
58529
58530
58531
58532
58533 public function setErrorMessage($errorMessage)
58534 {
58535 $this->errorMessage = $errorMessage;
58536 $this->setValidator($this->getDefaultValidator());
58537
58538 return $this;
58539 }
58540
58541
58542
58543
58544
58545
58546 private function getDefaultValidator()
58547 {
58548 $choices = $this->choices;
58549 $errorMessage = $this->errorMessage;
58550 $multiselect = $this->multiselect;
58551 $isAssoc = $this->isAssoc($choices);
58552
58553 return function ($selected) use ($choices, $errorMessage, $multiselect, $isAssoc) {
58554
58555  $selectedChoices = str_replace(' ', '', $selected);
58556
58557 if ($multiselect) {
58558
58559  if (!preg_match('/^[^,]+(?:,[^,]+)*$/', $selectedChoices, $matches)) {
58560 throw new InvalidArgumentException(sprintf($errorMessage, $selected));
58561 }
58562 $selectedChoices = explode(',', $selectedChoices);
58563 } else {
58564 $selectedChoices = array($selected);
58565 }
58566
58567 $multiselectChoices = array();
58568 foreach ($selectedChoices as $value) {
58569 $results = array();
58570 foreach ($choices as $key => $choice) {
58571 if ($choice === $value) {
58572 $results[] = $key;
58573 }
58574 }
58575
58576 if (count($results) > 1) {
58577 throw new InvalidArgumentException(sprintf('The provided answer is ambiguous. Value should be one of %s.', implode(' or ', $results)));
58578 }
58579
58580 $result = array_search($value, $choices);
58581
58582 if (!$isAssoc) {
58583 if (false !== $result) {
58584 $result = $choices[$result];
58585 } elseif (isset($choices[$value])) {
58586 $result = $choices[$value];
58587 }
58588 } elseif (false === $result && isset($choices[$value])) {
58589 $result = $value;
58590 }
58591
58592 if (false === $result) {
58593 throw new InvalidArgumentException(sprintf($errorMessage, $value));
58594 }
58595
58596 $multiselectChoices[] = (string) $result;
58597 }
58598
58599 if ($multiselect) {
58600 return $multiselectChoices;
58601 }
58602
58603 return current($multiselectChoices);
58604 };
58605 }
58606 }
58607 <?php
58608
58609
58610
58611
58612
58613
58614
58615
58616
58617
58618 namespace Symfony\Component\Console\Question;
58619
58620
58621
58622
58623
58624
58625 class ConfirmationQuestion extends Question
58626 {
58627 private $trueAnswerRegex;
58628
58629
58630
58631
58632
58633
58634
58635
58636 public function __construct($question, $default = true, $trueAnswerRegex = '/^y/i')
58637 {
58638 parent::__construct($question, (bool) $default);
58639
58640 $this->trueAnswerRegex = $trueAnswerRegex;
58641 $this->setNormalizer($this->getDefaultNormalizer());
58642 }
58643
58644
58645
58646
58647
58648
58649 private function getDefaultNormalizer()
58650 {
58651 $default = $this->getDefault();
58652 $regex = $this->trueAnswerRegex;
58653
58654 return function ($answer) use ($default, $regex) {
58655 if (is_bool($answer)) {
58656 return $answer;
58657 }
58658
58659 $answerIsTrue = (bool) preg_match($regex, $answer);
58660 if (false === $default) {
58661 return $answer && $answerIsTrue;
58662 }
58663
58664 return !$answer || $answerIsTrue;
58665 };
58666 }
58667 }
58668 <?php
58669
58670
58671
58672
58673
58674
58675
58676
58677
58678
58679 namespace Symfony\Component\Console\Question;
58680
58681 use Symfony\Component\Console\Exception\InvalidArgumentException;
58682 use Symfony\Component\Console\Exception\LogicException;
58683
58684
58685
58686
58687
58688
58689 class Question
58690 {
58691 private $question;
58692 private $attempts;
58693 private $hidden = false;
58694 private $hiddenFallback = true;
58695 private $autocompleterValues;
58696 private $validator;
58697 private $default;
58698 private $normalizer;
58699
58700
58701
58702
58703
58704
58705
58706 public function __construct($question, $default = null)
58707 {
58708 $this->question = $question;
58709 $this->default = $default;
58710 }
58711
58712
58713
58714
58715
58716
58717 public function getQuestion()
58718 {
58719 return $this->question;
58720 }
58721
58722
58723
58724
58725
58726
58727 public function getDefault()
58728 {
58729 return $this->default;
58730 }
58731
58732
58733
58734
58735
58736
58737 public function isHidden()
58738 {
58739 return $this->hidden;
58740 }
58741
58742
58743
58744
58745
58746
58747
58748
58749
58750
58751 public function setHidden($hidden)
58752 {
58753 if ($this->autocompleterValues) {
58754 throw new LogicException('A hidden question cannot use the autocompleter.');
58755 }
58756
58757 $this->hidden = (bool) $hidden;
58758
58759 return $this;
58760 }
58761
58762
58763
58764
58765
58766
58767 public function isHiddenFallback()
58768 {
58769 return $this->hiddenFallback;
58770 }
58771
58772
58773
58774
58775
58776
58777
58778
58779 public function setHiddenFallback($fallback)
58780 {
58781 $this->hiddenFallback = (bool) $fallback;
58782
58783 return $this;
58784 }
58785
58786
58787
58788
58789
58790
58791 public function getAutocompleterValues()
58792 {
58793 return $this->autocompleterValues;
58794 }
58795
58796
58797
58798
58799
58800
58801
58802
58803
58804
58805
58806 public function setAutocompleterValues($values)
58807 {
58808 if (is_array($values)) {
58809 $values = $this->isAssoc($values) ? array_merge(array_keys($values), array_values($values)) : array_values($values);
58810 }
58811
58812 if (null !== $values && !is_array($values)) {
58813 if (!$values instanceof \Traversable || !$values instanceof \Countable) {
58814 throw new InvalidArgumentException('Autocompleter values can be either an array, `null` or an object implementing both `Countable` and `Traversable` interfaces.');
58815 }
58816 }
58817
58818 if ($this->hidden) {
58819 throw new LogicException('A hidden question cannot use the autocompleter.');
58820 }
58821
58822 $this->autocompleterValues = $values;
58823
58824 return $this;
58825 }
58826
58827
58828
58829
58830
58831
58832
58833
58834 public function setValidator($validator)
58835 {
58836 $this->validator = $validator;
58837
58838 return $this;
58839 }
58840
58841
58842
58843
58844
58845
58846 public function getValidator()
58847 {
58848 return $this->validator;
58849 }
58850
58851
58852
58853
58854
58855
58856
58857
58858
58859
58860
58861
58862 public function setMaxAttempts($attempts)
58863 {
58864 if (null !== $attempts && $attempts < 1) {
58865 throw new InvalidArgumentException('Maximum number of attempts must be a positive value.');
58866 }
58867
58868 $this->attempts = $attempts;
58869
58870 return $this;
58871 }
58872
58873
58874
58875
58876
58877
58878
58879
58880 public function getMaxAttempts()
58881 {
58882 return $this->attempts;
58883 }
58884
58885
58886
58887
58888
58889
58890
58891
58892
58893
58894 public function setNormalizer($normalizer)
58895 {
58896 $this->normalizer = $normalizer;
58897
58898 return $this;
58899 }
58900
58901
58902
58903
58904
58905
58906
58907
58908 public function getNormalizer()
58909 {
58910 return $this->normalizer;
58911 }
58912
58913 protected function isAssoc($array)
58914 {
58915 return (bool) count(array_filter(array_keys($array), 'is_string'));
58916 }
58917 }
58918 <?php
58919
58920
58921
58922
58923
58924
58925
58926
58927
58928
58929 namespace Symfony\Component\Console;
58930
58931 use Symfony\Component\Console\Exception\RuntimeException;
58932 use Symfony\Component\Console\Input\StringInput;
58933 use Symfony\Component\Console\Output\ConsoleOutput;
58934 use Symfony\Component\Process\ProcessBuilder;
58935 use Symfony\Component\Process\PhpExecutableFinder;
58936
58937
58938
58939
58940
58941
58942
58943
58944
58945
58946
58947
58948 class Shell
58949 {
58950 private $application;
58951 private $history;
58952 private $output;
58953 private $hasReadline;
58954 private $processIsolation = false;
58955
58956
58957
58958
58959
58960
58961
58962
58963
58964 public function __construct(Application $application)
58965 {
58966 @trigger_error('The '.__CLASS__.' class is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
58967
58968 $this->hasReadline = function_exists('readline');
58969 $this->application = $application;
58970 $this->history = getenv('HOME').'/.history_'.$application->getName();
58971 $this->output = new ConsoleOutput();
58972 }
58973
58974
58975
58976
58977 public function run()
58978 {
58979 $this->application->setAutoExit(false);
58980 $this->application->setCatchExceptions(true);
58981
58982 if ($this->hasReadline) {
58983 readline_read_history($this->history);
58984 readline_completion_function(array($this, 'autocompleter'));
58985 }
58986
58987 $this->output->writeln($this->getHeader());
58988 $php = null;
58989 if ($this->processIsolation) {
58990 $finder = new PhpExecutableFinder();
58991 $php = $finder->find();
58992 $this->output->writeln(<<<'EOF'
58993 <info>Running with process isolation, you should consider this:</info>
58994   * each command is executed as separate process,
58995   * commands don't support interactivity, all params must be passed explicitly,
58996   * commands output is not colorized.
58997
58998 EOF
58999 );
59000 }
59001
59002 while (true) {
59003 $command = $this->readline();
59004
59005 if (false === $command) {
59006 $this->output->writeln("\n");
59007
59008 break;
59009 }
59010
59011 if ($this->hasReadline) {
59012 readline_add_history($command);
59013 readline_write_history($this->history);
59014 }
59015
59016 if ($this->processIsolation) {
59017 $pb = new ProcessBuilder();
59018
59019 $process = $pb
59020 ->add($php)
59021 ->add($_SERVER['argv'][0])
59022 ->add($command)
59023 ->inheritEnvironmentVariables(true)
59024 ->getProcess()
59025 ;
59026
59027 $output = $this->output;
59028 $process->run(function ($type, $data) use ($output) {
59029 $output->writeln($data);
59030 });
59031
59032 $ret = $process->getExitCode();
59033 } else {
59034 $ret = $this->application->run(new StringInput($command), $this->output);
59035 }
59036
59037 if (0 !== $ret) {
59038 $this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
59039 }
59040 }
59041 }
59042
59043
59044
59045
59046
59047
59048 protected function getHeader()
59049 {
59050 return <<<EOF
59051
59052 Welcome to the <info>{$this->application->getName()}</info> shell (<comment>{$this->application->getVersion()}</comment>).
59053
59054 At the prompt, type <comment>help</comment> for some help,
59055 or <comment>list</comment> to get a list of available commands.
59056
59057 To exit the shell, type <comment>^D</comment>.
59058
59059 EOF;
59060 }
59061
59062
59063
59064
59065
59066
59067 protected function getPrompt()
59068 {
59069
59070  return $this->output->getFormatter()->format($this->application->getName().' > ');
59071 }
59072
59073 protected function getOutput()
59074 {
59075 return $this->output;
59076 }
59077
59078 protected function getApplication()
59079 {
59080 return $this->application;
59081 }
59082
59083
59084
59085
59086
59087
59088
59089
59090 private function autocompleter($text)
59091 {
59092 $info = readline_info();
59093 $text = substr($info['line_buffer'], 0, $info['end']);
59094
59095 if ($info['point'] !== $info['end']) {
59096 return true;
59097 }
59098
59099
59100  if (false === strpos($text, ' ') || !$text) {
59101 return array_keys($this->application->all());
59102 }
59103
59104
59105  try {
59106 $command = $this->application->find(substr($text, 0, strpos($text, ' ')));
59107 } catch (\Exception $e) {
59108 return true;
59109 }
59110
59111 $list = array('--help');
59112 foreach ($command->getDefinition()->getOptions() as $option) {
59113 $list[] = '--'.$option->getName();
59114 }
59115
59116 return $list;
59117 }
59118
59119
59120
59121
59122
59123
59124 private function readline()
59125 {
59126 if ($this->hasReadline) {
59127 $line = readline($this->getPrompt());
59128 } else {
59129 $this->output->write($this->getPrompt());
59130 $line = fgets(STDIN, 1024);
59131 $line = (false === $line || '' === $line) ? false : rtrim($line);
59132 }
59133
59134 return $line;
59135 }
59136
59137 public function getProcessIsolation()
59138 {
59139 return $this->processIsolation;
59140 }
59141
59142 public function setProcessIsolation($processIsolation)
59143 {
59144 $this->processIsolation = (bool) $processIsolation;
59145
59146 if ($this->processIsolation && !class_exists('Symfony\\Component\\Process\\Process')) {
59147 throw new RuntimeException('Unable to isolate processes as the Symfony Process Component is not installed.');
59148 }
59149 }
59150 }
59151 <?php
59152
59153
59154
59155
59156
59157
59158
59159
59160
59161
59162 namespace Symfony\Component\Console\Style;
59163
59164 use Symfony\Component\Console\Formatter\OutputFormatterInterface;
59165 use Symfony\Component\Console\Helper\ProgressBar;
59166 use Symfony\Component\Console\Output\OutputInterface;
59167
59168
59169
59170
59171
59172
59173 abstract class OutputStyle implements OutputInterface, StyleInterface
59174 {
59175 private $output;
59176
59177
59178
59179
59180 public function __construct(OutputInterface $output)
59181 {
59182 $this->output = $output;
59183 }
59184
59185
59186
59187
59188 public function newLine($count = 1)
59189 {
59190 $this->output->write(str_repeat(PHP_EOL, $count));
59191 }
59192
59193
59194
59195
59196
59197
59198 public function createProgressBar($max = 0)
59199 {
59200 return new ProgressBar($this->output, $max);
59201 }
59202
59203
59204
59205
59206 public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
59207 {
59208 $this->output->write($messages, $newline, $type);
59209 }
59210
59211
59212
59213
59214 public function writeln($messages, $type = self::OUTPUT_NORMAL)
59215 {
59216 $this->output->writeln($messages, $type);
59217 }
59218
59219
59220
59221
59222 public function setVerbosity($level)
59223 {
59224 $this->output->setVerbosity($level);
59225 }
59226
59227
59228
59229
59230 public function getVerbosity()
59231 {
59232 return $this->output->getVerbosity();
59233 }
59234
59235
59236
59237
59238 public function setDecorated($decorated)
59239 {
59240 $this->output->setDecorated($decorated);
59241 }
59242
59243
59244
59245
59246 public function isDecorated()
59247 {
59248 return $this->output->isDecorated();
59249 }
59250
59251
59252
59253
59254 public function setFormatter(OutputFormatterInterface $formatter)
59255 {
59256 $this->output->setFormatter($formatter);
59257 }
59258
59259
59260
59261
59262 public function getFormatter()
59263 {
59264 return $this->output->getFormatter();
59265 }
59266 }
59267 <?php
59268
59269
59270
59271
59272
59273
59274
59275
59276
59277
59278 namespace Symfony\Component\Console\Style;
59279
59280
59281
59282
59283
59284
59285 interface StyleInterface
59286 {
59287
59288
59289
59290
59291
59292 public function title($message);
59293
59294
59295
59296
59297
59298
59299 public function section($message);
59300
59301
59302
59303
59304
59305
59306 public function listing(array $elements);
59307
59308
59309
59310
59311
59312
59313 public function text($message);
59314
59315
59316
59317
59318
59319
59320 public function success($message);
59321
59322
59323
59324
59325
59326
59327 public function error($message);
59328
59329
59330
59331
59332
59333
59334 public function warning($message);
59335
59336
59337
59338
59339
59340
59341 public function note($message);
59342
59343
59344
59345
59346
59347
59348 public function caution($message);
59349
59350
59351
59352
59353
59354
59355
59356 public function table(array $headers, array $rows);
59357
59358
59359
59360
59361
59362
59363
59364
59365
59366
59367 public function ask($question, $default = null, $validator = null);
59368
59369
59370
59371
59372
59373
59374
59375
59376
59377 public function askHidden($question, $validator = null);
59378
59379
59380
59381
59382
59383
59384
59385
59386
59387 public function confirm($question, $default = true);
59388
59389
59390
59391
59392
59393
59394
59395
59396
59397
59398 public function choice($question, array $choices, $default = null);
59399
59400
59401
59402
59403
59404
59405 public function newLine($count = 1);
59406
59407
59408
59409
59410
59411
59412 public function progressStart($max = 0);
59413
59414
59415
59416
59417
59418
59419 public function progressAdvance($step = 1);
59420
59421
59422
59423
59424 public function progressFinish();
59425 }
59426 <?php
59427
59428
59429
59430
59431
59432
59433
59434
59435
59436
59437 namespace Symfony\Component\Console\Style;
59438
59439 use Symfony\Component\Console\Application;
59440 use Symfony\Component\Console\Exception\RuntimeException;
59441 use Symfony\Component\Console\Formatter\OutputFormatter;
59442 use Symfony\Component\Console\Helper\Helper;
59443 use Symfony\Component\Console\Helper\ProgressBar;
59444 use Symfony\Component\Console\Helper\SymfonyQuestionHelper;
59445 use Symfony\Component\Console\Helper\Table;
59446 use Symfony\Component\Console\Input\InputInterface;
59447 use Symfony\Component\Console\Output\BufferedOutput;
59448 use Symfony\Component\Console\Output\OutputInterface;
59449 use Symfony\Component\Console\Question\ChoiceQuestion;
59450 use Symfony\Component\Console\Question\ConfirmationQuestion;
59451 use Symfony\Component\Console\Question\Question;
59452
59453
59454
59455
59456
59457
59458 class SymfonyStyle extends OutputStyle
59459 {
59460 const MAX_LINE_LENGTH = 120;
59461
59462 private $input;
59463 private $questionHelper;
59464 private $progressBar;
59465 private $lineLength;
59466 private $bufferedOutput;
59467
59468
59469
59470
59471
59472 public function __construct(InputInterface $input, OutputInterface $output)
59473 {
59474 $this->input = $input;
59475 $this->bufferedOutput = new BufferedOutput($output->getVerbosity(), false, clone $output->getFormatter());
59476
59477  $this->lineLength = min($this->getTerminalWidth() - (int) (DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);
59478
59479 parent::__construct($output);
59480 }
59481
59482
59483
59484
59485
59486
59487
59488
59489
59490
59491 public function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false)
59492 {
59493 $messages = is_array($messages) ? array_values($messages) : array($messages);
59494
59495 $this->autoPrependBlock();
59496 $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, true));
59497 $this->newLine();
59498 }
59499
59500
59501
59502
59503 public function title($message)
59504 {
59505 $this->autoPrependBlock();
59506 $this->writeln(array(
59507 sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
59508 sprintf('<comment>%s</>', str_repeat('=', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
59509 ));
59510 $this->newLine();
59511 }
59512
59513
59514
59515
59516 public function section($message)
59517 {
59518 $this->autoPrependBlock();
59519 $this->writeln(array(
59520 sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
59521 sprintf('<comment>%s</>', str_repeat('-', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
59522 ));
59523 $this->newLine();
59524 }
59525
59526
59527
59528
59529 public function listing(array $elements)
59530 {
59531 $this->autoPrependText();
59532 $elements = array_map(function ($element) {
59533 return sprintf(' * %s', $element);
59534 }, $elements);
59535
59536 $this->writeln($elements);
59537 $this->newLine();
59538 }
59539
59540
59541
59542
59543 public function text($message)
59544 {
59545 $this->autoPrependText();
59546
59547 $messages = is_array($message) ? array_values($message) : array($message);
59548 foreach ($messages as $message) {
59549 $this->writeln(sprintf(' %s', $message));
59550 }
59551 }
59552
59553
59554
59555
59556
59557
59558 public function comment($message)
59559 {
59560 $messages = is_array($message) ? array_values($message) : array($message);
59561
59562 $this->autoPrependBlock();
59563 $this->writeln($this->createBlock($messages, null, null, '<fg=default;bg=default> // </>'));
59564 $this->newLine();
59565 }
59566
59567
59568
59569
59570 public function success($message)
59571 {
59572 $this->block($message, 'OK', 'fg=black;bg=green', ' ', true);
59573 }
59574
59575
59576
59577
59578 public function error($message)
59579 {
59580 $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', true);
59581 }
59582
59583
59584
59585
59586 public function warning($message)
59587 {
59588 $this->block($message, 'WARNING', 'fg=white;bg=red', ' ', true);
59589 }
59590
59591
59592
59593
59594 public function note($message)
59595 {
59596 $this->block($message, 'NOTE', 'fg=yellow', ' ! ');
59597 }
59598
59599
59600
59601
59602 public function caution($message)
59603 {
59604 $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', true);
59605 }
59606
59607
59608
59609
59610 public function table(array $headers, array $rows)
59611 {
59612 $style = clone Table::getStyleDefinition('symfony-style-guide');
59613 $style->setCellHeaderFormat('<info>%s</info>');
59614
59615 $table = new Table($this);
59616 $table->setHeaders($headers);
59617 $table->setRows($rows);
59618 $table->setStyle($style);
59619
59620 $table->render();
59621 $this->newLine();
59622 }
59623
59624
59625
59626
59627 public function ask($question, $default = null, $validator = null)
59628 {
59629 $question = new Question($question, $default);
59630 $question->setValidator($validator);
59631
59632 return $this->askQuestion($question);
59633 }
59634
59635
59636
59637
59638 public function askHidden($question, $validator = null)
59639 {
59640 $question = new Question($question);
59641
59642 $question->setHidden(true);
59643 $question->setValidator($validator);
59644
59645 return $this->askQuestion($question);
59646 }
59647
59648
59649
59650
59651 public function confirm($question, $default = true)
59652 {
59653 return $this->askQuestion(new ConfirmationQuestion($question, $default));
59654 }
59655
59656
59657
59658
59659 public function choice($question, array $choices, $default = null)
59660 {
59661 if (null !== $default) {
59662 $values = array_flip($choices);
59663 $default = $values[$default];
59664 }
59665
59666 return $this->askQuestion(new ChoiceQuestion($question, $choices, $default));
59667 }
59668
59669
59670
59671
59672 public function progressStart($max = 0)
59673 {
59674 $this->progressBar = $this->createProgressBar($max);
59675 $this->progressBar->start();
59676 }
59677
59678
59679
59680
59681 public function progressAdvance($step = 1)
59682 {
59683 $this->getProgressBar()->advance($step);
59684 }
59685
59686
59687
59688
59689 public function progressFinish()
59690 {
59691 $this->getProgressBar()->finish();
59692 $this->newLine(2);
59693 $this->progressBar = null;
59694 }
59695
59696
59697
59698
59699 public function createProgressBar($max = 0)
59700 {
59701 $progressBar = parent::createProgressBar($max);
59702
59703 if ('\\' !== DIRECTORY_SEPARATOR) {
59704 $progressBar->setEmptyBarCharacter('░'); 
59705  $progressBar->setProgressCharacter('');
59706 $progressBar->setBarCharacter('▓'); 
59707  }
59708
59709 return $progressBar;
59710 }
59711
59712
59713
59714
59715
59716
59717 public function askQuestion(Question $question)
59718 {
59719 if ($this->input->isInteractive()) {
59720 $this->autoPrependBlock();
59721 }
59722
59723 if (!$this->questionHelper) {
59724 $this->questionHelper = new SymfonyQuestionHelper();
59725 }
59726
59727 $answer = $this->questionHelper->ask($this->input, $this, $question);
59728
59729 if ($this->input->isInteractive()) {
59730 $this->newLine();
59731 $this->bufferedOutput->write("\n");
59732 }
59733
59734 return $answer;
59735 }
59736
59737
59738
59739
59740 public function writeln($messages, $type = self::OUTPUT_NORMAL)
59741 {
59742 parent::writeln($messages, $type);
59743 $this->bufferedOutput->writeln($this->reduceBuffer($messages), $type);
59744 }
59745
59746
59747
59748
59749 public function write($messages, $newline = false, $type = self::OUTPUT_NORMAL)
59750 {
59751 parent::write($messages, $newline, $type);
59752 $this->bufferedOutput->write($this->reduceBuffer($messages), $newline, $type);
59753 }
59754
59755
59756
59757
59758 public function newLine($count = 1)
59759 {
59760 parent::newLine($count);
59761 $this->bufferedOutput->write(str_repeat("\n", $count));
59762 }
59763
59764
59765
59766
59767 private function getProgressBar()
59768 {
59769 if (!$this->progressBar) {
59770 throw new RuntimeException('The ProgressBar is not started.');
59771 }
59772
59773 return $this->progressBar;
59774 }
59775
59776 private function getTerminalWidth()
59777 {
59778 $application = new Application();
59779 $dimensions = $application->getTerminalDimensions();
59780
59781 return $dimensions[0] ?: self::MAX_LINE_LENGTH;
59782 }
59783
59784 private function autoPrependBlock()
59785 {
59786 $chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);
59787
59788 if (!isset($chars[0])) {
59789 return $this->newLine(); 
59790  }
59791
59792  $this->newLine(2 - substr_count($chars, "\n"));
59793 }
59794
59795 private function autoPrependText()
59796 {
59797 $fetched = $this->bufferedOutput->fetch();
59798
59799  if ("\n" !== substr($fetched, -1)) {
59800 $this->newLine();
59801 }
59802 }
59803
59804 private function reduceBuffer($messages)
59805 {
59806
59807  
59808  return array_map(function ($value) {
59809 return substr($value, -4);
59810 }, array_merge(array($this->bufferedOutput->fetch()), (array) $messages));
59811 }
59812
59813 private function createBlock($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = false)
59814 {
59815 $indentLength = 0;
59816 $prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(), $prefix);
59817 $lines = array();
59818
59819 if (null !== $type) {
59820 $type = sprintf('[%s] ', $type);
59821 $indentLength = strlen($type);
59822 $lineIndentation = str_repeat(' ', $indentLength);
59823 }
59824
59825
59826  foreach ($messages as $key => $message) {
59827 if ($escape) {
59828 $message = OutputFormatter::escape($message);
59829 }
59830
59831 $lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL, true)));
59832
59833 if (count($messages) > 1 && $key < count($messages) - 1) {
59834 $lines[] = '';
59835 }
59836 }
59837
59838 $firstLineIndex = 0;
59839 if ($padding && $this->isDecorated()) {
59840 $firstLineIndex = 1;
59841 array_unshift($lines, '');
59842 $lines[] = '';
59843 }
59844
59845 foreach ($lines as $i => &$line) {
59846 if (null !== $type) {
59847 $line = $firstLineIndex === $i ? $type.$line : $lineIndentation.$line;
59848 }
59849
59850 $line = $prefix.$line;
59851 $line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line));
59852
59853 if ($style) {
59854 $line = sprintf('<%s>%s</>', $style, $line);
59855 }
59856 }
59857
59858 return $lines;
59859 }
59860 }
59861 <?php
59862
59863
59864
59865
59866
59867
59868
59869
59870
59871
59872 namespace Symfony\Component\Console\Tester;
59873
59874 use Symfony\Component\Console\Application;
59875 use Symfony\Component\Console\Input\ArrayInput;
59876 use Symfony\Component\Console\Input\InputInterface;
59877 use Symfony\Component\Console\Output\OutputInterface;
59878 use Symfony\Component\Console\Output\StreamOutput;
59879
59880
59881
59882
59883
59884
59885
59886
59887
59888
59889
59890 class ApplicationTester
59891 {
59892 private $application;
59893 private $input;
59894 private $output;
59895 private $statusCode;
59896
59897
59898
59899
59900
59901
59902 public function __construct(Application $application)
59903 {
59904 $this->application = $application;
59905 }
59906
59907
59908
59909
59910
59911
59912
59913
59914
59915
59916
59917
59918
59919
59920
59921 public function run(array $input, $options = array())
59922 {
59923 $this->input = new ArrayInput($input);
59924 if (isset($options['interactive'])) {
59925 $this->input->setInteractive($options['interactive']);
59926 }
59927
59928 $this->output = new StreamOutput(fopen('php://memory', 'w', false));
59929 if (isset($options['decorated'])) {
59930 $this->output->setDecorated($options['decorated']);
59931 }
59932 if (isset($options['verbosity'])) {
59933 $this->output->setVerbosity($options['verbosity']);
59934 }
59935
59936 return $this->statusCode = $this->application->run($this->input, $this->output);
59937 }
59938
59939
59940
59941
59942
59943
59944
59945
59946 public function getDisplay($normalize = false)
59947 {
59948 rewind($this->output->getStream());
59949
59950 $display = stream_get_contents($this->output->getStream());
59951
59952 if ($normalize) {
59953 $display = str_replace(PHP_EOL, "\n", $display);
59954 }
59955
59956 return $display;
59957 }
59958
59959
59960
59961
59962
59963
59964 public function getInput()
59965 {
59966 return $this->input;
59967 }
59968
59969
59970
59971
59972
59973
59974 public function getOutput()
59975 {
59976 return $this->output;
59977 }
59978
59979
59980
59981
59982
59983
59984 public function getStatusCode()
59985 {
59986 return $this->statusCode;
59987 }
59988 }
59989 <?php
59990
59991
59992
59993
59994
59995
59996
59997
59998
59999
60000 namespace Symfony\Component\Console\Tester;
60001
60002 use Symfony\Component\Console\Command\Command;
60003 use Symfony\Component\Console\Input\ArrayInput;
60004 use Symfony\Component\Console\Output\StreamOutput;
60005 use Symfony\Component\Console\Input\InputInterface;
60006 use Symfony\Component\Console\Output\OutputInterface;
60007
60008
60009
60010
60011
60012
60013 class CommandTester
60014 {
60015 private $command;
60016 private $input;
60017 private $output;
60018 private $statusCode;
60019
60020
60021
60022
60023
60024
60025 public function __construct(Command $command)
60026 {
60027 $this->command = $command;
60028 }
60029
60030
60031
60032
60033
60034
60035
60036
60037
60038
60039
60040
60041
60042
60043
60044 public function execute(array $input, array $options = array())
60045 {
60046
60047  
60048  if (!isset($input['command'])
60049 && (null !== $application = $this->command->getApplication())
60050 && $application->getDefinition()->hasArgument('command')
60051 ) {
60052 $input = array_merge(array('command' => $this->command->getName()), $input);
60053 }
60054
60055 $this->input = new ArrayInput($input);
60056 if (isset($options['interactive'])) {
60057 $this->input->setInteractive($options['interactive']);
60058 }
60059
60060 $this->output = new StreamOutput(fopen('php://memory', 'w', false));
60061 $this->output->setDecorated(isset($options['decorated']) ? $options['decorated'] : false);
60062 if (isset($options['verbosity'])) {
60063 $this->output->setVerbosity($options['verbosity']);
60064 }
60065
60066 return $this->statusCode = $this->command->run($this->input, $this->output);
60067 }
60068
60069
60070
60071
60072
60073
60074
60075
60076 public function getDisplay($normalize = false)
60077 {
60078 rewind($this->output->getStream());
60079
60080 $display = stream_get_contents($this->output->getStream());
60081
60082 if ($normalize) {
60083 $display = str_replace(PHP_EOL, "\n", $display);
60084 }
60085
60086 return $display;
60087 }
60088
60089
60090
60091
60092
60093
60094 public function getInput()
60095 {
60096 return $this->input;
60097 }
60098
60099
60100
60101
60102
60103
60104 public function getOutput()
60105 {
60106 return $this->output;
60107 }
60108
60109
60110
60111
60112
60113
60114 public function getStatusCode()
60115 {
60116 return $this->statusCode;
60117 }
60118 }
60119 <?php
60120
60121
60122
60123
60124
60125
60126
60127
60128
60129
60130 namespace Symfony\Component\Debug;
60131
60132 use Psr\Log\AbstractLogger;
60133
60134
60135
60136
60137
60138
60139 class BufferingLogger extends AbstractLogger
60140 {
60141 private $logs = array();
60142
60143 public function log($level, $message, array $context = array())
60144 {
60145 $this->logs[] = array($level, $message, $context);
60146 }
60147
60148 public function cleanLogs()
60149 {
60150 $logs = $this->logs;
60151 $this->logs = array();
60152
60153 return $logs;
60154 }
60155 }
60156 <?php
60157
60158
60159
60160
60161
60162
60163
60164
60165
60166
60167 namespace Symfony\Component\Debug;
60168
60169
60170
60171
60172
60173
60174 class Debug
60175 {
60176 private static $enabled = false;
60177
60178
60179
60180
60181
60182
60183
60184
60185
60186
60187
60188
60189 public static function enable($errorReportingLevel = null, $displayErrors = true)
60190 {
60191 if (static::$enabled) {
60192 return;
60193 }
60194
60195 static::$enabled = true;
60196
60197 if (null !== $errorReportingLevel) {
60198 error_reporting($errorReportingLevel);
60199 } else {
60200 error_reporting(-1);
60201 }
60202
60203 if ('cli' !== PHP_SAPI) {
60204 ini_set('display_errors', 0);
60205 ExceptionHandler::register();
60206 } elseif ($displayErrors && (!ini_get('log_errors') || ini_get('error_log'))) {
60207
60208  ini_set('display_errors', 1);
60209 }
60210 if ($displayErrors) {
60211 ErrorHandler::register(new ErrorHandler(new BufferingLogger()));
60212 } else {
60213 ErrorHandler::register()->throwAt(0, true);
60214 }
60215
60216 DebugClassLoader::enable();
60217 }
60218 }
60219 <?php
60220
60221
60222
60223
60224
60225
60226
60227
60228
60229
60230 namespace Symfony\Component\Debug;
60231
60232
60233
60234
60235
60236
60237
60238
60239
60240
60241
60242
60243 class DebugClassLoader
60244 {
60245 private $classLoader;
60246 private $isFinder;
60247 private $wasFinder;
60248 private static $caseCheck;
60249 private static $deprecated = array();
60250 private static $php7Reserved = array('int', 'float', 'bool', 'string', 'true', 'false', 'null');
60251 private static $darwinCache = array('/' => array('/', array()));
60252
60253
60254
60255
60256
60257
60258 public function __construct($classLoader)
60259 {
60260 $this->wasFinder = is_object($classLoader) && method_exists($classLoader, 'findFile');
60261
60262 if ($this->wasFinder) {
60263 @trigger_error('The '.__METHOD__.' method will no longer support receiving an object into its $classLoader argument in 3.0.', E_USER_DEPRECATED);
60264 $this->classLoader = array($classLoader, 'loadClass');
60265 $this->isFinder = true;
60266 } else {
60267 $this->classLoader = $classLoader;
60268 $this->isFinder = is_array($classLoader) && method_exists($classLoader[0], 'findFile');
60269 }
60270
60271 if (!isset(self::$caseCheck)) {
60272 $file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), DIRECTORY_SEPARATOR);
60273 $i = strrpos($file, DIRECTORY_SEPARATOR);
60274 $dir = substr($file, 0, 1 + $i);
60275 $file = substr($file, 1 + $i);
60276 $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file);
60277 $test = realpath($dir.$test);
60278
60279 if (false === $test || false === $i) {
60280
60281  self::$caseCheck = 0;
60282 } elseif (substr($test, -strlen($file)) === $file) {
60283
60284  self::$caseCheck = 1;
60285 } elseif (false !== stripos(PHP_OS, 'darwin')) {
60286
60287  self::$caseCheck = 2;
60288 } else {
60289
60290  self::$caseCheck = 0;
60291 }
60292 }
60293 }
60294
60295
60296
60297
60298
60299
60300 public function getClassLoader()
60301 {
60302 return $this->wasFinder ? $this->classLoader[0] : $this->classLoader;
60303 }
60304
60305
60306
60307
60308 public static function enable()
60309 {
60310
60311  class_exists('Symfony\Component\Debug\ErrorHandler');
60312 class_exists('Psr\Log\LogLevel');
60313
60314 if (!is_array($functions = spl_autoload_functions())) {
60315 return;
60316 }
60317
60318 foreach ($functions as $function) {
60319 spl_autoload_unregister($function);
60320 }
60321
60322 foreach ($functions as $function) {
60323 if (!is_array($function) || !$function[0] instanceof self) {
60324 $function = array(new static($function), 'loadClass');
60325 }
60326
60327 spl_autoload_register($function);
60328 }
60329 }
60330
60331
60332
60333
60334 public static function disable()
60335 {
60336 if (!is_array($functions = spl_autoload_functions())) {
60337 return;
60338 }
60339
60340 foreach ($functions as $function) {
60341 spl_autoload_unregister($function);
60342 }
60343
60344 foreach ($functions as $function) {
60345 if (is_array($function) && $function[0] instanceof self) {
60346 $function = $function[0]->getClassLoader();
60347 }
60348
60349 spl_autoload_register($function);
60350 }
60351 }
60352
60353
60354
60355
60356
60357
60358
60359
60360
60361
60362 public function findFile($class)
60363 {
60364 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
60365
60366 if ($this->wasFinder) {
60367 return $this->classLoader[0]->findFile($class);
60368 }
60369 }
60370
60371
60372
60373
60374
60375
60376
60377
60378
60379
60380 public function loadClass($class)
60381 {
60382 ErrorHandler::stackErrors();
60383
60384 try {
60385 if ($this->isFinder) {
60386 if ($file = $this->classLoader[0]->findFile($class)) {
60387 require_once $file;
60388 }
60389 } else {
60390 call_user_func($this->classLoader, $class);
60391 $file = false;
60392 }
60393 } catch (\Exception $e) {
60394 ErrorHandler::unstackErrors();
60395
60396 throw $e;
60397 } catch (\Throwable $e) {
60398 ErrorHandler::unstackErrors();
60399
60400 throw $e;
60401 }
60402
60403 ErrorHandler::unstackErrors();
60404
60405 $exists = class_exists($class, false) || interface_exists($class, false) || (function_exists('trait_exists') && trait_exists($class, false));
60406
60407 if ($class && '\\' === $class[0]) {
60408 $class = substr($class, 1);
60409 }
60410
60411 if ($exists) {
60412 $refl = new \ReflectionClass($class);
60413 $name = $refl->getName();
60414
60415 if ($name !== $class && 0 === strcasecmp($name, $class)) {
60416 throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: %s vs %s', $class, $name));
60417 }
60418
60419 if (in_array(strtolower($refl->getShortName()), self::$php7Reserved)) {
60420 @trigger_error(sprintf('%s uses a reserved class name (%s) that will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED);
60421 } elseif (preg_match('#\n \* @deprecated (.*?)\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) {
60422 self::$deprecated[$name] = preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]);
60423 } else {
60424 if (2 > $len = 1 + (strpos($name, '\\', 1 + strpos($name, '\\')) ?: strpos($name, '_'))) {
60425 $len = 0;
60426 $ns = '';
60427 } else {
60428 switch ($ns = substr($name, 0, $len)) {
60429 case 'Symfony\Bridge\\':
60430 case 'Symfony\Bundle\\':
60431 case 'Symfony\Component\\':
60432 $ns = 'Symfony\\';
60433 $len = strlen($ns);
60434 break;
60435 }
60436 }
60437 $parent = get_parent_class($class);
60438
60439 if (!$parent || strncmp($ns, $parent, $len)) {
60440 if ($parent && isset(self::$deprecated[$parent]) && strncmp($ns, $parent, $len)) {
60441 @trigger_error(sprintf('The %s class extends %s that is deprecated %s', $name, $parent, self::$deprecated[$parent]), E_USER_DEPRECATED);
60442 }
60443
60444 $parentInterfaces = array();
60445 $deprecatedInterfaces = array();
60446 if ($parent) {
60447 foreach (class_implements($parent) as $interface) {
60448 $parentInterfaces[$interface] = 1;
60449 }
60450 }
60451
60452 foreach ($refl->getInterfaceNames() as $interface) {
60453 if (isset(self::$deprecated[$interface]) && strncmp($ns, $interface, $len)) {
60454 $deprecatedInterfaces[] = $interface;
60455 }
60456 foreach (class_implements($interface) as $interface) {
60457 $parentInterfaces[$interface] = 1;
60458 }
60459 }
60460
60461 foreach ($deprecatedInterfaces as $interface) {
60462 if (!isset($parentInterfaces[$interface])) {
60463 @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);
60464 }
60465 }
60466 }
60467 }
60468 }
60469
60470 if ($file) {
60471 if (!$exists) {
60472 if (false !== strpos($class, '/')) {
60473 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));
60474 }
60475
60476 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));
60477 }
60478 if (self::$caseCheck) {
60479 $real = explode('\\', $class.strrchr($file, '.'));
60480 $tail = explode(DIRECTORY_SEPARATOR, str_replace('/', DIRECTORY_SEPARATOR, $file));
60481
60482 $i = count($tail) - 1;
60483 $j = count($real) - 1;
60484
60485 while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) {
60486 --$i;
60487 --$j;
60488 }
60489
60490 array_splice($tail, 0, $i + 1);
60491 }
60492 if (self::$caseCheck && $tail) {
60493 $tail = DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $tail);
60494 $tailLen = strlen($tail);
60495 $real = $refl->getFileName();
60496
60497 if (2 === self::$caseCheck) {
60498
60499
60500 $i = 1 + strrpos($real, '/');
60501 $file = substr($real, $i);
60502 $real = substr($real, 0, $i);
60503
60504 if (isset(self::$darwinCache[$real])) {
60505 $kDir = $real;
60506 } else {
60507 $kDir = strtolower($real);
60508
60509 if (isset(self::$darwinCache[$kDir])) {
60510 $real = self::$darwinCache[$kDir][0];
60511 } else {
60512 $dir = getcwd();
60513 chdir($real);
60514 $real = getcwd().'/';
60515 chdir($dir);
60516
60517 $dir = $real;
60518 $k = $kDir;
60519 $i = strlen($dir) - 1;
60520 while (!isset(self::$darwinCache[$k])) {
60521 self::$darwinCache[$k] = array($dir, array());
60522 self::$darwinCache[$dir] = &self::$darwinCache[$k];
60523
60524 while ('/' !== $dir[--$i]) {
60525 }
60526 $k = substr($k, 0, ++$i);
60527 $dir = substr($dir, 0, $i--);
60528 }
60529 }
60530 }
60531
60532 $dirFiles = self::$darwinCache[$kDir][1];
60533
60534 if (isset($dirFiles[$file])) {
60535 $kFile = $file;
60536 } else {
60537 $kFile = strtolower($file);
60538
60539 if (!isset($dirFiles[$kFile])) {
60540 foreach (scandir($real, 2) as $f) {
60541 if ('.' !== $f[0]) {
60542 $dirFiles[$f] = $f;
60543 if ($f === $file) {
60544 $kFile = $k = $file;
60545 } elseif ($f !== $k = strtolower($f)) {
60546 $dirFiles[$k] = $f;
60547 }
60548 }
60549 }
60550 self::$darwinCache[$kDir][1] = $dirFiles;
60551 }
60552 }
60553
60554 $real .= $dirFiles[$kFile];
60555 }
60556
60557 if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true)
60558 && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false)
60559 ) {
60560 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)));
60561 }
60562 }
60563
60564 return true;
60565 }
60566 }
60567 }
60568 <?php
60569
60570
60571
60572
60573
60574
60575
60576
60577
60578
60579 namespace Symfony\Component\Debug;
60580
60581 use Psr\Log\LogLevel;
60582 use Psr\Log\LoggerInterface;
60583 use Symfony\Component\Debug\Exception\ContextErrorException;
60584 use Symfony\Component\Debug\Exception\FatalErrorException;
60585 use Symfony\Component\Debug\Exception\FatalThrowableError;
60586 use Symfony\Component\Debug\Exception\OutOfMemoryException;
60587 use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler;
60588 use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler;
60589 use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler;
60590 use Symfony\Component\Debug\FatalErrorHandler\FatalErrorHandlerInterface;
60591
60592
60593
60594
60595
60596
60597
60598
60599
60600
60601
60602
60603
60604
60605
60606
60607
60608
60609
60610
60611
60612
60613
60614 class ErrorHandler
60615 {
60616
60617
60618
60619 const TYPE_DEPRECATION = -100;
60620
60621 private $levels = array(
60622 E_DEPRECATED => 'Deprecated',
60623 E_USER_DEPRECATED => 'User Deprecated',
60624 E_NOTICE => 'Notice',
60625 E_USER_NOTICE => 'User Notice',
60626 E_STRICT => 'Runtime Notice',
60627 E_WARNING => 'Warning',
60628 E_USER_WARNING => 'User Warning',
60629 E_COMPILE_WARNING => 'Compile Warning',
60630 E_CORE_WARNING => 'Core Warning',
60631 E_USER_ERROR => 'User Error',
60632 E_RECOVERABLE_ERROR => 'Catchable Fatal Error',
60633 E_COMPILE_ERROR => 'Compile Error',
60634 E_PARSE => 'Parse Error',
60635 E_ERROR => 'Error',
60636 E_CORE_ERROR => 'Core Error',
60637 );
60638
60639 private $loggers = array(
60640 E_DEPRECATED => array(null, LogLevel::INFO),
60641 E_USER_DEPRECATED => array(null, LogLevel::INFO),
60642 E_NOTICE => array(null, LogLevel::WARNING),
60643 E_USER_NOTICE => array(null, LogLevel::WARNING),
60644 E_STRICT => array(null, LogLevel::WARNING),
60645 E_WARNING => array(null, LogLevel::WARNING),
60646 E_USER_WARNING => array(null, LogLevel::WARNING),
60647 E_COMPILE_WARNING => array(null, LogLevel::WARNING),
60648 E_CORE_WARNING => array(null, LogLevel::WARNING),
60649 E_USER_ERROR => array(null, LogLevel::CRITICAL),
60650 E_RECOVERABLE_ERROR => array(null, LogLevel::CRITICAL),
60651 E_COMPILE_ERROR => array(null, LogLevel::CRITICAL),
60652 E_PARSE => array(null, LogLevel::CRITICAL),
60653 E_ERROR => array(null, LogLevel::CRITICAL),
60654 E_CORE_ERROR => array(null, LogLevel::CRITICAL),
60655 );
60656
60657 private $thrownErrors = 0x1FFF; 
60658  private $scopedErrors = 0x1FFF; 
60659  private $tracedErrors = 0x77FB; 
60660  private $screamedErrors = 0x55; 
60661  private $loggedErrors = 0;
60662
60663 private $loggedTraces = array();
60664 private $isRecursive = 0;
60665 private $isRoot = false;
60666 private $exceptionHandler;
60667 private $bootstrappingLogger;
60668
60669 private static $reservedMemory;
60670 private static $stackedErrors = array();
60671 private static $stackedErrorLevels = array();
60672 private static $toStringException = null;
60673 private static $exitCode = 0;
60674
60675
60676
60677
60678
60679
60680 private $displayErrors = 0x1FFF;
60681
60682
60683
60684
60685
60686
60687
60688
60689
60690 public static function register($handler = null, $replace = true)
60691 {
60692 if (null === self::$reservedMemory) {
60693 self::$reservedMemory = str_repeat('x', 10240);
60694 register_shutdown_function(__CLASS__.'::handleFatalError');
60695 }
60696
60697 $levels = -1;
60698
60699 if ($handlerIsNew = !$handler instanceof self) {
60700
60701  if (null !== $handler) {
60702 $levels = $replace ? $handler : 0;
60703 $replace = true;
60704 }
60705 $handler = new static();
60706 }
60707
60708 if (null === $prev = set_error_handler(array($handler, 'handleError'))) {
60709 restore_error_handler();
60710
60711  set_error_handler(array($handler, 'handleError'), $handler->thrownErrors | $handler->loggedErrors);
60712 $handler->isRoot = true;
60713 }
60714
60715 if ($handlerIsNew && is_array($prev) && $prev[0] instanceof self) {
60716 $handler = $prev[0];
60717 $replace = false;
60718 }
60719 if ($replace || !$prev) {
60720 $handler->setExceptionHandler(set_exception_handler(array($handler, 'handleException')));
60721 } else {
60722 restore_error_handler();
60723 }
60724
60725 $handler->throwAt($levels & $handler->thrownErrors, true);
60726
60727 return $handler;
60728 }
60729
60730 public function __construct(BufferingLogger $bootstrappingLogger = null)
60731 {
60732 if ($bootstrappingLogger) {
60733 $this->bootstrappingLogger = $bootstrappingLogger;
60734 $this->setDefaultLogger($bootstrappingLogger);
60735 }
60736 }
60737
60738
60739
60740
60741
60742
60743
60744
60745 public function setDefaultLogger(LoggerInterface $logger, $levels = null, $replace = false)
60746 {
60747 $loggers = array();
60748
60749 if (is_array($levels)) {
60750 foreach ($levels as $type => $logLevel) {
60751 if (empty($this->loggers[$type][0]) || $replace || $this->loggers[$type][0] === $this->bootstrappingLogger) {
60752 $loggers[$type] = array($logger, $logLevel);
60753 }
60754 }
60755 } else {
60756 if (null === $levels) {
60757 $levels = E_ALL | E_STRICT;
60758 }
60759 foreach ($this->loggers as $type => $log) {
60760 if (($type & $levels) && (empty($log[0]) || $replace || $log[0] === $this->bootstrappingLogger)) {
60761 $log[0] = $logger;
60762 $loggers[$type] = $log;
60763 }
60764 }
60765 }
60766
60767 $this->setLoggers($loggers);
60768 }
60769
60770
60771
60772
60773
60774
60775
60776
60777
60778
60779 public function setLoggers(array $loggers)
60780 {
60781 $prevLogged = $this->loggedErrors;
60782 $prev = $this->loggers;
60783 $flush = array();
60784
60785 foreach ($loggers as $type => $log) {
60786 if (!isset($prev[$type])) {
60787 throw new \InvalidArgumentException('Unknown error type: '.$type);
60788 }
60789 if (!is_array($log)) {
60790 $log = array($log);
60791 } elseif (!array_key_exists(0, $log)) {
60792 throw new \InvalidArgumentException('No logger provided');
60793 }
60794 if (null === $log[0]) {
60795 $this->loggedErrors &= ~$type;
60796 } elseif ($log[0] instanceof LoggerInterface) {
60797 $this->loggedErrors |= $type;
60798 } else {
60799 throw new \InvalidArgumentException('Invalid logger provided');
60800 }
60801 $this->loggers[$type] = $log + $prev[$type];
60802
60803 if ($this->bootstrappingLogger && $prev[$type][0] === $this->bootstrappingLogger) {
60804 $flush[$type] = $type;
60805 }
60806 }
60807 $this->reRegister($prevLogged | $this->thrownErrors);
60808
60809 if ($flush) {
60810 foreach ($this->bootstrappingLogger->cleanLogs() as $log) {
60811 $type = $log[2]['type'];
60812 if (!isset($flush[$type])) {
60813 $this->bootstrappingLogger->log($log[0], $log[1], $log[2]);
60814 } elseif ($this->loggers[$type][0]) {
60815 $this->loggers[$type][0]->log($this->loggers[$type][1], $log[1], $log[2]);
60816 }
60817 }
60818 }
60819
60820 return $prev;
60821 }
60822
60823
60824
60825
60826
60827
60828
60829
60830
60831
60832 public function setExceptionHandler($handler)
60833 {
60834 if (null !== $handler && !is_callable($handler)) {
60835 throw new \LogicException('The exception handler must be a valid PHP callable.');
60836 }
60837 $prev = $this->exceptionHandler;
60838 $this->exceptionHandler = $handler;
60839
60840 return $prev;
60841 }
60842
60843
60844
60845
60846
60847
60848
60849
60850
60851 public function throwAt($levels, $replace = false)
60852 {
60853 $prev = $this->thrownErrors;
60854 $this->thrownErrors = ($levels | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED;
60855 if (!$replace) {
60856 $this->thrownErrors |= $prev;
60857 }
60858 $this->reRegister($prev | $this->loggedErrors);
60859
60860
60861  $this->displayErrors = $this->thrownErrors;
60862
60863 return $prev;
60864 }
60865
60866
60867
60868
60869
60870
60871
60872
60873
60874 public function scopeAt($levels, $replace = false)
60875 {
60876 $prev = $this->scopedErrors;
60877 $this->scopedErrors = (int) $levels;
60878 if (!$replace) {
60879 $this->scopedErrors |= $prev;
60880 }
60881
60882 return $prev;
60883 }
60884
60885
60886
60887
60888
60889
60890
60891
60892
60893 public function traceAt($levels, $replace = false)
60894 {
60895 $prev = $this->tracedErrors;
60896 $this->tracedErrors = (int) $levels;
60897 if (!$replace) {
60898 $this->tracedErrors |= $prev;
60899 }
60900
60901 return $prev;
60902 }
60903
60904
60905
60906
60907
60908
60909
60910
60911
60912 public function screamAt($levels, $replace = false)
60913 {
60914 $prev = $this->screamedErrors;
60915 $this->screamedErrors = (int) $levels;
60916 if (!$replace) {
60917 $this->screamedErrors |= $prev;
60918 }
60919
60920 return $prev;
60921 }
60922
60923
60924
60925
60926 private function reRegister($prev)
60927 {
60928 if ($prev !== $this->thrownErrors | $this->loggedErrors) {
60929 $handler = set_error_handler('var_dump');
60930 $handler = is_array($handler) ? $handler[0] : null;
60931 restore_error_handler();
60932 if ($handler === $this) {
60933 restore_error_handler();
60934 if ($this->isRoot) {
60935 set_error_handler(array($this, 'handleError'), $this->thrownErrors | $this->loggedErrors);
60936 } else {
60937 set_error_handler(array($this, 'handleError'));
60938 }
60939 }
60940 }
60941 }
60942
60943
60944
60945
60946
60947
60948
60949
60950
60951
60952
60953
60954
60955
60956
60957 public function handleError($type, $message, $file, $line)
60958 {
60959 $level = error_reporting() | E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED;
60960 $log = $this->loggedErrors & $type;
60961 $throw = $this->thrownErrors & $type & $level;
60962 $type &= $level | $this->screamedErrors;
60963
60964 if (!$type || (!$log && !$throw)) {
60965 return $type && $log;
60966 }
60967 $scope = $this->scopedErrors & $type;
60968
60969 if (4 < $numArgs = func_num_args()) {
60970 $context = $scope ? (func_get_arg(4) ?: array()) : array();
60971 $backtrace = 5 < $numArgs ? func_get_arg(5) : null; 
60972  } else {
60973 $context = array();
60974 $backtrace = null;
60975 }
60976
60977 if (isset($context['GLOBALS']) && $scope) {
60978 $e = $context; 
60979  unset($e['GLOBALS'], $context); 
60980  $context = $e;
60981 }
60982
60983 if (null !== $backtrace && $type & E_ERROR) {
60984
60985  
60986  
60987  $this->handleFatalError(compact('type', 'message', 'file', 'line', 'backtrace'));
60988
60989 return true;
60990 }
60991
60992 if ($throw) {
60993 if (null !== self::$toStringException) {
60994 $throw = self::$toStringException;
60995 self::$toStringException = null;
60996 } elseif ($scope && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) {
60997
60998  $throw = new ContextErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line, $context);
60999 } else {
61000 $throw = new \ErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line);
61001 }
61002
61003 if (\PHP_VERSION_ID <= 50407 && (\PHP_VERSION_ID >= 50400 || \PHP_VERSION_ID <= 50317)) {
61004
61005  
61006  
61007
61008 $throw->errorHandlerCanary = new ErrorHandlerCanary();
61009 }
61010
61011 if (E_USER_ERROR & $type) {
61012 $backtrace = $backtrace ?: $throw->getTrace();
61013
61014 for ($i = 1; isset($backtrace[$i]); ++$i) {
61015 if (isset($backtrace[$i]['function'], $backtrace[$i]['type'], $backtrace[$i - 1]['function'])
61016 && '__toString' === $backtrace[$i]['function']
61017 && '->' === $backtrace[$i]['type']
61018 && !isset($backtrace[$i - 1]['class'])
61019 && ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function'])
61020 ) {
61021
61022  
61023  
61024  
61025  
61026  
61027
61028 foreach ($context as $e) {
61029 if (($e instanceof \Exception || $e instanceof \Throwable) && $e->__toString() === $message) {
61030 if (1 === $i) {
61031
61032  $throw = $e;
61033 break;
61034 }
61035 self::$toStringException = $e;
61036
61037 return true;
61038 }
61039 }
61040
61041 if (1 < $i) {
61042
61043  $this->handleException($throw);
61044
61045
61046  return false;
61047 }
61048 }
61049 }
61050 }
61051
61052 throw $throw;
61053 }
61054
61055
61056  $e = md5("{$type}/{$line}/{$file}\x00{$message}", true);
61057 $trace = true;
61058
61059 if (!($this->tracedErrors & $type) || isset($this->loggedTraces[$e])) {
61060 $trace = false;
61061 } else {
61062 $this->loggedTraces[$e] = 1;
61063 }
61064
61065 $e = compact('type', 'file', 'line', 'level');
61066
61067 if ($type & $level) {
61068 if ($scope) {
61069 $e['scope_vars'] = $context;
61070 if ($trace) {
61071 $e['stack'] = $backtrace ?: debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT);
61072 }
61073 } elseif ($trace) {
61074 if (null === $backtrace) {
61075 $e['stack'] = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
61076 } else {
61077 foreach ($backtrace as &$frame) {
61078 unset($frame['args'], $frame);
61079 }
61080 $e['stack'] = $backtrace;
61081 }
61082 }
61083 }
61084
61085 if ($this->isRecursive) {
61086 $log = 0;
61087 } elseif (self::$stackedErrorLevels) {
61088 self::$stackedErrors[] = array($this->loggers[$type][0], ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, $message, $e);
61089 } else {
61090 try {
61091 $this->isRecursive = true;
61092 $this->loggers[$type][0]->log(($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, $message, $e);
61093 $this->isRecursive = false;
61094 } catch (\Exception $e) {
61095 $this->isRecursive = false;
61096
61097 throw $e;
61098 } catch (\Throwable $e) {
61099 $this->isRecursive = false;
61100
61101 throw $e;
61102 }
61103 }
61104
61105 return $type && $log;
61106 }
61107
61108
61109
61110
61111
61112
61113
61114
61115
61116 public function handleException($exception, array $error = null)
61117 {
61118 if (null === $error) {
61119 self::$exitCode = 255;
61120 }
61121 if (!$exception instanceof \Exception) {
61122 $exception = new FatalThrowableError($exception);
61123 }
61124 $type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR;
61125
61126 if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) {
61127 $e = array(
61128 'type' => $type,
61129 'file' => $exception->getFile(),
61130 'line' => $exception->getLine(),
61131 'level' => error_reporting(),
61132 'stack' => $exception->getTrace(),
61133 );
61134 if ($exception instanceof FatalErrorException) {
61135 if ($exception instanceof FatalThrowableError) {
61136 $error = array(
61137 'type' => $type,
61138 'message' => $message = $exception->getMessage(),
61139 'file' => $e['file'],
61140 'line' => $e['line'],
61141 );
61142 } else {
61143 $message = 'Fatal '.$exception->getMessage();
61144 }
61145 } elseif ($exception instanceof \ErrorException) {
61146 $message = 'Uncaught '.$exception->getMessage();
61147 if ($exception instanceof ContextErrorException) {
61148 $e['context'] = $exception->getContext();
61149 }
61150 } else {
61151 $message = 'Uncaught Exception: '.$exception->getMessage();
61152 }
61153 }
61154 if ($this->loggedErrors & $type) {
61155 try {
61156 $this->loggers[$type][0]->log($this->loggers[$type][1], $message, $e);
61157 } catch (\Exception $handlerException) {
61158 } catch (\Throwable $handlerException) {
61159 }
61160 }
61161 if ($exception instanceof FatalErrorException && !$exception instanceof OutOfMemoryException && $error) {
61162 foreach ($this->getFatalErrorHandlers() as $handler) {
61163 if ($e = $handler->handleError($error, $exception)) {
61164 $exception = $e;
61165 break;
61166 }
61167 }
61168 }
61169 if (empty($this->exceptionHandler)) {
61170 throw $exception; 
61171  }
61172 try {
61173 call_user_func($this->exceptionHandler, $exception);
61174 } catch (\Exception $handlerException) {
61175 } catch (\Throwable $handlerException) {
61176 }
61177 if (isset($handlerException)) {
61178 $this->exceptionHandler = null;
61179 $this->handleException($handlerException);
61180 }
61181 }
61182
61183
61184
61185
61186
61187
61188
61189
61190 public static function handleFatalError(array $error = null)
61191 {
61192 if (null === self::$reservedMemory) {
61193 return;
61194 }
61195
61196 self::$reservedMemory = null;
61197
61198 $handler = set_error_handler('var_dump');
61199 $handler = is_array($handler) ? $handler[0] : null;
61200 restore_error_handler();
61201
61202 if (!$handler instanceof self) {
61203 return;
61204 }
61205
61206 if ($exit = null === $error) {
61207 $error = error_get_last();
61208 }
61209
61210 try {
61211 while (self::$stackedErrorLevels) {
61212 static::unstackErrors();
61213 }
61214 } catch (\Exception $exception) {
61215
61216  } catch (\Throwable $exception) {
61217
61218  }
61219
61220 if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) {
61221
61222  $handler->throwAt(0, true);
61223 $trace = isset($error['backtrace']) ? $error['backtrace'] : null;
61224
61225 if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) {
61226 $exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false, $trace);
61227 } else {
61228 $exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true, $trace);
61229 }
61230 }
61231
61232 try {
61233 if (isset($exception)) {
61234 self::$exitCode = 255;
61235 $handler->handleException($exception, $error);
61236 }
61237 } catch (FatalErrorException $e) {
61238
61239  }
61240
61241 if ($exit && self::$exitCode) {
61242 $exitCode = self::$exitCode;
61243 register_shutdown_function('register_shutdown_function', function () use ($exitCode) { exit($exitCode); });
61244 }
61245 }
61246
61247
61248
61249
61250
61251
61252
61253
61254
61255
61256
61257
61258 public static function stackErrors()
61259 {
61260 self::$stackedErrorLevels[] = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
61261 }
61262
61263
61264
61265
61266 public static function unstackErrors()
61267 {
61268 $level = array_pop(self::$stackedErrorLevels);
61269
61270 if (null !== $level) {
61271 $e = error_reporting($level);
61272 if ($e !== ($level | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR)) {
61273
61274  error_reporting($e);
61275 }
61276 }
61277
61278 if (empty(self::$stackedErrorLevels)) {
61279 $errors = self::$stackedErrors;
61280 self::$stackedErrors = array();
61281
61282 foreach ($errors as $e) {
61283 $e[0]->log($e[1], $e[2], $e[3]);
61284 }
61285 }
61286 }
61287
61288
61289
61290
61291
61292
61293
61294
61295 protected function getFatalErrorHandlers()
61296 {
61297 return array(
61298 new UndefinedFunctionFatalErrorHandler(),
61299 new UndefinedMethodFatalErrorHandler(),
61300 new ClassNotFoundFatalErrorHandler(),
61301 );
61302 }
61303
61304
61305
61306
61307
61308
61309
61310
61311 public function setLevel($level)
61312 {
61313 @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);
61314
61315 $level = null === $level ? error_reporting() : $level;
61316 $this->throwAt($level, true);
61317 }
61318
61319
61320
61321
61322
61323
61324
61325
61326 public function setDisplayErrors($displayErrors)
61327 {
61328 @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);
61329
61330 if ($displayErrors) {
61331 $this->throwAt($this->displayErrors, true);
61332 } else {
61333 $displayErrors = $this->displayErrors;
61334 $this->throwAt(0, true);
61335 $this->displayErrors = $displayErrors;
61336 }
61337 }
61338
61339
61340
61341
61342
61343
61344
61345
61346
61347 public static function setLogger(LoggerInterface $logger, $channel = 'deprecation')
61348 {
61349 @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);
61350
61351 $handler = set_error_handler('var_dump');
61352 $handler = is_array($handler) ? $handler[0] : null;
61353 restore_error_handler();
61354 if (!$handler instanceof self) {
61355 return;
61356 }
61357 if ('deprecation' === $channel) {
61358 $handler->setDefaultLogger($logger, E_DEPRECATED | E_USER_DEPRECATED, true);
61359 $handler->screamAt(E_DEPRECATED | E_USER_DEPRECATED);
61360 } elseif ('scream' === $channel) {
61361 $handler->setDefaultLogger($logger, E_ALL | E_STRICT, false);
61362 $handler->screamAt(E_ALL | E_STRICT);
61363 } elseif ('emergency' === $channel) {
61364 $handler->setDefaultLogger($logger, E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR, true);
61365 $handler->screamAt(E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR);
61366 }
61367 }
61368
61369
61370
61371
61372 public function handle($level, $message, $file = 'unknown', $line = 0, $context = array())
61373 {
61374 $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());
61375
61376 return $this->handleError($level, $message, $file, $line, (array) $context);
61377 }
61378
61379
61380
61381
61382
61383
61384 public function handleFatal()
61385 {
61386 @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);
61387
61388 static::handleFatalError();
61389 }
61390 }
61391
61392
61393
61394
61395
61396
61397
61398
61399 class ErrorHandlerCanary
61400 {
61401 private static $displayErrors = null;
61402
61403 public function __construct()
61404 {
61405 if (null === self::$displayErrors) {
61406 self::$displayErrors = ini_set('display_errors', 1);
61407 }
61408 }
61409
61410 public function __destruct()
61411 {
61412 if (null !== self::$displayErrors) {
61413 ini_set('display_errors', self::$displayErrors);
61414 self::$displayErrors = null;
61415 }
61416 }
61417 }
61418 <?php
61419
61420
61421
61422
61423
61424
61425
61426
61427
61428
61429 namespace Symfony\Component\Debug\Exception;
61430
61431
61432
61433
61434
61435
61436 class ClassNotFoundException extends FatalErrorException
61437 {
61438 public function __construct($message, \ErrorException $previous)
61439 {
61440 parent::__construct(
61441 $message,
61442 $previous->getCode(),
61443 $previous->getSeverity(),
61444 $previous->getFile(),
61445 $previous->getLine(),
61446 $previous->getPrevious()
61447 );
61448 $this->setTrace($previous->getTrace());
61449 }
61450 }
61451 <?php
61452
61453
61454
61455
61456
61457
61458
61459
61460
61461
61462 namespace Symfony\Component\Debug\Exception;
61463
61464
61465
61466
61467
61468
61469 class ContextErrorException extends \ErrorException
61470 {
61471 private $context = array();
61472
61473 public function __construct($message, $code, $severity, $filename, $lineno, $context = array())
61474 {
61475 parent::__construct($message, $code, $severity, $filename, $lineno);
61476 $this->context = $context;
61477 }
61478
61479
61480
61481
61482 public function getContext()
61483 {
61484 return $this->context;
61485 }
61486 }
61487 <?php
61488
61489
61490
61491
61492
61493
61494
61495
61496
61497
61498 namespace Symfony\Component\Debug\Exception;
61499
61500 @trigger_error('The '.__NAMESPACE__.'\DummyException class is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
61501
61502
61503
61504
61505
61506
61507 class DummyException extends \ErrorException
61508 {
61509 }
61510 <?php
61511
61512
61513
61514
61515
61516
61517
61518
61519
61520
61521 namespace Symfony\Component\HttpKernel\Exception;
61522
61523
61524
61525
61526
61527
61528
61529
61530
61531
61532 class FatalErrorException extends \ErrorException
61533 {
61534 }
61535
61536 namespace Symfony\Component\Debug\Exception;
61537
61538 use Symfony\Component\HttpKernel\Exception\FatalErrorException as LegacyFatalErrorException;
61539
61540
61541
61542
61543
61544
61545 class FatalErrorException extends LegacyFatalErrorException
61546 {
61547 public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true, array $trace = null)
61548 {
61549 parent::__construct($message, $code, $severity, $filename, $lineno);
61550
61551 if (null !== $trace) {
61552 if (!$traceArgs) {
61553 foreach ($trace as &$frame) {
61554 unset($frame['args'], $frame['this'], $frame);
61555 }
61556 }
61557
61558 $this->setTrace($trace);
61559 } elseif (null !== $traceOffset) {
61560 if (function_exists('xdebug_get_function_stack')) {
61561 $trace = xdebug_get_function_stack();
61562 if (0 < $traceOffset) {
61563 array_splice($trace, -$traceOffset);
61564 }
61565
61566 foreach ($trace as &$frame) {
61567 if (!isset($frame['type'])) {
61568
61569  if (isset($frame['class'])) {
61570 $frame['type'] = '::';
61571 }
61572 } elseif ('dynamic' === $frame['type']) {
61573 $frame['type'] = '->';
61574 } elseif ('static' === $frame['type']) {
61575 $frame['type'] = '::';
61576 }
61577
61578
61579  if (!$traceArgs) {
61580 unset($frame['params'], $frame['args']);
61581 } elseif (isset($frame['params']) && !isset($frame['args'])) {
61582 $frame['args'] = $frame['params'];
61583 unset($frame['params']);
61584 }
61585 }
61586
61587 unset($frame);
61588 $trace = array_reverse($trace);
61589 } elseif (function_exists('symfony_debug_backtrace')) {
61590 $trace = symfony_debug_backtrace();
61591 if (0 < $traceOffset) {
61592 array_splice($trace, 0, $traceOffset);
61593 }
61594 } else {
61595 $trace = array();
61596 }
61597
61598 $this->setTrace($trace);
61599 }
61600 }
61601
61602 protected function setTrace($trace)
61603 {
61604 $traceReflector = new \ReflectionProperty('Exception', 'trace');
61605 $traceReflector->setAccessible(true);
61606 $traceReflector->setValue($this, $trace);
61607 }
61608 }
61609 <?php
61610
61611
61612
61613
61614
61615
61616
61617
61618
61619
61620 namespace Symfony\Component\Debug\Exception;
61621
61622
61623
61624
61625
61626
61627 class FatalThrowableError extends FatalErrorException
61628 {
61629 public function __construct(\Throwable $e)
61630 {
61631 if ($e instanceof \ParseError) {
61632 $message = 'Parse error: '.$e->getMessage();
61633 $severity = E_PARSE;
61634 } elseif ($e instanceof \TypeError) {
61635 $message = 'Type error: '.$e->getMessage();
61636 $severity = E_RECOVERABLE_ERROR;
61637 } else {
61638 $message = $e->getMessage();
61639 $severity = E_ERROR;
61640 }
61641
61642 \ErrorException::__construct(
61643 $message,
61644 $e->getCode(),
61645 $severity,
61646 $e->getFile(),
61647 $e->getLine()
61648 );
61649
61650 $this->setTrace($e->getTrace());
61651 }
61652 }
61653 <?php
61654
61655
61656
61657
61658
61659
61660
61661
61662
61663
61664 namespace Symfony\Component\HttpKernel\Exception;
61665
61666 use Symfony\Component\Debug\Exception\FlattenException as DebugFlattenException;
61667
61668
61669
61670
61671
61672
61673
61674
61675
61676
61677 class FlattenException
61678 {
61679 private $handler;
61680
61681 public static function __callStatic($method, $args)
61682 {
61683 if (!method_exists('Symfony\Component\Debug\Exception\FlattenException', $method)) {
61684 throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_called_class(), $method));
61685 }
61686
61687 return call_user_func_array(array('Symfony\Component\Debug\Exception\FlattenException', $method), $args);
61688 }
61689
61690 public function __call($method, $args)
61691 {
61692 if (!isset($this->handler)) {
61693 $this->handler = new DebugFlattenException();
61694 }
61695
61696 if (!method_exists($this->handler, $method)) {
61697 throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_class($this), $method));
61698 }
61699
61700 return call_user_func_array(array($this->handler, $method), $args);
61701 }
61702 }
61703
61704 namespace Symfony\Component\Debug\Exception;
61705
61706 use Symfony\Component\HttpKernel\Exception\FlattenException as LegacyFlattenException;
61707 use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
61708
61709
61710
61711
61712
61713
61714
61715
61716 class FlattenException extends LegacyFlattenException
61717 {
61718 private $message;
61719 private $code;
61720 private $previous;
61721 private $trace;
61722 private $class;
61723 private $statusCode;
61724 private $headers;
61725 private $file;
61726 private $line;
61727
61728 public static function create(\Exception $exception, $statusCode = null, array $headers = array())
61729 {
61730 $e = new static();
61731 $e->setMessage($exception->getMessage());
61732 $e->setCode($exception->getCode());
61733
61734 if ($exception instanceof HttpExceptionInterface) {
61735 $statusCode = $exception->getStatusCode();
61736 $headers = array_merge($headers, $exception->getHeaders());
61737 }
61738
61739 if (null === $statusCode) {
61740 $statusCode = 500;
61741 }
61742
61743 $e->setStatusCode($statusCode);
61744 $e->setHeaders($headers);
61745 $e->setTraceFromException($exception);
61746 $e->setClass(get_class($exception));
61747 $e->setFile($exception->getFile());
61748 $e->setLine($exception->getLine());
61749
61750 $previous = $exception->getPrevious();
61751
61752 if ($previous instanceof \Exception) {
61753 $e->setPrevious(static::create($previous));
61754 } elseif ($previous instanceof \Throwable) {
61755 $e->setPrevious(static::create(new FatalThrowableError($previous)));
61756 }
61757
61758 return $e;
61759 }
61760
61761 public function toArray()
61762 {
61763 $exceptions = array();
61764 foreach (array_merge(array($this), $this->getAllPrevious()) as $exception) {
61765 $exceptions[] = array(
61766 'message' => $exception->getMessage(),
61767 'class' => $exception->getClass(),
61768 'trace' => $exception->getTrace(),
61769 );
61770 }
61771
61772 return $exceptions;
61773 }
61774
61775 public function getStatusCode()
61776 {
61777 return $this->statusCode;
61778 }
61779
61780 public function setStatusCode($code)
61781 {
61782 $this->statusCode = $code;
61783 }
61784
61785 public function getHeaders()
61786 {
61787 return $this->headers;
61788 }
61789
61790 public function setHeaders(array $headers)
61791 {
61792 $this->headers = $headers;
61793 }
61794
61795 public function getClass()
61796 {
61797 return $this->class;
61798 }
61799
61800 public function setClass($class)
61801 {
61802 $this->class = $class;
61803 }
61804
61805 public function getFile()
61806 {
61807 return $this->file;
61808 }
61809
61810 public function setFile($file)
61811 {
61812 $this->file = $file;
61813 }
61814
61815 public function getLine()
61816 {
61817 return $this->line;
61818 }
61819
61820 public function setLine($line)
61821 {
61822 $this->line = $line;
61823 }
61824
61825 public function getMessage()
61826 {
61827 return $this->message;
61828 }
61829
61830 public function setMessage($message)
61831 {
61832 $this->message = $message;
61833 }
61834
61835 public function getCode()
61836 {
61837 return $this->code;
61838 }
61839
61840 public function setCode($code)
61841 {
61842 $this->code = $code;
61843 }
61844
61845 public function getPrevious()
61846 {
61847 return $this->previous;
61848 }
61849
61850 public function setPrevious(FlattenException $previous)
61851 {
61852 $this->previous = $previous;
61853 }
61854
61855 public function getAllPrevious()
61856 {
61857 $exceptions = array();
61858 $e = $this;
61859 while ($e = $e->getPrevious()) {
61860 $exceptions[] = $e;
61861 }
61862
61863 return $exceptions;
61864 }
61865
61866 public function getTrace()
61867 {
61868 return $this->trace;
61869 }
61870
61871 public function setTraceFromException(\Exception $exception)
61872 {
61873 $this->setTrace($exception->getTrace(), $exception->getFile(), $exception->getLine());
61874 }
61875
61876 public function setTrace($trace, $file, $line)
61877 {
61878 $this->trace = array();
61879 $this->trace[] = array(
61880 'namespace' => '',
61881 'short_class' => '',
61882 'class' => '',
61883 'type' => '',
61884 'function' => '',
61885 'file' => $file,
61886 'line' => $line,
61887 'args' => array(),
61888 );
61889 foreach ($trace as $entry) {
61890 $class = '';
61891 $namespace = '';
61892 if (isset($entry['class'])) {
61893 $parts = explode('\\', $entry['class']);
61894 $class = array_pop($parts);
61895 $namespace = implode('\\', $parts);
61896 }
61897
61898 $this->trace[] = array(
61899 'namespace' => $namespace,
61900 'short_class' => $class,
61901 'class' => isset($entry['class']) ? $entry['class'] : '',
61902 'type' => isset($entry['type']) ? $entry['type'] : '',
61903 'function' => isset($entry['function']) ? $entry['function'] : null,
61904 'file' => isset($entry['file']) ? $entry['file'] : null,
61905 'line' => isset($entry['line']) ? $entry['line'] : null,
61906 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : array(),
61907 );
61908 }
61909 }
61910
61911 private function flattenArgs($args, $level = 0, &$count = 0)
61912 {
61913 $result = array();
61914 foreach ($args as $key => $value) {
61915 if (++$count > 1e4) {
61916 return array('array', '*SKIPPED over 10000 entries*');
61917 }
61918 if ($value instanceof \__PHP_Incomplete_Class) {
61919
61920  $result[$key] = array('incomplete-object', $this->getClassNameFromIncomplete($value));
61921 } elseif (is_object($value)) {
61922 $result[$key] = array('object', get_class($value));
61923 } elseif (is_array($value)) {
61924 if ($level > 10) {
61925 $result[$key] = array('array', '*DEEP NESTED ARRAY*');
61926 } else {
61927 $result[$key] = array('array', $this->flattenArgs($value, $level + 1, $count));
61928 }
61929 } elseif (null === $value) {
61930 $result[$key] = array('null', null);
61931 } elseif (is_bool($value)) {
61932 $result[$key] = array('boolean', $value);
61933 } elseif (is_resource($value)) {
61934 $result[$key] = array('resource', get_resource_type($value));
61935 } else {
61936 $result[$key] = array('string', (string) $value);
61937 }
61938 }
61939
61940 return $result;
61941 }
61942
61943 private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value)
61944 {
61945 $array = new \ArrayObject($value);
61946
61947 return $array['__PHP_Incomplete_Class_Name'];
61948 }
61949 }
61950 <?php
61951
61952
61953
61954
61955
61956
61957
61958
61959
61960
61961 namespace Symfony\Component\Debug\Exception;
61962
61963
61964
61965
61966
61967
61968 class OutOfMemoryException extends FatalErrorException
61969 {
61970 }
61971 <?php
61972
61973
61974
61975
61976
61977
61978
61979
61980
61981
61982 namespace Symfony\Component\Debug\Exception;
61983
61984
61985
61986
61987
61988
61989 class UndefinedFunctionException extends FatalErrorException
61990 {
61991 public function __construct($message, \ErrorException $previous)
61992 {
61993 parent::__construct(
61994 $message,
61995 $previous->getCode(),
61996 $previous->getSeverity(),
61997 $previous->getFile(),
61998 $previous->getLine(),
61999 $previous->getPrevious()
62000 );
62001 $this->setTrace($previous->getTrace());
62002 }
62003 }
62004 <?php
62005
62006
62007
62008
62009
62010
62011
62012
62013
62014
62015 namespace Symfony\Component\Debug\Exception;
62016
62017
62018
62019
62020
62021
62022 class UndefinedMethodException extends FatalErrorException
62023 {
62024 public function __construct($message, \ErrorException $previous)
62025 {
62026 parent::__construct(
62027 $message,
62028 $previous->getCode(),
62029 $previous->getSeverity(),
62030 $previous->getFile(),
62031 $previous->getLine(),
62032 $previous->getPrevious()
62033 );
62034 $this->setTrace($previous->getTrace());
62035 }
62036 }
62037 <?php
62038
62039
62040
62041
62042
62043
62044
62045
62046
62047
62048 namespace Symfony\Component\Debug;
62049
62050 use Symfony\Component\HttpFoundation\Response;
62051 use Symfony\Component\Debug\Exception\FlattenException;
62052 use Symfony\Component\Debug\Exception\OutOfMemoryException;
62053
62054
62055
62056
62057
62058
62059
62060
62061
62062
62063
62064
62065
62066 class ExceptionHandler
62067 {
62068 private $debug;
62069 private $charset;
62070 private $handler;
62071 private $caughtBuffer;
62072 private $caughtLength;
62073 private $fileLinkFormat;
62074
62075 public function __construct($debug = true, $charset = null, $fileLinkFormat = null)
62076 {
62077 if (false !== strpos($charset, '%')) {
62078 @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);
62079
62080
62081  $pivot = $fileLinkFormat;
62082 $fileLinkFormat = $charset;
62083 $charset = $pivot;
62084 }
62085 $this->debug = $debug;
62086 $this->charset = $charset ?: ini_get('default_charset') ?: 'UTF-8';
62087 $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format');
62088 }
62089
62090
62091
62092
62093
62094
62095
62096
62097
62098
62099 public static function register($debug = true, $charset = null, $fileLinkFormat = null)
62100 {
62101 $handler = new static($debug, $charset, $fileLinkFormat);
62102
62103 $prev = set_exception_handler(array($handler, 'handle'));
62104 if (is_array($prev) && $prev[0] instanceof ErrorHandler) {
62105 restore_exception_handler();
62106 $prev[0]->setExceptionHandler(array($handler, 'handle'));
62107 }
62108
62109 return $handler;
62110 }
62111
62112
62113
62114
62115
62116
62117
62118
62119 public function setHandler($handler)
62120 {
62121 if (null !== $handler && !is_callable($handler)) {
62122 throw new \LogicException('The exception handler must be a valid PHP callable.');
62123 }
62124 $old = $this->handler;
62125 $this->handler = $handler;
62126
62127 return $old;
62128 }
62129
62130
62131
62132
62133
62134
62135
62136
62137 public function setFileLinkFormat($format)
62138 {
62139 $old = $this->fileLinkFormat;
62140 $this->fileLinkFormat = $format;
62141
62142 return $old;
62143 }
62144
62145
62146
62147
62148
62149
62150
62151
62152
62153 public function handle(\Exception $exception)
62154 {
62155 if (null === $this->handler || $exception instanceof OutOfMemoryException) {
62156 $this->failSafeHandle($exception);
62157
62158 return;
62159 }
62160
62161 $caughtLength = $this->caughtLength = 0;
62162
62163 ob_start(array($this, 'catchOutput'));
62164 $this->failSafeHandle($exception);
62165 while (null === $this->caughtBuffer && ob_end_flush()) {
62166
62167  }
62168 if (isset($this->caughtBuffer[0])) {
62169 ob_start(array($this, 'cleanOutput'));
62170 echo $this->caughtBuffer;
62171 $caughtLength = ob_get_length();
62172 }
62173 $this->caughtBuffer = null;
62174
62175 try {
62176 call_user_func($this->handler, $exception);
62177 $this->caughtLength = $caughtLength;
62178 } catch (\Exception $e) {
62179 if (!$caughtLength) {
62180
62181  throw $exception;
62182 }
62183 }
62184 }
62185
62186
62187
62188
62189
62190
62191
62192
62193
62194
62195 private function failSafeHandle(\Exception $exception)
62196 {
62197 if (class_exists('Symfony\Component\HttpFoundation\Response', false)
62198 && __CLASS__ !== get_class($this)
62199 && ($reflector = new \ReflectionMethod($this, 'createResponse'))
62200 && __CLASS__ !== $reflector->class
62201 ) {
62202 $response = $this->createResponse($exception);
62203 $response->sendHeaders();
62204 $response->sendContent();
62205 @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);
62206
62207 return;
62208 }
62209
62210 $this->sendPhpResponse($exception);
62211 }
62212
62213
62214
62215
62216
62217
62218
62219
62220
62221 public function sendPhpResponse($exception)
62222 {
62223 if (!$exception instanceof FlattenException) {
62224 $exception = FlattenException::create($exception);
62225 }
62226
62227 if (!headers_sent()) {
62228 header(sprintf('HTTP/1.0 %s', $exception->getStatusCode()));
62229 foreach ($exception->getHeaders() as $name => $value) {
62230 header($name.': '.$value, false);
62231 }
62232 header('Content-Type: text/html; charset='.$this->charset);
62233 }
62234
62235 echo $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
62236 }
62237
62238
62239
62240
62241
62242
62243
62244
62245
62246
62247 public function createResponse($exception)
62248 {
62249 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
62250
62251 if (!$exception instanceof FlattenException) {
62252 $exception = FlattenException::create($exception);
62253 }
62254
62255 return Response::create($this->getHtml($exception), $exception->getStatusCode(), $exception->getHeaders())->setCharset($this->charset);
62256 }
62257
62258
62259
62260
62261
62262
62263
62264
62265 public function getHtml($exception)
62266 {
62267 if (!$exception instanceof FlattenException) {
62268 $exception = FlattenException::create($exception);
62269 }
62270
62271 return $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
62272 }
62273
62274
62275
62276
62277
62278
62279
62280
62281 public function getContent(FlattenException $exception)
62282 {
62283 switch ($exception->getStatusCode()) {
62284 case 404:
62285 $title = 'Sorry, the page you are looking for could not be found.';
62286 break;
62287 default:
62288 $title = 'Whoops, looks like something went wrong.';
62289 }
62290
62291 $content = '';
62292 if ($this->debug) {
62293 try {
62294 $count = count($exception->getAllPrevious());
62295 $total = $count + 1;
62296 foreach ($exception->toArray() as $position => $e) {
62297 $ind = $count - $position + 1;
62298 $class = $this->formatClass($e['class']);
62299 $message = nl2br($this->escapeHtml($e['message']));
62300 $content .= sprintf(<<<'EOF'
62301                         <h2 class="block_exception clear_fix">
62302                             <span class="exception_counter">%d/%d</span>
62303                             <span class="exception_title">%s%s:</span>
62304                             <span class="exception_message">%s</span>
62305                         </h2>
62306                         <div class="block">
62307                             <ol class="traces list_exception">
62308
62309 EOF
62310 , $ind, $total, $class, $this->formatPath($e['trace'][0]['file'], $e['trace'][0]['line']), $message);
62311 foreach ($e['trace'] as $trace) {
62312 $content .= '       <li>';
62313 if ($trace['function']) {
62314 $content .= sprintf('at %s%s%s(%s)', $this->formatClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args']));
62315 }
62316 if (isset($trace['file']) && isset($trace['line'])) {
62317 $content .= $this->formatPath($trace['file'], $trace['line']);
62318 }
62319 $content .= "</li>\n";
62320 }
62321
62322 $content .= "    </ol>\n</div>\n";
62323 }
62324 } catch (\Exception $e) {
62325
62326  if ($this->debug) {
62327 $title = sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $this->escapeHtml($e->getMessage()));
62328 } else {
62329 $title = 'Whoops, looks like something went wrong.';
62330 }
62331 }
62332 }
62333
62334 return <<<EOF
62335             <div id="sf-resetcontent" class="sf-reset">
62336                 <h1>$title</h1>
62337                 $content
62338             </div>
62339 EOF;
62340 }
62341
62342
62343
62344
62345
62346
62347
62348
62349 public function getStylesheet(FlattenException $exception)
62350 {
62351 return <<<'EOF'
62352             .sf-reset { font: 11px Verdana, Arial, sans-serif; color: #333 }
62353             .sf-reset .clear { clear:both; height:0; font-size:0; line-height:0; }
62354             .sf-reset .clear_fix:after { display:block; height:0; clear:both; visibility:hidden; }
62355             .sf-reset .clear_fix { display:inline-block; }
62356             .sf-reset * html .clear_fix { height:1%; }
62357             .sf-reset .clear_fix { display:block; }
62358             .sf-reset, .sf-reset .block { margin: auto }
62359             .sf-reset abbr { border-bottom: 1px dotted #000; cursor: help; }
62360             .sf-reset p { font-size:14px; line-height:20px; color:#868686; padding-bottom:20px }
62361             .sf-reset strong { font-weight:bold; }
62362             .sf-reset a { color:#6c6159; cursor: default; }
62363             .sf-reset a img { border:none; }
62364             .sf-reset a:hover { text-decoration:underline; }
62365             .sf-reset em { font-style:italic; }
62366             .sf-reset h1, .sf-reset h2 { font: 20px Georgia, "Times New Roman", Times, serif }
62367             .sf-reset .exception_counter { background-color: #fff; color: #333; padding: 6px; float: left; margin-right: 10px; float: left; display: block; }
62368             .sf-reset .exception_title { margin-left: 3em; margin-bottom: 0.7em; display: block; }
62369             .sf-reset .exception_message { margin-left: 3em; display: block; }
62370             .sf-reset .traces li { font-size:12px; padding: 2px 4px; list-style-type:decimal; margin-left:20px; }
62371             .sf-reset .block { background-color:#FFFFFF; padding:10px 28px; margin-bottom:20px;
62372                 -webkit-border-bottom-right-radius: 16px;
62373                 -webkit-border-bottom-left-radius: 16px;
62374                 -moz-border-radius-bottomright: 16px;
62375                 -moz-border-radius-bottomleft: 16px;
62376                 border-bottom-right-radius: 16px;
62377                 border-bottom-left-radius: 16px;
62378                 border-bottom:1px solid #ccc;
62379                 border-right:1px solid #ccc;
62380                 border-left:1px solid #ccc;
62381                 word-wrap: break-word;
62382             }
62383             .sf-reset .block_exception { background-color:#ddd; color: #333; padding:20px;
62384                 -webkit-border-top-left-radius: 16px;
62385                 -webkit-border-top-right-radius: 16px;
62386                 -moz-border-radius-topleft: 16px;
62387                 -moz-border-radius-topright: 16px;
62388                 border-top-left-radius: 16px;
62389                 border-top-right-radius: 16px;
62390                 border-top:1px solid #ccc;
62391                 border-right:1px solid #ccc;
62392                 border-left:1px solid #ccc;
62393                 overflow: hidden;
62394                 word-wrap: break-word;
62395             }
62396             .sf-reset a { background:none; color:#868686; text-decoration:none; }
62397             .sf-reset a:hover { background:none; color:#313131; text-decoration:underline; }
62398             .sf-reset ol { padding: 10px 0; }
62399             .sf-reset h1 { background-color:#FFFFFF; padding: 15px 28px; margin-bottom: 20px;
62400                 -webkit-border-radius: 10px;
62401                 -moz-border-radius: 10px;
62402                 border-radius: 10px;
62403                 border: 1px solid #ccc;
62404             }
62405 EOF;
62406 }
62407
62408 private function decorate($content, $css)
62409 {
62410 return <<<EOF
62411 <!DOCTYPE html>
62412 <html>
62413     <head>
62414         <meta charset="{$this->charset}" />
62415         <meta name="robots" content="noindex,nofollow" />
62416         <style>
62417             /* Copyright (c) 2010, Yahoo! Inc. All rights reserved. Code licensed under the BSD License: http://developer.yahoo.com/yui/license.html */
62418             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;}
62419
62420             html { background: #eee; padding: 10px }
62421             img { border: 0; }
62422             #sf-resetcontent { width:970px; margin:0 auto; }
62423             $css
62424         </style>
62425     </head>
62426     <body>
62427         $content
62428     </body>
62429 </html>
62430 EOF;
62431 }
62432
62433 private function formatClass($class)
62434 {
62435 $parts = explode('\\', $class);
62436
62437 return sprintf('<abbr title="%s">%s</abbr>', $class, array_pop($parts));
62438 }
62439
62440 private function formatPath($path, $line)
62441 {
62442 $path = $this->escapeHtml($path);
62443 $file = preg_match('#[^/\\\\]*$#', $path, $file) ? $file[0] : $path;
62444
62445 if ($linkFormat = $this->fileLinkFormat) {
62446 $link = strtr($this->escapeHtml($linkFormat), array('%f' => $path, '%l' => (int) $line));
62447
62448 return sprintf(' in <a href="%s" title="Go to source">%s line %d</a>', $link, $file, $line);
62449 }
62450
62451 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);
62452 }
62453
62454
62455
62456
62457
62458
62459
62460
62461 private function formatArgs(array $args)
62462 {
62463 $result = array();
62464 foreach ($args as $key => $item) {
62465 if ('object' === $item[0]) {
62466 $formattedValue = sprintf('<em>object</em>(%s)', $this->formatClass($item[1]));
62467 } elseif ('array' === $item[0]) {
62468 $formattedValue = sprintf('<em>array</em>(%s)', is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]);
62469 } elseif ('string' === $item[0]) {
62470 $formattedValue = sprintf("'%s'", $this->escapeHtml($item[1]));
62471 } elseif ('null' === $item[0]) {
62472 $formattedValue = '<em>null</em>';
62473 } elseif ('boolean' === $item[0]) {
62474 $formattedValue = '<em>'.strtolower(var_export($item[1], true)).'</em>';
62475 } elseif ('resource' === $item[0]) {
62476 $formattedValue = '<em>resource</em>';
62477 } else {
62478 $formattedValue = str_replace("\n", '', var_export($this->escapeHtml((string) $item[1]), true));
62479 }
62480
62481 $result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escapeHtml($key), $formattedValue);
62482 }
62483
62484 return implode(', ', $result);
62485 }
62486
62487
62488
62489
62490
62491
62492 protected static function utf8Htmlize($str)
62493 {
62494 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0.', E_USER_DEPRECATED);
62495
62496 return htmlspecialchars($str, ENT_QUOTES | (\PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), 'UTF-8');
62497 }
62498
62499
62500
62501
62502 private function escapeHtml($str)
62503 {
62504 return htmlspecialchars($str, ENT_QUOTES | (\PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), $this->charset);
62505 }
62506
62507
62508
62509
62510 public function catchOutput($buffer)
62511 {
62512 $this->caughtBuffer = $buffer;
62513
62514 return '';
62515 }
62516
62517
62518
62519
62520 public function cleanOutput($buffer)
62521 {
62522 if ($this->caughtLength) {
62523
62524  $cleanBuffer = substr_replace($buffer, '', 0, $this->caughtLength);
62525 if (isset($cleanBuffer[0])) {
62526 $buffer = $cleanBuffer;
62527 }
62528 }
62529
62530 return $buffer;
62531 }
62532 }
62533 <?php
62534
62535
62536
62537
62538
62539
62540
62541
62542
62543
62544 namespace Symfony\Component\Debug\FatalErrorHandler;
62545
62546 use Symfony\Component\Debug\Exception\ClassNotFoundException;
62547 use Symfony\Component\Debug\Exception\FatalErrorException;
62548 use Symfony\Component\Debug\DebugClassLoader;
62549 use Composer\Autoload\ClassLoader as ComposerClassLoader;
62550 use Symfony\Component\ClassLoader\ClassLoader as SymfonyClassLoader;
62551 use Symfony\Component\ClassLoader\UniversalClassLoader as SymfonyUniversalClassLoader;
62552
62553
62554
62555
62556
62557
62558 class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
62559 {
62560
62561
62562
62563 public function handleError(array $error, FatalErrorException $exception)
62564 {
62565 $messageLen = strlen($error['message']);
62566 $notFoundSuffix = '\' not found';
62567 $notFoundSuffixLen = strlen($notFoundSuffix);
62568 if ($notFoundSuffixLen > $messageLen) {
62569 return;
62570 }
62571
62572 if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
62573 return;
62574 }
62575
62576 foreach (array('class', 'interface', 'trait') as $typeName) {
62577 $prefix = ucfirst($typeName).' \'';
62578 $prefixLen = strlen($prefix);
62579 if (0 !== strpos($error['message'], $prefix)) {
62580 continue;
62581 }
62582
62583 $fullyQualifiedClassName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);
62584 if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedClassName, '\\')) {
62585 $className = substr($fullyQualifiedClassName, $namespaceSeparatorIndex + 1);
62586 $namespacePrefix = substr($fullyQualifiedClassName, 0, $namespaceSeparatorIndex);
62587 $message = sprintf('Attempted to load %s "%s" from namespace "%s".', $typeName, $className, $namespacePrefix);
62588 $tail = ' for another namespace?';
62589 } else {
62590 $className = $fullyQualifiedClassName;
62591 $message = sprintf('Attempted to load %s "%s" from the global namespace.', $typeName, $className);
62592 $tail = '?';
62593 }
62594
62595 if ($candidates = $this->getClassCandidates($className)) {
62596 $tail = array_pop($candidates).'"?';
62597 if ($candidates) {
62598 $tail = ' for e.g. "'.implode('", "', $candidates).'" or "'.$tail;
62599 } else {
62600 $tail = ' for "'.$tail;
62601 }
62602 }
62603 $message .= "\nDid you forget a \"use\" statement".$tail;
62604
62605 return new ClassNotFoundException($message, $exception);
62606 }
62607 }
62608
62609
62610
62611
62612
62613
62614
62615
62616
62617
62618
62619 private function getClassCandidates($class)
62620 {
62621 if (!is_array($functions = spl_autoload_functions())) {
62622 return array();
62623 }
62624
62625
62626  $classes = array();
62627
62628 foreach ($functions as $function) {
62629 if (!is_array($function)) {
62630 continue;
62631 }
62632
62633  if ($function[0] instanceof DebugClassLoader) {
62634 $function = $function[0]->getClassLoader();
62635
62636
62637  if (is_object($function)) {
62638 $function = array($function);
62639 }
62640
62641 if (!is_array($function)) {
62642 continue;
62643 }
62644 }
62645
62646 if ($function[0] instanceof ComposerClassLoader || $function[0] instanceof SymfonyClassLoader || $function[0] instanceof SymfonyUniversalClassLoader) {
62647 foreach ($function[0]->getPrefixes() as $prefix => $paths) {
62648 foreach ($paths as $path) {
62649 $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
62650 }
62651 }
62652 }
62653 if ($function[0] instanceof ComposerClassLoader) {
62654 foreach ($function[0]->getPrefixesPsr4() as $prefix => $paths) {
62655 foreach ($paths as $path) {
62656 $classes = array_merge($classes, $this->findClassInPath($path, $class, $prefix));
62657 }
62658 }
62659 }
62660 }
62661
62662 return array_unique($classes);
62663 }
62664
62665
62666
62667
62668
62669
62670
62671
62672 private function findClassInPath($path, $class, $prefix)
62673 {
62674 if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) {
62675 return array();
62676 }
62677
62678 $classes = array();
62679 $filename = $class.'.php';
62680 foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
62681 if ($filename == $file->getFileName() && $class = $this->convertFileToClass($path, $file->getPathName(), $prefix)) {
62682 $classes[] = $class;
62683 }
62684 }
62685
62686 return $classes;
62687 }
62688
62689
62690
62691
62692
62693
62694
62695
62696 private function convertFileToClass($path, $file, $prefix)
62697 {
62698 $candidates = array(
62699
62700  $namespacedClass = str_replace(array($path.DIRECTORY_SEPARATOR, '.php', '/'), array('', '', '\\'), $file),
62701
62702  $prefix.$namespacedClass,
62703
62704  $prefix.'\\'.$namespacedClass,
62705
62706  str_replace('\\', '_', $namespacedClass),
62707
62708  str_replace('\\', '_', $prefix.$namespacedClass),
62709
62710  str_replace('\\', '_', $prefix.'\\'.$namespacedClass),
62711 );
62712
62713 if ($prefix) {
62714 $candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); });
62715 }
62716
62717
62718  
62719  
62720  foreach ($candidates as $candidate) {
62721 if ($this->classExists($candidate)) {
62722 return $candidate;
62723 }
62724 }
62725
62726 require_once $file;
62727
62728 foreach ($candidates as $candidate) {
62729 if ($this->classExists($candidate)) {
62730 return $candidate;
62731 }
62732 }
62733 }
62734
62735
62736
62737
62738
62739
62740 private function classExists($class)
62741 {
62742 return class_exists($class, false) || interface_exists($class, false) || (function_exists('trait_exists') && trait_exists($class, false));
62743 }
62744 }
62745 <?php
62746
62747
62748
62749
62750
62751
62752
62753
62754
62755
62756 namespace Symfony\Component\Debug\FatalErrorHandler;
62757
62758 use Symfony\Component\Debug\Exception\FatalErrorException;
62759
62760
62761
62762
62763
62764
62765 interface FatalErrorHandlerInterface
62766 {
62767
62768
62769
62770
62771
62772
62773
62774
62775 public function handleError(array $error, FatalErrorException $exception);
62776 }
62777 <?php
62778
62779
62780
62781
62782
62783
62784
62785
62786
62787
62788 namespace Symfony\Component\Debug\FatalErrorHandler;
62789
62790 use Symfony\Component\Debug\Exception\UndefinedFunctionException;
62791 use Symfony\Component\Debug\Exception\FatalErrorException;
62792
62793
62794
62795
62796
62797
62798 class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface
62799 {
62800
62801
62802
62803 public function handleError(array $error, FatalErrorException $exception)
62804 {
62805 $messageLen = strlen($error['message']);
62806 $notFoundSuffix = '()';
62807 $notFoundSuffixLen = strlen($notFoundSuffix);
62808 if ($notFoundSuffixLen > $messageLen) {
62809 return;
62810 }
62811
62812 if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) {
62813 return;
62814 }
62815
62816 $prefix = 'Call to undefined function ';
62817 $prefixLen = strlen($prefix);
62818 if (0 !== strpos($error['message'], $prefix)) {
62819 return;
62820 }
62821
62822 $fullyQualifiedFunctionName = substr($error['message'], $prefixLen, -$notFoundSuffixLen);
62823 if (false !== $namespaceSeparatorIndex = strrpos($fullyQualifiedFunctionName, '\\')) {
62824 $functionName = substr($fullyQualifiedFunctionName, $namespaceSeparatorIndex + 1);
62825 $namespacePrefix = substr($fullyQualifiedFunctionName, 0, $namespaceSeparatorIndex);
62826 $message = sprintf('Attempted to call function "%s" from namespace "%s".', $functionName, $namespacePrefix);
62827 } else {
62828 $functionName = $fullyQualifiedFunctionName;
62829 $message = sprintf('Attempted to call function "%s" from the global namespace.', $functionName);
62830 }
62831
62832 $candidates = array();
62833 foreach (get_defined_functions() as $type => $definedFunctionNames) {
62834 foreach ($definedFunctionNames as $definedFunctionName) {
62835 if (false !== $namespaceSeparatorIndex = strrpos($definedFunctionName, '\\')) {
62836 $definedFunctionNameBasename = substr($definedFunctionName, $namespaceSeparatorIndex + 1);
62837 } else {
62838 $definedFunctionNameBasename = $definedFunctionName;
62839 }
62840
62841 if ($definedFunctionNameBasename === $functionName) {
62842 $candidates[] = '\\'.$definedFunctionName;
62843 }
62844 }
62845 }
62846
62847 if ($candidates) {
62848 sort($candidates);
62849 $last = array_pop($candidates).'"?';
62850 if ($candidates) {
62851 $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
62852 } else {
62853 $candidates = '"'.$last;
62854 }
62855 $message .= "\nDid you mean to call ".$candidates;
62856 }
62857
62858 return new UndefinedFunctionException($message, $exception);
62859 }
62860 }
62861 <?php
62862
62863
62864
62865
62866
62867
62868
62869
62870
62871
62872 namespace Symfony\Component\Debug\FatalErrorHandler;
62873
62874 use Symfony\Component\Debug\Exception\FatalErrorException;
62875 use Symfony\Component\Debug\Exception\UndefinedMethodException;
62876
62877
62878
62879
62880
62881
62882 class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface
62883 {
62884
62885
62886
62887 public function handleError(array $error, FatalErrorException $exception)
62888 {
62889 preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $error['message'], $matches);
62890 if (!$matches) {
62891 return;
62892 }
62893
62894 $className = $matches[1];
62895 $methodName = $matches[2];
62896
62897 $message = sprintf('Attempted to call an undefined method named "%s" of class "%s".', $methodName, $className);
62898
62899 if (!class_exists($className) || null === $methods = get_class_methods($className)) {
62900
62901  return new UndefinedMethodException($message, $exception);
62902 }
62903
62904 $candidates = array();
62905 foreach ($methods as $definedMethodName) {
62906 $lev = levenshtein($methodName, $definedMethodName);
62907 if ($lev <= strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) {
62908 $candidates[] = $definedMethodName;
62909 }
62910 }
62911
62912 if ($candidates) {
62913 sort($candidates);
62914 $last = array_pop($candidates).'"?';
62915 if ($candidates) {
62916 $candidates = 'e.g. "'.implode('", "', $candidates).'" or "'.$last;
62917 } else {
62918 $candidates = '"'.$last;
62919 }
62920
62921 $message .= "\nDid you mean to call ".$candidates;
62922 }
62923
62924 return new UndefinedMethodException($message, $exception);
62925 }
62926 }
62927 Copyright (c) 2004-2017 Fabien Potencier
62928
62929 Permission is hereby granted, free of charge, to any person obtaining a copy
62930 of this software and associated documentation files (the "Software"), to deal
62931 in the Software without restriction, including without limitation the rights
62932 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
62933 copies of the Software, and to permit persons to whom the Software is furnished
62934 to do so, subject to the following conditions:
62935
62936 The above copyright notice and this permission notice shall be included in all
62937 copies or substantial portions of the Software.
62938
62939 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
62940 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
62941 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
62942 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
62943 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
62944 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
62945 THE SOFTWARE.
62946 <?php
62947
62948
62949
62950
62951
62952
62953
62954
62955
62956
62957 namespace Symfony\Component\Filesystem\Exception;
62958
62959
62960
62961
62962
62963
62964 interface ExceptionInterface
62965 {
62966 }
62967 <?php
62968
62969
62970
62971
62972
62973
62974
62975
62976
62977
62978 namespace Symfony\Component\Filesystem\Exception;
62979
62980
62981
62982
62983
62984
62985
62986 class FileNotFoundException extends IOException
62987 {
62988 public function __construct($message = null, $code = 0, \Exception $previous = null, $path = null)
62989 {
62990 if (null === $message) {
62991 if (null === $path) {
62992 $message = 'File could not be found.';
62993 } else {
62994 $message = sprintf('File "%s" could not be found.', $path);
62995 }
62996 }
62997
62998 parent::__construct($message, $code, $previous, $path);
62999 }
63000 }
63001 <?php
63002
63003
63004
63005
63006
63007
63008
63009
63010
63011
63012 namespace Symfony\Component\Filesystem\Exception;
63013
63014
63015
63016
63017
63018
63019
63020
63021 class IOException extends \RuntimeException implements IOExceptionInterface
63022 {
63023 private $path;
63024
63025 public function __construct($message, $code = 0, \Exception $previous = null, $path = null)
63026 {
63027 $this->path = $path;
63028
63029 parent::__construct($message, $code, $previous);
63030 }
63031
63032
63033
63034
63035 public function getPath()
63036 {
63037 return $this->path;
63038 }
63039 }
63040 <?php
63041
63042
63043
63044
63045
63046
63047
63048
63049
63050
63051 namespace Symfony\Component\Filesystem\Exception;
63052
63053
63054
63055
63056
63057
63058 interface IOExceptionInterface extends ExceptionInterface
63059 {
63060
63061
63062
63063
63064
63065 public function getPath();
63066 }
63067 <?php
63068
63069
63070
63071
63072
63073
63074
63075
63076
63077
63078 namespace Symfony\Component\Filesystem;
63079
63080 use Symfony\Component\Filesystem\Exception\IOException;
63081 use Symfony\Component\Filesystem\Exception\FileNotFoundException;
63082
63083
63084
63085
63086
63087
63088 class Filesystem
63089 {
63090
63091
63092
63093
63094
63095
63096
63097
63098
63099
63100
63101
63102
63103
63104 public function copy($originFile, $targetFile, $overwriteNewerFiles = false)
63105 {
63106 $originIsLocal = stream_is_local($originFile) || 0 === stripos($originFile, 'file://');
63107 if ($originIsLocal && !is_file($originFile)) {
63108 throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile);
63109 }
63110
63111 $this->mkdir(dirname($targetFile));
63112
63113 $doCopy = true;
63114 if (!$overwriteNewerFiles && null === parse_url($originFile, PHP_URL_HOST) && is_file($targetFile)) {
63115 $doCopy = filemtime($originFile) > filemtime($targetFile);
63116 }
63117
63118 if ($doCopy) {
63119
63120  if (false === $source = @fopen($originFile, 'r')) {
63121 throw new IOException(sprintf('Failed to copy "%s" to "%s" because source file could not be opened for reading.', $originFile, $targetFile), 0, null, $originFile);
63122 }
63123
63124
63125  if (false === $target = @fopen($targetFile, 'w', null, stream_context_create(array('ftp' => array('overwrite' => true))))) {
63126 throw new IOException(sprintf('Failed to copy "%s" to "%s" because target file could not be opened for writing.', $originFile, $targetFile), 0, null, $originFile);
63127 }
63128
63129 $bytesCopied = stream_copy_to_stream($source, $target);
63130 fclose($source);
63131 fclose($target);
63132 unset($source, $target);
63133
63134 if (!is_file($targetFile)) {
63135 throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile);
63136 }
63137
63138 if ($originIsLocal) {
63139
63140  @chmod($targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111));
63141
63142 if ($bytesCopied !== $bytesOrigin = filesize($originFile)) {
63143 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);
63144 }
63145 }
63146 }
63147 }
63148
63149
63150
63151
63152
63153
63154
63155
63156
63157 public function mkdir($dirs, $mode = 0777)
63158 {
63159 foreach ($this->toIterator($dirs) as $dir) {
63160 if (is_dir($dir)) {
63161 continue;
63162 }
63163
63164 if (true !== @mkdir($dir, $mode, true)) {
63165 $error = error_get_last();
63166 if (!is_dir($dir)) {
63167
63168  if ($error) {
63169 throw new IOException(sprintf('Failed to create "%s": %s.', $dir, $error['message']), 0, null, $dir);
63170 }
63171 throw new IOException(sprintf('Failed to create "%s"', $dir), 0, null, $dir);
63172 }
63173 }
63174 }
63175 }
63176
63177
63178
63179
63180
63181
63182
63183
63184 public function exists($files)
63185 {
63186 foreach ($this->toIterator($files) as $file) {
63187 if ('\\' === DIRECTORY_SEPARATOR && strlen($file) > 258) {
63188 throw new IOException('Could not check if file exist because path length exceeds 258 characters.', 0, null, $file);
63189 }
63190
63191 if (!file_exists($file)) {
63192 return false;
63193 }
63194 }
63195
63196 return true;
63197 }
63198
63199
63200
63201
63202
63203
63204
63205
63206
63207
63208 public function touch($files, $time = null, $atime = null)
63209 {
63210 foreach ($this->toIterator($files) as $file) {
63211 $touch = $time ? @touch($file, $time, $atime) : @touch($file);
63212 if (true !== $touch) {
63213 throw new IOException(sprintf('Failed to touch "%s".', $file), 0, null, $file);
63214 }
63215 }
63216 }
63217
63218
63219
63220
63221
63222
63223
63224
63225 public function remove($files)
63226 {
63227 if ($files instanceof \Traversable) {
63228 $files = iterator_to_array($files, false);
63229 } elseif (!is_array($files)) {
63230 $files = array($files);
63231 }
63232 $files = array_reverse($files);
63233 foreach ($files as $file) {
63234 if (is_link($file)) {
63235
63236  if (!@(unlink($file) || '\\' !== DIRECTORY_SEPARATOR || rmdir($file)) && file_exists($file)) {
63237 $error = error_get_last();
63238 throw new IOException(sprintf('Failed to remove symlink "%s": %s.', $file, $error['message']));
63239 }
63240 } elseif (is_dir($file)) {
63241 $this->remove(new \FilesystemIterator($file, \FilesystemIterator::CURRENT_AS_PATHNAME | \FilesystemIterator::SKIP_DOTS));
63242
63243 if (!@rmdir($file) && file_exists($file)) {
63244 $error = error_get_last();
63245 throw new IOException(sprintf('Failed to remove directory "%s": %s.', $file, $error['message']));
63246 }
63247 } elseif (!@unlink($file) && file_exists($file)) {
63248 $error = error_get_last();
63249 throw new IOException(sprintf('Failed to remove file "%s": %s.', $file, $error['message']));
63250 }
63251 }
63252 }
63253
63254
63255
63256
63257
63258
63259
63260
63261
63262
63263
63264 public function chmod($files, $mode, $umask = 0000, $recursive = false)
63265 {
63266 foreach ($this->toIterator($files) as $file) {
63267 if (true !== @chmod($file, $mode & ~$umask)) {
63268 throw new IOException(sprintf('Failed to chmod file "%s".', $file), 0, null, $file);
63269 }
63270 if ($recursive && is_dir($file) && !is_link($file)) {
63271 $this->chmod(new \FilesystemIterator($file), $mode, $umask, true);
63272 }
63273 }
63274 }
63275
63276
63277
63278
63279
63280
63281
63282
63283
63284
63285 public function chown($files, $user, $recursive = false)
63286 {
63287 foreach ($this->toIterator($files) as $file) {
63288 if ($recursive && is_dir($file) && !is_link($file)) {
63289 $this->chown(new \FilesystemIterator($file), $user, true);
63290 }
63291 if (is_link($file) && function_exists('lchown')) {
63292 if (true !== @lchown($file, $user)) {
63293 throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
63294 }
63295 } else {
63296 if (true !== @chown($file, $user)) {
63297 throw new IOException(sprintf('Failed to chown file "%s".', $file), 0, null, $file);
63298 }
63299 }
63300 }
63301 }
63302
63303
63304
63305
63306
63307
63308
63309
63310
63311
63312 public function chgrp($files, $group, $recursive = false)
63313 {
63314 foreach ($this->toIterator($files) as $file) {
63315 if ($recursive && is_dir($file) && !is_link($file)) {
63316 $this->chgrp(new \FilesystemIterator($file), $group, true);
63317 }
63318 if (is_link($file) && function_exists('lchgrp')) {
63319 if (true !== @lchgrp($file, $group) || (defined('HHVM_VERSION') && !posix_getgrnam($group))) {
63320 throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
63321 }
63322 } else {
63323 if (true !== @chgrp($file, $group)) {
63324 throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file);
63325 }
63326 }
63327 }
63328 }
63329
63330
63331
63332
63333
63334
63335
63336
63337
63338
63339
63340 public function rename($origin, $target, $overwrite = false)
63341 {
63342
63343  if (!$overwrite && $this->isReadable($target)) {
63344 throw new IOException(sprintf('Cannot rename because the target "%s" already exists.', $target), 0, null, $target);
63345 }
63346
63347 if (true !== @rename($origin, $target)) {
63348 if (is_dir($origin)) {
63349
63350  $this->mirror($origin, $target, null, array('override' => $overwrite, 'delete' => $overwrite));
63351 $this->remove($origin);
63352
63353 return;
63354 }
63355 throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target);
63356 }
63357 }
63358
63359
63360
63361
63362
63363
63364
63365
63366
63367
63368 private function isReadable($filename)
63369 {
63370 if ('\\' === DIRECTORY_SEPARATOR && strlen($filename) > 258) {
63371 throw new IOException('Could not check if file is readable because path length exceeds 258 characters.', 0, null, $filename);
63372 }
63373
63374 return is_readable($filename);
63375 }
63376
63377
63378
63379
63380
63381
63382
63383
63384
63385
63386 public function symlink($originDir, $targetDir, $copyOnWindows = false)
63387 {
63388 if ('\\' === DIRECTORY_SEPARATOR) {
63389 $originDir = strtr($originDir, '/', '\\');
63390 $targetDir = strtr($targetDir, '/', '\\');
63391
63392 if ($copyOnWindows) {
63393 $this->mirror($originDir, $targetDir);
63394
63395 return;
63396 }
63397 }
63398
63399 $this->mkdir(dirname($targetDir));
63400
63401 $ok = false;
63402 if (is_link($targetDir)) {
63403 if (readlink($targetDir) != $originDir) {
63404 $this->remove($targetDir);
63405 } else {
63406 $ok = true;
63407 }
63408 }
63409
63410 if (!$ok && true !== @symlink($originDir, $targetDir)) {
63411 $report = error_get_last();
63412 if (is_array($report)) {
63413 if ('\\' === DIRECTORY_SEPARATOR && false !== strpos($report['message'], 'error code(1314)')) {
63414 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);
63415 }
63416 }
63417 throw new IOException(sprintf('Failed to create symbolic link from "%s" to "%s".', $originDir, $targetDir), 0, null, $targetDir);
63418 }
63419 }
63420
63421
63422
63423
63424
63425
63426
63427
63428
63429 public function makePathRelative($endPath, $startPath)
63430 {
63431
63432  if ('\\' === DIRECTORY_SEPARATOR) {
63433 $endPath = str_replace('\\', '/', $endPath);
63434 $startPath = str_replace('\\', '/', $startPath);
63435 }
63436
63437
63438  $startPathArr = explode('/', trim($startPath, '/'));
63439 $endPathArr = explode('/', trim($endPath, '/'));
63440
63441 if ('/' !== $startPath[0]) {
63442 array_shift($startPathArr);
63443 }
63444
63445 if ('/' !== $endPath[0]) {
63446 array_shift($endPathArr);
63447 }
63448
63449 $normalizePathArray = function ($pathSegments) {
63450 $result = array();
63451
63452 foreach ($pathSegments as $segment) {
63453 if ('..' === $segment) {
63454 array_pop($result);
63455 } else {
63456 $result[] = $segment;
63457 }
63458 }
63459
63460 return $result;
63461 };
63462
63463 $startPathArr = $normalizePathArray($startPathArr);
63464 $endPathArr = $normalizePathArray($endPathArr);
63465
63466
63467  $index = 0;
63468 while (isset($startPathArr[$index]) && isset($endPathArr[$index]) && $startPathArr[$index] === $endPathArr[$index]) {
63469 ++$index;
63470 }
63471
63472
63473  if (count($startPathArr) === 1 && $startPathArr[0] === '') {
63474 $depth = 0;
63475 } else {
63476 $depth = count($startPathArr) - $index;
63477 }
63478
63479
63480  if ('/' === $startPath[0] && 0 === $index && 0 === $depth) {
63481 $traverser = '';
63482 } else {
63483
63484  $traverser = str_repeat('../', $depth);
63485 }
63486
63487 $endPathRemainder = implode('/', array_slice($endPathArr, $index));
63488
63489
63490  $relativePath = $traverser.('' !== $endPathRemainder ? $endPathRemainder.'/' : '');
63491
63492 return '' === $relativePath ? './' : $relativePath;
63493 }
63494
63495
63496
63497
63498
63499
63500
63501
63502
63503
63504
63505
63506
63507
63508
63509 public function mirror($originDir, $targetDir, \Traversable $iterator = null, $options = array())
63510 {
63511 $targetDir = rtrim($targetDir, '/\\');
63512 $originDir = rtrim($originDir, '/\\');
63513
63514
63515  if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) {
63516 $deleteIterator = $iterator;
63517 if (null === $deleteIterator) {
63518 $flags = \FilesystemIterator::SKIP_DOTS;
63519 $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST);
63520 }
63521 foreach ($deleteIterator as $file) {
63522 $origin = str_replace($targetDir, $originDir, $file->getPathname());
63523 if (!$this->exists($origin)) {
63524 $this->remove($file);
63525 }
63526 }
63527 }
63528
63529 $copyOnWindows = false;
63530 if (isset($options['copy_on_windows'])) {
63531 $copyOnWindows = $options['copy_on_windows'];
63532 }
63533
63534 if (null === $iterator) {
63535 $flags = $copyOnWindows ? \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::FOLLOW_SYMLINKS : \FilesystemIterator::SKIP_DOTS;
63536 $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($originDir, $flags), \RecursiveIteratorIterator::SELF_FIRST);
63537 }
63538
63539 if ($this->exists($originDir)) {
63540 $this->mkdir($targetDir);
63541 }
63542
63543 foreach ($iterator as $file) {
63544 $target = str_replace($originDir, $targetDir, $file->getPathname());
63545
63546 if ($copyOnWindows) {
63547 if (is_file($file)) {
63548 $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
63549 } elseif (is_dir($file)) {
63550 $this->mkdir($target);
63551 } else {
63552 throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
63553 }
63554 } else {
63555 if (is_link($file)) {
63556 $this->symlink($file->getLinkTarget(), $target);
63557 } elseif (is_dir($file)) {
63558 $this->mkdir($target);
63559 } elseif (is_file($file)) {
63560 $this->copy($file, $target, isset($options['override']) ? $options['override'] : false);
63561 } else {
63562 throw new IOException(sprintf('Unable to guess "%s" file type.', $file), 0, null, $file);
63563 }
63564 }
63565 }
63566 }
63567
63568
63569
63570
63571
63572
63573
63574
63575 public function isAbsolutePath($file)
63576 {
63577 return strspn($file, '/\\', 0, 1)
63578 || (strlen($file) > 3 && ctype_alpha($file[0])
63579 && substr($file, 1, 1) === ':'
63580 && strspn($file, '/\\', 2, 1)
63581 )
63582 || null !== parse_url($file, PHP_URL_SCHEME)
63583 ;
63584 }
63585
63586
63587
63588
63589
63590
63591
63592
63593
63594
63595 public function tempnam($dir, $prefix)
63596 {
63597 list($scheme, $hierarchy) = $this->getSchemeAndHierarchy($dir);
63598
63599
63600  if (null === $scheme || 'file' === $scheme || 'gs' === $scheme) {
63601 $tmpFile = @tempnam($hierarchy, $prefix);
63602
63603
63604  if (false !== $tmpFile) {
63605 if (null !== $scheme && 'gs' !== $scheme) {
63606 return $scheme.'://'.$tmpFile;
63607 }
63608
63609 return $tmpFile;
63610 }
63611
63612 throw new IOException('A temporary file could not be created.');
63613 }
63614
63615
63616  for ($i = 0; $i < 10; ++$i) {
63617
63618  $tmpFile = $dir.'/'.$prefix.uniqid(mt_rand(), true);
63619
63620
63621  
63622  $handle = @fopen($tmpFile, 'x+');
63623
63624
63625  if (false === $handle) {
63626 continue;
63627 }
63628
63629
63630  @fclose($handle);
63631
63632 return $tmpFile;
63633 }
63634
63635 throw new IOException('A temporary file could not be created.');
63636 }
63637
63638
63639
63640
63641
63642
63643
63644
63645
63646
63647
63648 public function dumpFile($filename, $content, $mode = 0666)
63649 {
63650 $dir = dirname($filename);
63651
63652 if (!is_dir($dir)) {
63653 $this->mkdir($dir);
63654 }
63655
63656 if (!is_writable($dir)) {
63657 throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir);
63658 }
63659
63660 $tmpFile = $this->tempnam($dir, basename($filename));
63661
63662 if (false === @file_put_contents($tmpFile, $content)) {
63663 throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
63664 }
63665
63666 if (null !== $mode) {
63667 if (func_num_args() > 2) {
63668 @trigger_error('Support for modifying file permissions is deprecated since version 2.3.12 and will be removed in 3.0.', E_USER_DEPRECATED);
63669 }
63670
63671 $this->chmod($tmpFile, $mode);
63672 } elseif (file_exists($filename)) {
63673 @chmod($tmpFile, fileperms($filename));
63674 }
63675
63676 $this->rename($tmpFile, $filename, true);
63677 }
63678
63679
63680
63681
63682
63683
63684 private function toIterator($files)
63685 {
63686 if (!$files instanceof \Traversable) {
63687 $files = new \ArrayObject(is_array($files) ? $files : array($files));
63688 }
63689
63690 return $files;
63691 }
63692
63693
63694
63695
63696
63697
63698
63699
63700 private function getSchemeAndHierarchy($filename)
63701 {
63702 $components = explode('://', $filename, 2);
63703
63704 return 2 === count($components) ? array($components[0], $components[1]) : array(null, $components[0]);
63705 }
63706 }
63707 Copyright (c) 2004-2017 Fabien Potencier
63708
63709 Permission is hereby granted, free of charge, to any person obtaining a copy
63710 of this software and associated documentation files (the "Software"), to deal
63711 in the Software without restriction, including without limitation the rights
63712 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
63713 copies of the Software, and to permit persons to whom the Software is furnished
63714 to do so, subject to the following conditions:
63715
63716 The above copyright notice and this permission notice shall be included in all
63717 copies or substantial portions of the Software.
63718
63719 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63720 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
63721 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
63722 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
63723 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
63724 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
63725 THE SOFTWARE.
63726 <?php
63727
63728
63729
63730
63731
63732
63733
63734
63735
63736
63737 namespace Symfony\Component\Filesystem;
63738
63739 use Symfony\Component\Filesystem\Exception\IOException;
63740
63741
63742
63743
63744
63745
63746
63747
63748
63749
63750
63751
63752
63753
63754 class LockHandler
63755 {
63756 private $file;
63757 private $handle;
63758
63759
63760
63761
63762
63763
63764
63765 public function __construct($name, $lockPath = null)
63766 {
63767 $lockPath = $lockPath ?: sys_get_temp_dir();
63768
63769 if (!is_dir($lockPath)) {
63770 $fs = new Filesystem();
63771 $fs->mkdir($lockPath);
63772 }
63773
63774 if (!is_writable($lockPath)) {
63775 throw new IOException(sprintf('The directory "%s" is not writable.', $lockPath), 0, null, $lockPath);
63776 }
63777
63778 $this->file = sprintf('%s/sf.%s.%s.lock', $lockPath, preg_replace('/[^a-z0-9\._-]+/i', '-', $name), hash('sha256', $name));
63779 }
63780
63781
63782
63783
63784
63785
63786
63787
63788
63789
63790 public function lock($blocking = false)
63791 {
63792 if ($this->handle) {
63793 return true;
63794 }
63795
63796 $error = null;
63797
63798
63799  set_error_handler(function ($errno, $msg) use (&$error) {
63800 $error = $msg;
63801 });
63802
63803 if (!$this->handle = fopen($this->file, 'r')) {
63804 if ($this->handle = fopen($this->file, 'x')) {
63805 chmod($this->file, 0444);
63806 } elseif (!$this->handle = fopen($this->file, 'r')) {
63807 usleep(100); 
63808  $this->handle = fopen($this->file, 'r');
63809 }
63810 }
63811 restore_error_handler();
63812
63813 if (!$this->handle) {
63814 throw new IOException($error, 0, null, $this->file);
63815 }
63816
63817
63818  
63819  if (!flock($this->handle, LOCK_EX | ($blocking ? 0 : LOCK_NB))) {
63820 fclose($this->handle);
63821 $this->handle = null;
63822
63823 return false;
63824 }
63825
63826 return true;
63827 }
63828
63829
63830
63831
63832 public function release()
63833 {
63834 if ($this->handle) {
63835 flock($this->handle, LOCK_UN | LOCK_NB);
63836 fclose($this->handle);
63837 $this->handle = null;
63838 }
63839 }
63840 }
63841 <?php
63842
63843
63844
63845
63846
63847
63848
63849
63850
63851
63852 namespace Symfony\Component\Finder\Adapter;
63853
63854 @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);
63855
63856
63857
63858
63859
63860
63861
63862
63863 abstract class AbstractAdapter implements AdapterInterface
63864 {
63865 protected $followLinks = false;
63866 protected $mode = 0;
63867 protected $minDepth = 0;
63868 protected $maxDepth = PHP_INT_MAX;
63869 protected $exclude = array();
63870 protected $names = array();
63871 protected $notNames = array();
63872 protected $contains = array();
63873 protected $notContains = array();
63874 protected $sizes = array();
63875 protected $dates = array();
63876 protected $filters = array();
63877 protected $sort = false;
63878 protected $paths = array();
63879 protected $notPaths = array();
63880 protected $ignoreUnreadableDirs = false;
63881
63882 private static $areSupported = array();
63883
63884
63885
63886
63887 public function isSupported()
63888 {
63889 $name = $this->getName();
63890
63891 if (!array_key_exists($name, self::$areSupported)) {
63892 self::$areSupported[$name] = $this->canBeUsed();
63893 }
63894
63895 return self::$areSupported[$name];
63896 }
63897
63898
63899
63900
63901 public function setFollowLinks($followLinks)
63902 {
63903 $this->followLinks = $followLinks;
63904
63905 return $this;
63906 }
63907
63908
63909
63910
63911 public function setMode($mode)
63912 {
63913 $this->mode = $mode;
63914
63915 return $this;
63916 }
63917
63918
63919
63920
63921 public function setDepths(array $depths)
63922 {
63923 $this->minDepth = 0;
63924 $this->maxDepth = PHP_INT_MAX;
63925
63926 foreach ($depths as $comparator) {
63927 switch ($comparator->getOperator()) {
63928 case '>':
63929 $this->minDepth = $comparator->getTarget() + 1;
63930 break;
63931 case '>=':
63932 $this->minDepth = $comparator->getTarget();
63933 break;
63934 case '<':
63935 $this->maxDepth = $comparator->getTarget() - 1;
63936 break;
63937 case '<=':
63938 $this->maxDepth = $comparator->getTarget();
63939 break;
63940 default:
63941 $this->minDepth = $this->maxDepth = $comparator->getTarget();
63942 }
63943 }
63944
63945 return $this;
63946 }
63947
63948
63949
63950
63951 public function setExclude(array $exclude)
63952 {
63953 $this->exclude = $exclude;
63954
63955 return $this;
63956 }
63957
63958
63959
63960
63961 public function setNames(array $names)
63962 {
63963 $this->names = $names;
63964
63965 return $this;
63966 }
63967
63968
63969
63970
63971 public function setNotNames(array $notNames)
63972 {
63973 $this->notNames = $notNames;
63974
63975 return $this;
63976 }
63977
63978
63979
63980
63981 public function setContains(array $contains)
63982 {
63983 $this->contains = $contains;
63984
63985 return $this;
63986 }
63987
63988
63989
63990
63991 public function setNotContains(array $notContains)
63992 {
63993 $this->notContains = $notContains;
63994
63995 return $this;
63996 }
63997
63998
63999
64000
64001 public function setSizes(array $sizes)
64002 {
64003 $this->sizes = $sizes;
64004
64005 return $this;
64006 }
64007
64008
64009
64010
64011 public function setDates(array $dates)
64012 {
64013 $this->dates = $dates;
64014
64015 return $this;
64016 }
64017
64018
64019
64020
64021 public function setFilters(array $filters)
64022 {
64023 $this->filters = $filters;
64024
64025 return $this;
64026 }
64027
64028
64029
64030
64031 public function setSort($sort)
64032 {
64033 $this->sort = $sort;
64034
64035 return $this;
64036 }
64037
64038
64039
64040
64041 public function setPath(array $paths)
64042 {
64043 $this->paths = $paths;
64044
64045 return $this;
64046 }
64047
64048
64049
64050
64051 public function setNotPath(array $notPaths)
64052 {
64053 $this->notPaths = $notPaths;
64054
64055 return $this;
64056 }
64057
64058
64059
64060
64061 public function ignoreUnreadableDirs($ignore = true)
64062 {
64063 $this->ignoreUnreadableDirs = (bool) $ignore;
64064
64065 return $this;
64066 }
64067
64068
64069
64070
64071
64072
64073
64074
64075
64076
64077
64078
64079 abstract protected function canBeUsed();
64080 }
64081 <?php
64082
64083
64084
64085
64086
64087
64088
64089
64090
64091
64092 namespace Symfony\Component\Finder\Adapter;
64093
64094 @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);
64095
64096 use Symfony\Component\Finder\Exception\AccessDeniedException;
64097 use Symfony\Component\Finder\Iterator;
64098 use Symfony\Component\Finder\Shell\Shell;
64099 use Symfony\Component\Finder\Expression\Expression;
64100 use Symfony\Component\Finder\Shell\Command;
64101 use Symfony\Component\Finder\Comparator\NumberComparator;
64102 use Symfony\Component\Finder\Comparator\DateComparator;
64103
64104
64105
64106
64107
64108
64109
64110
64111 abstract class AbstractFindAdapter extends AbstractAdapter
64112 {
64113
64114
64115
64116 protected $shell;
64117
64118
64119
64120
64121 public function __construct()
64122 {
64123 $this->shell = new Shell();
64124 }
64125
64126
64127
64128
64129 public function searchInDirectory($dir)
64130 {
64131
64132  $dir = realpath($dir);
64133
64134
64135  if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode && ($this->contains || $this->notContains)) {
64136 return new Iterator\FilePathsIterator(array(), $dir);
64137 }
64138
64139 $command = Command::create();
64140 $find = $this->buildFindCommand($command, $dir);
64141
64142 if ($this->followLinks) {
64143 $find->add('-follow');
64144 }
64145
64146 $find->add('-mindepth')->add($this->minDepth + 1);
64147
64148 if (PHP_INT_MAX !== $this->maxDepth) {
64149 $find->add('-maxdepth')->add($this->maxDepth + 1);
64150 }
64151
64152 if (Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES === $this->mode) {
64153 $find->add('-type d');
64154 } elseif (Iterator\FileTypeFilterIterator::ONLY_FILES === $this->mode) {
64155 $find->add('-type f');
64156 }
64157
64158 $this->buildNamesFiltering($find, $this->names);
64159 $this->buildNamesFiltering($find, $this->notNames, true);
64160 $this->buildPathsFiltering($find, $dir, $this->paths);
64161 $this->buildPathsFiltering($find, $dir, $this->notPaths, true);
64162 $this->buildSizesFiltering($find, $this->sizes);
64163 $this->buildDatesFiltering($find, $this->dates);
64164
64165 $useGrep = $this->shell->testCommand('grep') && $this->shell->testCommand('xargs');
64166 $useSort = is_int($this->sort) && $this->shell->testCommand('sort') && $this->shell->testCommand('cut');
64167
64168 if ($useGrep && ($this->contains || $this->notContains)) {
64169 $grep = $command->ins('grep');
64170 $this->buildContentFiltering($grep, $this->contains);
64171 $this->buildContentFiltering($grep, $this->notContains, true);
64172 }
64173
64174 if ($useSort) {
64175 $this->buildSorting($command, $this->sort);
64176 }
64177
64178 $command->setErrorHandler(
64179 $this->ignoreUnreadableDirs
64180
64181  ? function ($stderr) { }
64182 : function ($stderr) { throw new AccessDeniedException($stderr); }
64183 );
64184
64185 $paths = $this->shell->testCommand('uniq') ? $command->add('| uniq')->execute() : array_unique($command->execute());
64186 $iterator = new Iterator\FilePathsIterator($paths, $dir);
64187
64188 if ($this->exclude) {
64189 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
64190 }
64191
64192 if (!$useGrep && ($this->contains || $this->notContains)) {
64193 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
64194 }
64195
64196 if ($this->filters) {
64197 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
64198 }
64199
64200 if (!$useSort && $this->sort) {
64201 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
64202 $iterator = $iteratorAggregate->getIterator();
64203 }
64204
64205 return $iterator;
64206 }
64207
64208
64209
64210
64211 protected function canBeUsed()
64212 {
64213 return $this->shell->testCommand('find');
64214 }
64215
64216
64217
64218
64219
64220
64221
64222 protected function buildFindCommand(Command $command, $dir)
64223 {
64224 return $command
64225 ->ins('find')
64226 ->add('find ')
64227 ->arg($dir)
64228 ->add('-noleaf'); 
64229  }
64230
64231
64232
64233
64234
64235
64236 private function buildNamesFiltering(Command $command, array $names, $not = false)
64237 {
64238 if (0 === count($names)) {
64239 return;
64240 }
64241
64242 $command->add($not ? '-not' : null)->cmd('(');
64243
64244 foreach ($names as $i => $name) {
64245 $expr = Expression::create($name);
64246
64247
64248  if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
64249 $expr = Expression::create($expr->getGlob()->toRegex(false));
64250 }
64251
64252
64253  
64254  
64255  if ($expr->isRegex()) {
64256 $regex = $expr->getRegex();
64257 $regex->prepend($regex->hasStartFlag() ? '/' : '/[^/]*')
64258 ->setStartFlag(false)
64259 ->setStartJoker(true)
64260 ->replaceJokers('[^/]');
64261 if (!$regex->hasEndFlag() || $regex->hasEndJoker()) {
64262 $regex->setEndJoker(false)->append('[^/]*');
64263 }
64264 }
64265
64266 $command
64267 ->add($i > 0 ? '-or' : null)
64268 ->add($expr->isRegex()
64269 ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
64270 : ($expr->isCaseSensitive() ? '-name' : '-iname')
64271 )
64272 ->arg($expr->renderPattern());
64273 }
64274
64275 $command->cmd(')');
64276 }
64277
64278
64279
64280
64281
64282
64283
64284 private function buildPathsFiltering(Command $command, $dir, array $paths, $not = false)
64285 {
64286 if (0 === count($paths)) {
64287 return;
64288 }
64289
64290 $command->add($not ? '-not' : null)->cmd('(');
64291
64292 foreach ($paths as $i => $path) {
64293 $expr = Expression::create($path);
64294
64295
64296  if ($expr->isGlob() && $expr->getGlob()->isExpandable()) {
64297 $expr = Expression::create($expr->getGlob()->toRegex(false));
64298 }
64299
64300
64301  if ($expr->isRegex()) {
64302 $regex = $expr->getRegex();
64303 $regex->prepend($regex->hasStartFlag() ? preg_quote($dir).DIRECTORY_SEPARATOR : '.*')->setEndJoker(!$regex->hasEndFlag());
64304 } else {
64305 $expr->prepend('*')->append('*');
64306 }
64307
64308 $command
64309 ->add($i > 0 ? '-or' : null)
64310 ->add($expr->isRegex()
64311 ? ($expr->isCaseSensitive() ? '-regex' : '-iregex')
64312 : ($expr->isCaseSensitive() ? '-path' : '-ipath')
64313 )
64314 ->arg($expr->renderPattern());
64315 }
64316
64317 $command->cmd(')');
64318 }
64319
64320
64321
64322
64323
64324 private function buildSizesFiltering(Command $command, array $sizes)
64325 {
64326 foreach ($sizes as $i => $size) {
64327 $command->add($i > 0 ? '-and' : null);
64328
64329 switch ($size->getOperator()) {
64330 case '<=':
64331 $command->add('-size -'.($size->getTarget() + 1).'c');
64332 break;
64333 case '>=':
64334 $command->add('-size +'.($size->getTarget() - 1).'c');
64335 break;
64336 case '>':
64337 $command->add('-size +'.$size->getTarget().'c');
64338 break;
64339 case '!=':
64340 $command->add('-size -'.$size->getTarget().'c');
64341 $command->add('-size +'.$size->getTarget().'c');
64342 break;
64343 case '<':
64344 default:
64345 $command->add('-size -'.$size->getTarget().'c');
64346 }
64347 }
64348 }
64349
64350
64351
64352
64353
64354 private function buildDatesFiltering(Command $command, array $dates)
64355 {
64356 foreach ($dates as $i => $date) {
64357 $command->add($i > 0 ? '-and' : null);
64358
64359 $mins = (int) round((time() - $date->getTarget()) / 60);
64360
64361 if (0 > $mins) {
64362
64363  $command->add(' -mmin -0');
64364
64365  return;
64366 }
64367
64368 switch ($date->getOperator()) {
64369 case '<=':
64370 $command->add('-mmin +'.($mins - 1));
64371 break;
64372 case '>=':
64373 $command->add('-mmin -'.($mins + 1));
64374 break;
64375 case '>':
64376 $command->add('-mmin -'.$mins);
64377 break;
64378 case '!=':
64379 $command->add('-mmin +'.$mins.' -or -mmin -'.$mins);
64380 break;
64381 case '<':
64382 default:
64383 $command->add('-mmin +'.$mins);
64384 }
64385 }
64386 }
64387
64388
64389
64390
64391
64392
64393
64394 private function buildSorting(Command $command, $sort)
64395 {
64396 $this->buildFormatSorting($command, $sort);
64397 }
64398
64399
64400
64401
64402
64403 abstract protected function buildFormatSorting(Command $command, $sort);
64404
64405
64406
64407
64408
64409
64410 abstract protected function buildContentFiltering(Command $command, array $contains, $not = false);
64411 }
64412 <?php
64413
64414
64415
64416
64417
64418
64419
64420
64421
64422
64423 namespace Symfony\Component\Finder\Adapter;
64424
64425
64426
64427
64428
64429
64430 interface AdapterInterface
64431 {
64432
64433
64434
64435
64436
64437 public function setFollowLinks($followLinks);
64438
64439
64440
64441
64442
64443
64444 public function setMode($mode);
64445
64446
64447
64448
64449
64450
64451 public function setExclude(array $exclude);
64452
64453
64454
64455
64456
64457
64458 public function setDepths(array $depths);
64459
64460
64461
64462
64463
64464
64465 public function setNames(array $names);
64466
64467
64468
64469
64470
64471
64472 public function setNotNames(array $notNames);
64473
64474
64475
64476
64477
64478
64479 public function setContains(array $contains);
64480
64481
64482
64483
64484
64485
64486 public function setNotContains(array $notContains);
64487
64488
64489
64490
64491
64492
64493 public function setSizes(array $sizes);
64494
64495
64496
64497
64498
64499
64500 public function setDates(array $dates);
64501
64502
64503
64504
64505
64506
64507 public function setFilters(array $filters);
64508
64509
64510
64511
64512
64513
64514 public function setSort($sort);
64515
64516
64517
64518
64519
64520
64521 public function setPath(array $paths);
64522
64523
64524
64525
64526
64527
64528 public function setNotPath(array $notPaths);
64529
64530
64531
64532
64533
64534
64535 public function ignoreUnreadableDirs($ignore = true);
64536
64537
64538
64539
64540
64541
64542 public function searchInDirectory($dir);
64543
64544
64545
64546
64547
64548
64549 public function isSupported();
64550
64551
64552
64553
64554
64555
64556 public function getName();
64557 }
64558 <?php
64559
64560
64561
64562
64563
64564
64565
64566
64567
64568
64569 namespace Symfony\Component\Finder\Adapter;
64570
64571 @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);
64572
64573 use Symfony\Component\Finder\Shell\Shell;
64574 use Symfony\Component\Finder\Shell\Command;
64575 use Symfony\Component\Finder\Iterator\SortableIterator;
64576 use Symfony\Component\Finder\Expression\Expression;
64577
64578
64579
64580
64581
64582
64583
64584
64585 class BsdFindAdapter extends AbstractFindAdapter
64586 {
64587
64588
64589
64590 public function getName()
64591 {
64592 return 'bsd_find';
64593 }
64594
64595
64596
64597
64598 protected function canBeUsed()
64599 {
64600 return in_array($this->shell->getType(), array(Shell::TYPE_BSD, Shell::TYPE_DARWIN)) && parent::canBeUsed();
64601 }
64602
64603
64604
64605
64606 protected function buildFormatSorting(Command $command, $sort)
64607 {
64608 switch ($sort) {
64609 case SortableIterator::SORT_BY_NAME:
64610 $command->ins('sort')->add('| sort');
64611
64612 return;
64613 case SortableIterator::SORT_BY_TYPE:
64614 $format = '%HT';
64615 break;
64616 case SortableIterator::SORT_BY_ACCESSED_TIME:
64617 $format = '%a';
64618 break;
64619 case SortableIterator::SORT_BY_CHANGED_TIME:
64620 $format = '%c';
64621 break;
64622 case SortableIterator::SORT_BY_MODIFIED_TIME:
64623 $format = '%m';
64624 break;
64625 default:
64626 throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
64627 }
64628
64629 $command
64630 ->add('-print0 | xargs -0 stat -f')
64631 ->arg($format.'%t%N')
64632 ->add('| sort | cut -f 2');
64633 }
64634
64635
64636
64637
64638 protected function buildFindCommand(Command $command, $dir)
64639 {
64640 parent::buildFindCommand($command, $dir)->addAtIndex('-E', 1);
64641
64642 return $command;
64643 }
64644
64645
64646
64647
64648 protected function buildContentFiltering(Command $command, array $contains, $not = false)
64649 {
64650 foreach ($contains as $contain) {
64651 $expr = Expression::create($contain);
64652
64653
64654  $command
64655 ->add('| grep -v \'^$\'')
64656 ->add('| xargs -I{} grep -I')
64657 ->add($expr->isCaseSensitive() ? null : '-i')
64658 ->add($not ? '-L' : '-l')
64659 ->add('-Ee')->arg($expr->renderPattern())
64660 ->add('{}')
64661 ;
64662 }
64663 }
64664 }
64665 <?php
64666
64667
64668
64669
64670
64671
64672
64673
64674
64675
64676 namespace Symfony\Component\Finder\Adapter;
64677
64678 @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);
64679
64680 use Symfony\Component\Finder\Shell\Shell;
64681 use Symfony\Component\Finder\Shell\Command;
64682 use Symfony\Component\Finder\Iterator\SortableIterator;
64683 use Symfony\Component\Finder\Expression\Expression;
64684
64685
64686
64687
64688
64689
64690
64691
64692 class GnuFindAdapter extends AbstractFindAdapter
64693 {
64694
64695
64696
64697 public function getName()
64698 {
64699 return 'gnu_find';
64700 }
64701
64702
64703
64704
64705 protected function buildFormatSorting(Command $command, $sort)
64706 {
64707 switch ($sort) {
64708 case SortableIterator::SORT_BY_NAME:
64709 $command->ins('sort')->add('| sort');
64710
64711 return;
64712 case SortableIterator::SORT_BY_TYPE:
64713 $format = '%y';
64714 break;
64715 case SortableIterator::SORT_BY_ACCESSED_TIME:
64716 $format = '%A@';
64717 break;
64718 case SortableIterator::SORT_BY_CHANGED_TIME:
64719 $format = '%C@';
64720 break;
64721 case SortableIterator::SORT_BY_MODIFIED_TIME:
64722 $format = '%T@';
64723 break;
64724 default:
64725 throw new \InvalidArgumentException(sprintf('Unknown sort options: %s.', $sort));
64726 }
64727
64728 $command
64729 ->get('find')
64730 ->add('-printf')
64731 ->arg($format.' %h/%f\\n')
64732 ->add('| sort | cut')
64733 ->arg('-d ')
64734 ->arg('-f2-')
64735 ;
64736 }
64737
64738
64739
64740
64741 protected function canBeUsed()
64742 {
64743 return $this->shell->getType() === Shell::TYPE_UNIX && parent::canBeUsed();
64744 }
64745
64746
64747
64748
64749 protected function buildFindCommand(Command $command, $dir)
64750 {
64751 return parent::buildFindCommand($command, $dir)->add('-regextype posix-extended');
64752 }
64753
64754
64755
64756
64757 protected function buildContentFiltering(Command $command, array $contains, $not = false)
64758 {
64759 foreach ($contains as $contain) {
64760 $expr = Expression::create($contain);
64761
64762
64763  $command
64764 ->add('| xargs -I{} -r grep -I')
64765 ->add($expr->isCaseSensitive() ? null : '-i')
64766 ->add($not ? '-L' : '-l')
64767 ->add('-Ee')->arg($expr->renderPattern())
64768 ->add('{}')
64769 ;
64770 }
64771 }
64772 }
64773 <?php
64774
64775
64776
64777
64778
64779
64780
64781
64782
64783
64784 namespace Symfony\Component\Finder\Adapter;
64785
64786 @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);
64787
64788 use Symfony\Component\Finder\Iterator;
64789
64790
64791
64792
64793
64794
64795
64796
64797 class PhpAdapter extends AbstractAdapter
64798 {
64799
64800
64801
64802 public function searchInDirectory($dir)
64803 {
64804 $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
64805
64806 if ($this->followLinks) {
64807 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
64808 }
64809
64810 $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
64811
64812 if ($this->exclude) {
64813 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
64814 }
64815
64816 $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
64817
64818 if ($this->minDepth > 0 || $this->maxDepth < PHP_INT_MAX) {
64819 $iterator = new Iterator\DepthRangeFilterIterator($iterator, $this->minDepth, $this->maxDepth);
64820 }
64821
64822 if ($this->mode) {
64823 $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
64824 }
64825
64826 if ($this->names || $this->notNames) {
64827 $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
64828 }
64829
64830 if ($this->contains || $this->notContains) {
64831 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
64832 }
64833
64834 if ($this->sizes) {
64835 $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
64836 }
64837
64838 if ($this->dates) {
64839 $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
64840 }
64841
64842 if ($this->filters) {
64843 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
64844 }
64845
64846 if ($this->paths || $this->notPaths) {
64847 $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
64848 }
64849
64850 if ($this->sort) {
64851 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
64852 $iterator = $iteratorAggregate->getIterator();
64853 }
64854
64855 return $iterator;
64856 }
64857
64858
64859
64860
64861 public function getName()
64862 {
64863 return 'php';
64864 }
64865
64866
64867
64868
64869 protected function canBeUsed()
64870 {
64871 return true;
64872 }
64873 }
64874 <?php
64875
64876
64877
64878
64879
64880
64881
64882
64883
64884
64885 namespace Symfony\Component\Finder\Comparator;
64886
64887
64888
64889
64890
64891
64892 class Comparator
64893 {
64894 private $target;
64895 private $operator = '==';
64896
64897
64898
64899
64900
64901
64902 public function getTarget()
64903 {
64904 return $this->target;
64905 }
64906
64907
64908
64909
64910
64911
64912 public function setTarget($target)
64913 {
64914 $this->target = $target;
64915 }
64916
64917
64918
64919
64920
64921
64922 public function getOperator()
64923 {
64924 return $this->operator;
64925 }
64926
64927
64928
64929
64930
64931
64932
64933
64934 public function setOperator($operator)
64935 {
64936 if (!$operator) {
64937 $operator = '==';
64938 }
64939
64940 if (!in_array($operator, array('>', '<', '>=', '<=', '==', '!='))) {
64941 throw new \InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
64942 }
64943
64944 $this->operator = $operator;
64945 }
64946
64947
64948
64949
64950
64951
64952
64953
64954 public function test($test)
64955 {
64956 switch ($this->operator) {
64957 case '>':
64958 return $test > $this->target;
64959 case '>=':
64960 return $test >= $this->target;
64961 case '<':
64962 return $test < $this->target;
64963 case '<=':
64964 return $test <= $this->target;
64965 case '!=':
64966 return $test != $this->target;
64967 }
64968
64969 return $test == $this->target;
64970 }
64971 }
64972 <?php
64973
64974
64975
64976
64977
64978
64979
64980
64981
64982
64983 namespace Symfony\Component\Finder\Comparator;
64984
64985
64986
64987
64988
64989
64990 class DateComparator extends Comparator
64991 {
64992
64993
64994
64995
64996
64997
64998
64999 public function __construct($test)
65000 {
65001 if (!preg_match('#^\s*(==|!=|[<>]=?|after|since|before|until)?\s*(.+?)\s*$#i', $test, $matches)) {
65002 throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a date test.', $test));
65003 }
65004
65005 try {
65006 $date = new \DateTime($matches[2]);
65007 $target = $date->format('U');
65008 } catch (\Exception $e) {
65009 throw new \InvalidArgumentException(sprintf('"%s" is not a valid date.', $matches[2]));
65010 }
65011
65012 $operator = isset($matches[1]) ? $matches[1] : '==';
65013 if ('since' === $operator || 'after' === $operator) {
65014 $operator = '>';
65015 }
65016
65017 if ('until' === $operator || 'before' === $operator) {
65018 $operator = '<';
65019 }
65020
65021 $this->setOperator($operator);
65022 $this->setTarget($target);
65023 }
65024 }
65025 <?php
65026
65027
65028
65029
65030
65031
65032
65033
65034
65035
65036 namespace Symfony\Component\Finder\Comparator;
65037
65038
65039
65040
65041
65042
65043
65044
65045
65046
65047
65048
65049
65050
65051
65052
65053
65054
65055
65056
65057
65058
65059 class NumberComparator extends Comparator
65060 {
65061
65062
65063
65064
65065
65066
65067
65068 public function __construct($test)
65069 {
65070 if (!preg_match('#^\s*(==|!=|[<>]=?)?\s*([0-9\.]+)\s*([kmg]i?)?\s*$#i', $test, $matches)) {
65071 throw new \InvalidArgumentException(sprintf('Don\'t understand "%s" as a number test.', $test));
65072 }
65073
65074 $target = $matches[2];
65075 if (!is_numeric($target)) {
65076 throw new \InvalidArgumentException(sprintf('Invalid number "%s".', $target));
65077 }
65078 if (isset($matches[3])) {
65079
65080  switch (strtolower($matches[3])) {
65081 case 'k':
65082 $target *= 1000;
65083 break;
65084 case 'ki':
65085 $target *= 1024;
65086 break;
65087 case 'm':
65088 $target *= 1000000;
65089 break;
65090 case 'mi':
65091 $target *= 1024 * 1024;
65092 break;
65093 case 'g':
65094 $target *= 1000000000;
65095 break;
65096 case 'gi':
65097 $target *= 1024 * 1024 * 1024;
65098 break;
65099 }
65100 }
65101
65102 $this->setTarget($target);
65103 $this->setOperator(isset($matches[1]) ? $matches[1] : '==');
65104 }
65105 }
65106 <?php
65107
65108
65109
65110
65111
65112
65113
65114
65115
65116
65117 namespace Symfony\Component\Finder\Exception;
65118
65119
65120
65121
65122 class AccessDeniedException extends \UnexpectedValueException
65123 {
65124 }
65125 <?php
65126
65127
65128
65129
65130
65131
65132
65133
65134
65135
65136 namespace Symfony\Component\Finder\Exception;
65137
65138 @trigger_error('The '.__NAMESPACE__.'\AdapterFailureException class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65139
65140 use Symfony\Component\Finder\Adapter\AdapterInterface;
65141
65142
65143
65144
65145
65146
65147
65148
65149 class AdapterFailureException extends \RuntimeException implements ExceptionInterface
65150 {
65151
65152
65153
65154 private $adapter;
65155
65156
65157
65158
65159
65160
65161 public function __construct(AdapterInterface $adapter, $message = null, \Exception $previous = null)
65162 {
65163 $this->adapter = $adapter;
65164 parent::__construct($message ?: 'Search failed with "'.$adapter->getName().'" adapter.', $previous);
65165 }
65166
65167
65168
65169
65170 public function getAdapter()
65171 {
65172 return $this->adapter;
65173 }
65174 }
65175 <?php
65176
65177
65178
65179
65180
65181
65182
65183
65184
65185
65186 namespace Symfony\Component\Finder\Exception;
65187
65188
65189
65190
65191 interface ExceptionInterface
65192 {
65193
65194
65195
65196 public function getAdapter();
65197 }
65198 <?php
65199
65200
65201
65202
65203
65204
65205
65206
65207
65208
65209 namespace Symfony\Component\Finder\Exception;
65210
65211 @trigger_error('The '.__NAMESPACE__.'\OperationNotPermitedException class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65212
65213
65214
65215
65216
65217
65218 class OperationNotPermitedException extends AdapterFailureException
65219 {
65220 }
65221 <?php
65222
65223
65224
65225
65226
65227
65228
65229
65230
65231
65232 namespace Symfony\Component\Finder\Exception;
65233
65234 @trigger_error('The '.__NAMESPACE__.'\ShellCommandFailureException class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65235
65236 use Symfony\Component\Finder\Adapter\AdapterInterface;
65237 use Symfony\Component\Finder\Shell\Command;
65238
65239
65240
65241
65242
65243
65244 class ShellCommandFailureException extends AdapterFailureException
65245 {
65246
65247
65248
65249 private $command;
65250
65251
65252
65253
65254
65255
65256 public function __construct(AdapterInterface $adapter, Command $command, \Exception $previous = null)
65257 {
65258 $this->command = $command;
65259 parent::__construct($adapter, 'Shell command failed: "'.$command->join().'".', $previous);
65260 }
65261
65262
65263
65264
65265 public function getCommand()
65266 {
65267 return $this->command;
65268 }
65269 }
65270 <?php
65271
65272
65273
65274
65275
65276
65277
65278
65279
65280
65281 namespace Symfony\Component\Finder\Expression;
65282
65283 @trigger_error('The '.__NAMESPACE__.'\Expression class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65284
65285
65286
65287
65288 class Expression implements ValueInterface
65289 {
65290 const TYPE_REGEX = 1;
65291 const TYPE_GLOB = 2;
65292
65293
65294
65295
65296 private $value;
65297
65298
65299
65300
65301
65302
65303 public static function create($expr)
65304 {
65305 return new self($expr);
65306 }
65307
65308
65309
65310
65311 public function __construct($expr)
65312 {
65313 try {
65314 $this->value = Regex::create($expr);
65315 } catch (\InvalidArgumentException $e) {
65316 $this->value = new Glob($expr);
65317 }
65318 }
65319
65320
65321
65322
65323 public function __toString()
65324 {
65325 return $this->render();
65326 }
65327
65328
65329
65330
65331 public function render()
65332 {
65333 return $this->value->render();
65334 }
65335
65336
65337
65338
65339 public function renderPattern()
65340 {
65341 return $this->value->renderPattern();
65342 }
65343
65344
65345
65346
65347 public function isCaseSensitive()
65348 {
65349 return $this->value->isCaseSensitive();
65350 }
65351
65352
65353
65354
65355 public function getType()
65356 {
65357 return $this->value->getType();
65358 }
65359
65360
65361
65362
65363 public function prepend($expr)
65364 {
65365 $this->value->prepend($expr);
65366
65367 return $this;
65368 }
65369
65370
65371
65372
65373 public function append($expr)
65374 {
65375 $this->value->append($expr);
65376
65377 return $this;
65378 }
65379
65380
65381
65382
65383 public function isRegex()
65384 {
65385 return self::TYPE_REGEX === $this->value->getType();
65386 }
65387
65388
65389
65390
65391 public function isGlob()
65392 {
65393 return self::TYPE_GLOB === $this->value->getType();
65394 }
65395
65396
65397
65398
65399
65400
65401 public function getGlob()
65402 {
65403 if (self::TYPE_GLOB !== $this->value->getType()) {
65404 throw new \LogicException('Regex can\'t be transformed to glob.');
65405 }
65406
65407 return $this->value;
65408 }
65409
65410
65411
65412
65413 public function getRegex()
65414 {
65415 return self::TYPE_REGEX === $this->value->getType() ? $this->value : $this->value->toRegex();
65416 }
65417 }
65418 <?php
65419
65420
65421
65422
65423
65424
65425
65426
65427
65428
65429 namespace Symfony\Component\Finder\Expression;
65430
65431 @trigger_error('The '.__NAMESPACE__.'\Glob class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65432
65433 use Symfony\Component\Finder\Glob as FinderGlob;
65434
65435
65436
65437
65438 class Glob implements ValueInterface
65439 {
65440
65441
65442
65443 private $pattern;
65444
65445
65446
65447
65448 public function __construct($pattern)
65449 {
65450 $this->pattern = $pattern;
65451 }
65452
65453
65454
65455
65456 public function render()
65457 {
65458 return $this->pattern;
65459 }
65460
65461
65462
65463
65464 public function renderPattern()
65465 {
65466 return $this->pattern;
65467 }
65468
65469
65470
65471
65472 public function getType()
65473 {
65474 return Expression::TYPE_GLOB;
65475 }
65476
65477
65478
65479
65480 public function isCaseSensitive()
65481 {
65482 return true;
65483 }
65484
65485
65486
65487
65488 public function prepend($expr)
65489 {
65490 $this->pattern = $expr.$this->pattern;
65491
65492 return $this;
65493 }
65494
65495
65496
65497
65498 public function append($expr)
65499 {
65500 $this->pattern .= $expr;
65501
65502 return $this;
65503 }
65504
65505
65506
65507
65508
65509
65510 public function isExpandable()
65511 {
65512 return false !== strpos($this->pattern, '{')
65513 && false !== strpos($this->pattern, '}');
65514 }
65515
65516
65517
65518
65519
65520
65521
65522 public function toRegex($strictLeadingDot = true, $strictWildcardSlash = true)
65523 {
65524 $regex = FinderGlob::toRegex($this->pattern, $strictLeadingDot, $strictWildcardSlash, '');
65525
65526 return new Regex($regex);
65527 }
65528 }
65529 <?php
65530
65531
65532
65533
65534
65535
65536
65537
65538
65539
65540 namespace Symfony\Component\Finder\Expression;
65541
65542 @trigger_error('The '.__NAMESPACE__.'\Regex class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65543
65544
65545
65546
65547 class Regex implements ValueInterface
65548 {
65549 const START_FLAG = '^';
65550 const END_FLAG = '$';
65551 const BOUNDARY = '~';
65552 const JOKER = '.*';
65553 const ESCAPING = '\\';
65554
65555
65556
65557
65558 private $pattern;
65559
65560
65561
65562
65563 private $options;
65564
65565
65566
65567
65568 private $startFlag;
65569
65570
65571
65572
65573 private $endFlag;
65574
65575
65576
65577
65578 private $startJoker;
65579
65580
65581
65582
65583 private $endJoker;
65584
65585
65586
65587
65588
65589
65590
65591
65592 public static function create($expr)
65593 {
65594 if (preg_match('/^(.{3,}?)([imsxuADU]*)$/', $expr, $m)) {
65595 $start = substr($m[1], 0, 1);
65596 $end = substr($m[1], -1);
65597
65598 if (
65599 ($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start))
65600 || ($start === '{' && $end === '}')
65601 || ($start === '(' && $end === ')')
65602 ) {
65603 return new self(substr($m[1], 1, -1), $m[2], $end);
65604 }
65605 }
65606
65607 throw new \InvalidArgumentException('Given expression is not a regex.');
65608 }
65609
65610
65611
65612
65613
65614
65615 public function __construct($pattern, $options = '', $delimiter = null)
65616 {
65617 if (null !== $delimiter) {
65618
65619  $pattern = str_replace('\\'.$delimiter, $delimiter, $pattern);
65620 }
65621
65622 $this->parsePattern($pattern);
65623 $this->options = $options;
65624 }
65625
65626
65627
65628
65629 public function __toString()
65630 {
65631 return $this->render();
65632 }
65633
65634
65635
65636
65637 public function render()
65638 {
65639 return self::BOUNDARY
65640 .$this->renderPattern()
65641 .self::BOUNDARY
65642 .$this->options;
65643 }
65644
65645
65646
65647
65648 public function renderPattern()
65649 {
65650 return ($this->startFlag ? self::START_FLAG : '')
65651 .($this->startJoker ? self::JOKER : '')
65652 .str_replace(self::BOUNDARY, '\\'.self::BOUNDARY, $this->pattern)
65653 .($this->endJoker ? self::JOKER : '')
65654 .($this->endFlag ? self::END_FLAG : '');
65655 }
65656
65657
65658
65659
65660 public function isCaseSensitive()
65661 {
65662 return !$this->hasOption('i');
65663 }
65664
65665
65666
65667
65668 public function getType()
65669 {
65670 return Expression::TYPE_REGEX;
65671 }
65672
65673
65674
65675
65676 public function prepend($expr)
65677 {
65678 $this->pattern = $expr.$this->pattern;
65679
65680 return $this;
65681 }
65682
65683
65684
65685
65686 public function append($expr)
65687 {
65688 $this->pattern .= $expr;
65689
65690 return $this;
65691 }
65692
65693
65694
65695
65696
65697
65698 public function hasOption($option)
65699 {
65700 return false !== strpos($this->options, $option);
65701 }
65702
65703
65704
65705
65706
65707
65708 public function addOption($option)
65709 {
65710 if (!$this->hasOption($option)) {
65711 $this->options .= $option;
65712 }
65713
65714 return $this;
65715 }
65716
65717
65718
65719
65720
65721
65722 public function removeOption($option)
65723 {
65724 $this->options = str_replace($option, '', $this->options);
65725
65726 return $this;
65727 }
65728
65729
65730
65731
65732
65733
65734 public function setStartFlag($startFlag)
65735 {
65736 $this->startFlag = $startFlag;
65737
65738 return $this;
65739 }
65740
65741
65742
65743
65744 public function hasStartFlag()
65745 {
65746 return $this->startFlag;
65747 }
65748
65749
65750
65751
65752
65753
65754 public function setEndFlag($endFlag)
65755 {
65756 $this->endFlag = (bool) $endFlag;
65757
65758 return $this;
65759 }
65760
65761
65762
65763
65764 public function hasEndFlag()
65765 {
65766 return $this->endFlag;
65767 }
65768
65769
65770
65771
65772
65773
65774 public function setStartJoker($startJoker)
65775 {
65776 $this->startJoker = $startJoker;
65777
65778 return $this;
65779 }
65780
65781
65782
65783
65784 public function hasStartJoker()
65785 {
65786 return $this->startJoker;
65787 }
65788
65789
65790
65791
65792
65793
65794 public function setEndJoker($endJoker)
65795 {
65796 $this->endJoker = (bool) $endJoker;
65797
65798 return $this;
65799 }
65800
65801
65802
65803
65804 public function hasEndJoker()
65805 {
65806 return $this->endJoker;
65807 }
65808
65809
65810
65811
65812
65813
65814 public function replaceJokers($replacement)
65815 {
65816 $replace = function ($subject) use ($replacement) {
65817 $subject = $subject[0];
65818 $replace = 0 === substr_count($subject, '\\') % 2;
65819
65820 return $replace ? str_replace('.', $replacement, $subject) : $subject;
65821 };
65822
65823 $this->pattern = preg_replace_callback('~[\\\\]*\\.~', $replace, $this->pattern);
65824
65825 return $this;
65826 }
65827
65828
65829
65830
65831 private function parsePattern($pattern)
65832 {
65833 if ($this->startFlag = self::START_FLAG === substr($pattern, 0, 1)) {
65834 $pattern = substr($pattern, 1);
65835 }
65836
65837 if ($this->startJoker = self::JOKER === substr($pattern, 0, 2)) {
65838 $pattern = substr($pattern, 2);
65839 }
65840
65841 if ($this->endFlag = (self::END_FLAG === substr($pattern, -1) && self::ESCAPING !== substr($pattern, -2, -1))) {
65842 $pattern = substr($pattern, 0, -1);
65843 }
65844
65845 if ($this->endJoker = (self::JOKER === substr($pattern, -2) && self::ESCAPING !== substr($pattern, -3, -2))) {
65846 $pattern = substr($pattern, 0, -2);
65847 }
65848
65849 $this->pattern = $pattern;
65850 }
65851 }
65852 <?php
65853
65854
65855
65856
65857
65858
65859
65860
65861
65862
65863 namespace Symfony\Component\Finder\Expression;
65864
65865 @trigger_error('The '.__NAMESPACE__.'\ValueInterface interface is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
65866
65867
65868
65869
65870 interface ValueInterface
65871 {
65872
65873
65874
65875
65876
65877 public function render();
65878
65879
65880
65881
65882
65883
65884 public function renderPattern();
65885
65886
65887
65888
65889
65890
65891 public function isCaseSensitive();
65892
65893
65894
65895
65896
65897
65898 public function getType();
65899
65900
65901
65902
65903
65904
65905 public function prepend($expr);
65906
65907
65908
65909
65910
65911
65912 public function append($expr);
65913 }
65914 <?php
65915
65916
65917
65918
65919
65920
65921
65922
65923
65924
65925 namespace Symfony\Component\Finder;
65926
65927 use Symfony\Component\Finder\Adapter\AdapterInterface;
65928 use Symfony\Component\Finder\Adapter\GnuFindAdapter;
65929 use Symfony\Component\Finder\Adapter\BsdFindAdapter;
65930 use Symfony\Component\Finder\Adapter\PhpAdapter;
65931 use Symfony\Component\Finder\Comparator\DateComparator;
65932 use Symfony\Component\Finder\Comparator\NumberComparator;
65933 use Symfony\Component\Finder\Exception\ExceptionInterface;
65934 use Symfony\Component\Finder\Iterator\CustomFilterIterator;
65935 use Symfony\Component\Finder\Iterator\DateRangeFilterIterator;
65936 use Symfony\Component\Finder\Iterator\DepthRangeFilterIterator;
65937 use Symfony\Component\Finder\Iterator\ExcludeDirectoryFilterIterator;
65938 use Symfony\Component\Finder\Iterator\FilecontentFilterIterator;
65939 use Symfony\Component\Finder\Iterator\FilenameFilterIterator;
65940 use Symfony\Component\Finder\Iterator\SizeRangeFilterIterator;
65941 use Symfony\Component\Finder\Iterator\SortableIterator;
65942
65943
65944
65945
65946
65947
65948
65949
65950
65951
65952
65953
65954
65955
65956 class Finder implements \IteratorAggregate, \Countable
65957 {
65958 const IGNORE_VCS_FILES = 1;
65959 const IGNORE_DOT_FILES = 2;
65960
65961 private $mode = 0;
65962 private $names = array();
65963 private $notNames = array();
65964 private $exclude = array();
65965 private $filters = array();
65966 private $depths = array();
65967 private $sizes = array();
65968 private $followLinks = false;
65969 private $sort = false;
65970 private $ignore = 0;
65971 private $dirs = array();
65972 private $dates = array();
65973 private $iterators = array();
65974 private $contains = array();
65975 private $notContains = array();
65976 private $adapters = null;
65977 private $paths = array();
65978 private $notPaths = array();
65979 private $ignoreUnreadableDirs = false;
65980
65981 private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg');
65982
65983
65984
65985
65986 public function __construct()
65987 {
65988 $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES;
65989 }
65990
65991
65992
65993
65994
65995
65996 public static function create()
65997 {
65998 return new static();
65999 }
66000
66001
66002
66003
66004
66005
66006
66007
66008
66009
66010
66011 public function addAdapter(AdapterInterface $adapter, $priority = 0)
66012 {
66013 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66014
66015 $this->initDefaultAdapters();
66016
66017 $this->adapters[$adapter->getName()] = array(
66018 'adapter' => $adapter,
66019 'priority' => $priority,
66020 'selected' => false,
66021 );
66022
66023 return $this->sortAdapters();
66024 }
66025
66026
66027
66028
66029
66030
66031
66032
66033 public function useBestAdapter()
66034 {
66035 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66036
66037 $this->initDefaultAdapters();
66038
66039 $this->resetAdapterSelection();
66040
66041 return $this->sortAdapters();
66042 }
66043
66044
66045
66046
66047
66048
66049
66050
66051
66052
66053
66054
66055 public function setAdapter($name)
66056 {
66057 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66058
66059 $this->initDefaultAdapters();
66060
66061 if (!isset($this->adapters[$name])) {
66062 throw new \InvalidArgumentException(sprintf('Adapter "%s" does not exist.', $name));
66063 }
66064
66065 $this->resetAdapterSelection();
66066 $this->adapters[$name]['selected'] = true;
66067
66068 return $this->sortAdapters();
66069 }
66070
66071
66072
66073
66074
66075
66076
66077
66078 public function removeAdapters()
66079 {
66080 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66081
66082 $this->adapters = array();
66083
66084 return $this;
66085 }
66086
66087
66088
66089
66090
66091
66092
66093
66094 public function getAdapters()
66095 {
66096 @trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
66097
66098 $this->initDefaultAdapters();
66099
66100 return array_values(array_map(function (array $adapter) {
66101 return $adapter['adapter'];
66102 }, $this->adapters));
66103 }
66104
66105
66106
66107
66108
66109
66110 public function directories()
66111 {
66112 $this->mode = Iterator\FileTypeFilterIterator::ONLY_DIRECTORIES;
66113
66114 return $this;
66115 }
66116
66117
66118
66119
66120
66121
66122 public function files()
66123 {
66124 $this->mode = Iterator\FileTypeFilterIterator::ONLY_FILES;
66125
66126 return $this;
66127 }
66128
66129
66130
66131
66132
66133
66134
66135
66136
66137
66138
66139
66140
66141
66142
66143
66144 public function depth($level)
66145 {
66146 $this->depths[] = new Comparator\NumberComparator($level);
66147
66148 return $this;
66149 }
66150
66151
66152
66153
66154
66155
66156
66157
66158
66159
66160
66161
66162
66163
66164
66165
66166
66167
66168
66169 public function date($date)
66170 {
66171 $this->dates[] = new Comparator\DateComparator($date);
66172
66173 return $this;
66174 }
66175
66176
66177
66178
66179
66180
66181
66182
66183
66184
66185
66186
66187
66188
66189
66190
66191 public function name($pattern)
66192 {
66193 $this->names[] = $pattern;
66194
66195 return $this;
66196 }
66197
66198
66199
66200
66201
66202
66203
66204
66205
66206
66207 public function notName($pattern)
66208 {
66209 $this->notNames[] = $pattern;
66210
66211 return $this;
66212 }
66213
66214
66215
66216
66217
66218
66219
66220
66221
66222
66223
66224
66225
66226
66227
66228 public function contains($pattern)
66229 {
66230 $this->contains[] = $pattern;
66231
66232 return $this;
66233 }
66234
66235
66236
66237
66238
66239
66240
66241
66242
66243
66244
66245
66246
66247
66248
66249 public function notContains($pattern)
66250 {
66251 $this->notContains[] = $pattern;
66252
66253 return $this;
66254 }
66255
66256
66257
66258
66259
66260
66261
66262
66263
66264
66265
66266
66267
66268
66269
66270
66271
66272 public function path($pattern)
66273 {
66274 $this->paths[] = $pattern;
66275
66276 return $this;
66277 }
66278
66279
66280
66281
66282
66283
66284
66285
66286
66287
66288
66289
66290
66291
66292
66293
66294
66295 public function notPath($pattern)
66296 {
66297 $this->notPaths[] = $pattern;
66298
66299 return $this;
66300 }
66301
66302
66303
66304
66305
66306
66307
66308
66309
66310
66311
66312
66313
66314
66315
66316 public function size($size)
66317 {
66318 $this->sizes[] = new Comparator\NumberComparator($size);
66319
66320 return $this;
66321 }
66322
66323
66324
66325
66326
66327
66328
66329
66330
66331
66332 public function exclude($dirs)
66333 {
66334 $this->exclude = array_merge($this->exclude, (array) $dirs);
66335
66336 return $this;
66337 }
66338
66339
66340
66341
66342
66343
66344
66345
66346
66347
66348 public function ignoreDotFiles($ignoreDotFiles)
66349 {
66350 if ($ignoreDotFiles) {
66351 $this->ignore |= static::IGNORE_DOT_FILES;
66352 } else {
66353 $this->ignore &= ~static::IGNORE_DOT_FILES;
66354 }
66355
66356 return $this;
66357 }
66358
66359
66360
66361
66362
66363
66364
66365
66366
66367
66368 public function ignoreVCS($ignoreVCS)
66369 {
66370 if ($ignoreVCS) {
66371 $this->ignore |= static::IGNORE_VCS_FILES;
66372 } else {
66373 $this->ignore &= ~static::IGNORE_VCS_FILES;
66374 }
66375
66376 return $this;
66377 }
66378
66379
66380
66381
66382
66383
66384
66385
66386 public static function addVCSPattern($pattern)
66387 {
66388 foreach ((array) $pattern as $p) {
66389 self::$vcsPatterns[] = $p;
66390 }
66391
66392 self::$vcsPatterns = array_unique(self::$vcsPatterns);
66393 }
66394
66395
66396
66397
66398
66399
66400
66401
66402
66403
66404
66405
66406
66407
66408 public function sort(\Closure $closure)
66409 {
66410 $this->sort = $closure;
66411
66412 return $this;
66413 }
66414
66415
66416
66417
66418
66419
66420
66421
66422
66423
66424 public function sortByName()
66425 {
66426 $this->sort = Iterator\SortableIterator::SORT_BY_NAME;
66427
66428 return $this;
66429 }
66430
66431
66432
66433
66434
66435
66436
66437
66438
66439
66440 public function sortByType()
66441 {
66442 $this->sort = Iterator\SortableIterator::SORT_BY_TYPE;
66443
66444 return $this;
66445 }
66446
66447
66448
66449
66450
66451
66452
66453
66454
66455
66456
66457
66458 public function sortByAccessedTime()
66459 {
66460 $this->sort = Iterator\SortableIterator::SORT_BY_ACCESSED_TIME;
66461
66462 return $this;
66463 }
66464
66465
66466
66467
66468
66469
66470
66471
66472
66473
66474
66475
66476
66477
66478 public function sortByChangedTime()
66479 {
66480 $this->sort = Iterator\SortableIterator::SORT_BY_CHANGED_TIME;
66481
66482 return $this;
66483 }
66484
66485
66486
66487
66488
66489
66490
66491
66492
66493
66494
66495
66496 public function sortByModifiedTime()
66497 {
66498 $this->sort = Iterator\SortableIterator::SORT_BY_MODIFIED_TIME;
66499
66500 return $this;
66501 }
66502
66503
66504
66505
66506
66507
66508
66509
66510
66511
66512
66513
66514
66515 public function filter(\Closure $closure)
66516 {
66517 $this->filters[] = $closure;
66518
66519 return $this;
66520 }
66521
66522
66523
66524
66525
66526
66527 public function followLinks()
66528 {
66529 $this->followLinks = true;
66530
66531 return $this;
66532 }
66533
66534
66535
66536
66537
66538
66539
66540
66541
66542
66543 public function ignoreUnreadableDirs($ignore = true)
66544 {
66545 $this->ignoreUnreadableDirs = (bool) $ignore;
66546
66547 return $this;
66548 }
66549
66550
66551
66552
66553
66554
66555
66556
66557
66558
66559 public function in($dirs)
66560 {
66561 $resolvedDirs = array();
66562
66563 foreach ((array) $dirs as $dir) {
66564 if (is_dir($dir)) {
66565 $resolvedDirs[] = $dir;
66566 } elseif ($glob = glob($dir, (defined('GLOB_BRACE') ? GLOB_BRACE : 0) | GLOB_ONLYDIR)) {
66567 $resolvedDirs = array_merge($resolvedDirs, $glob);
66568 } else {
66569 throw new \InvalidArgumentException(sprintf('The "%s" directory does not exist.', $dir));
66570 }
66571 }
66572
66573 $this->dirs = array_merge($this->dirs, $resolvedDirs);
66574
66575 return $this;
66576 }
66577
66578
66579
66580
66581
66582
66583
66584
66585
66586
66587 public function getIterator()
66588 {
66589 if (0 === count($this->dirs) && 0 === count($this->iterators)) {
66590 throw new \LogicException('You must call one of in() or append() methods before iterating over a Finder.');
66591 }
66592
66593 if (1 === count($this->dirs) && 0 === count($this->iterators)) {
66594 return $this->searchInDirectory($this->dirs[0]);
66595 }
66596
66597 $iterator = new \AppendIterator();
66598 foreach ($this->dirs as $dir) {
66599 $iterator->append($this->searchInDirectory($dir));
66600 }
66601
66602 foreach ($this->iterators as $it) {
66603 $iterator->append($it);
66604 }
66605
66606 return $iterator;
66607 }
66608
66609
66610
66611
66612
66613
66614
66615
66616
66617
66618
66619
66620 public function append($iterator)
66621 {
66622 if ($iterator instanceof \IteratorAggregate) {
66623 $this->iterators[] = $iterator->getIterator();
66624 } elseif ($iterator instanceof \Iterator) {
66625 $this->iterators[] = $iterator;
66626 } elseif ($iterator instanceof \Traversable || is_array($iterator)) {
66627 $it = new \ArrayIterator();
66628 foreach ($iterator as $file) {
66629 $it->append($file instanceof \SplFileInfo ? $file : new \SplFileInfo($file));
66630 }
66631 $this->iterators[] = $it;
66632 } else {
66633 throw new \InvalidArgumentException('Finder::append() method wrong argument type.');
66634 }
66635
66636 return $this;
66637 }
66638
66639
66640
66641
66642
66643
66644 public function count()
66645 {
66646 return iterator_count($this->getIterator());
66647 }
66648
66649
66650
66651
66652 private function sortAdapters()
66653 {
66654 uasort($this->adapters, function (array $a, array $b) {
66655 if ($a['selected'] || $b['selected']) {
66656 return $a['selected'] ? -1 : 1;
66657 }
66658
66659 return $a['priority'] > $b['priority'] ? -1 : 1;
66660 });
66661
66662 return $this;
66663 }
66664
66665
66666
66667
66668
66669
66670 private function searchInDirectory($dir)
66671 {
66672 if (static::IGNORE_VCS_FILES === (static::IGNORE_VCS_FILES & $this->ignore)) {
66673 $this->exclude = array_merge($this->exclude, self::$vcsPatterns);
66674 }
66675
66676 if (static::IGNORE_DOT_FILES === (static::IGNORE_DOT_FILES & $this->ignore)) {
66677 $this->notPaths[] = '#(^|/)\..+(/|$)#';
66678 }
66679
66680 if ($this->adapters) {
66681 foreach ($this->adapters as $adapter) {
66682 if ($adapter['adapter']->isSupported()) {
66683 try {
66684 return $this
66685 ->buildAdapter($adapter['adapter'])
66686 ->searchInDirectory($dir);
66687 } catch (ExceptionInterface $e) {
66688 }
66689 }
66690 }
66691 }
66692
66693 $minDepth = 0;
66694 $maxDepth = PHP_INT_MAX;
66695
66696 foreach ($this->depths as $comparator) {
66697 switch ($comparator->getOperator()) {
66698 case '>':
66699 $minDepth = $comparator->getTarget() + 1;
66700 break;
66701 case '>=':
66702 $minDepth = $comparator->getTarget();
66703 break;
66704 case '<':
66705 $maxDepth = $comparator->getTarget() - 1;
66706 break;
66707 case '<=':
66708 $maxDepth = $comparator->getTarget();
66709 break;
66710 default:
66711 $minDepth = $maxDepth = $comparator->getTarget();
66712 }
66713 }
66714
66715 $flags = \RecursiveDirectoryIterator::SKIP_DOTS;
66716
66717 if ($this->followLinks) {
66718 $flags |= \RecursiveDirectoryIterator::FOLLOW_SYMLINKS;
66719 }
66720
66721 $iterator = new Iterator\RecursiveDirectoryIterator($dir, $flags, $this->ignoreUnreadableDirs);
66722
66723 if ($this->exclude) {
66724 $iterator = new Iterator\ExcludeDirectoryFilterIterator($iterator, $this->exclude);
66725 }
66726
66727 $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
66728
66729 if ($minDepth > 0 || $maxDepth < PHP_INT_MAX) {
66730 $iterator = new Iterator\DepthRangeFilterIterator($iterator, $minDepth, $maxDepth);
66731 }
66732
66733 if ($this->mode) {
66734 $iterator = new Iterator\FileTypeFilterIterator($iterator, $this->mode);
66735 }
66736
66737 if ($this->names || $this->notNames) {
66738 $iterator = new Iterator\FilenameFilterIterator($iterator, $this->names, $this->notNames);
66739 }
66740
66741 if ($this->contains || $this->notContains) {
66742 $iterator = new Iterator\FilecontentFilterIterator($iterator, $this->contains, $this->notContains);
66743 }
66744
66745 if ($this->sizes) {
66746 $iterator = new Iterator\SizeRangeFilterIterator($iterator, $this->sizes);
66747 }
66748
66749 if ($this->dates) {
66750 $iterator = new Iterator\DateRangeFilterIterator($iterator, $this->dates);
66751 }
66752
66753 if ($this->filters) {
66754 $iterator = new Iterator\CustomFilterIterator($iterator, $this->filters);
66755 }
66756
66757 if ($this->paths || $this->notPaths) {
66758 $iterator = new Iterator\PathFilterIterator($iterator, $this->paths, $this->notPaths);
66759 }
66760
66761 if ($this->sort) {
66762 $iteratorAggregate = new Iterator\SortableIterator($iterator, $this->sort);
66763 $iterator = $iteratorAggregate->getIterator();
66764 }
66765
66766 return $iterator;
66767 }
66768
66769
66770
66771
66772
66773
66774 private function buildAdapter(AdapterInterface $adapter)
66775 {
66776 return $adapter
66777 ->setFollowLinks($this->followLinks)
66778 ->setDepths($this->depths)
66779 ->setMode($this->mode)
66780 ->setExclude($this->exclude)
66781 ->setNames($this->names)
66782 ->setNotNames($this->notNames)
66783 ->setContains($this->contains)
66784 ->setNotContains($this->notContains)
66785 ->setSizes($this->sizes)
66786 ->setDates($this->dates)
66787 ->setFilters($this->filters)
66788 ->setSort($this->sort)
66789 ->setPath($this->paths)
66790 ->setNotPath($this->notPaths)
66791 ->ignoreUnreadableDirs($this->ignoreUnreadableDirs);
66792 }
66793
66794
66795
66796
66797 private function resetAdapterSelection()
66798 {
66799 $this->adapters = array_map(function (array $properties) {
66800 $properties['selected'] = false;
66801
66802 return $properties;
66803 }, $this->adapters);
66804 }
66805
66806 private function initDefaultAdapters()
66807 {
66808 if (null === $this->adapters) {
66809 $this->adapters = array();
66810 $this
66811 ->addAdapter(new GnuFindAdapter())
66812 ->addAdapter(new BsdFindAdapter())
66813 ->addAdapter(new PhpAdapter(), -50)
66814 ->setAdapter('php')
66815 ;
66816 }
66817 }
66818 }
66819 <?php
66820
66821
66822
66823
66824
66825
66826
66827
66828
66829
66830 namespace Symfony\Component\Finder;
66831
66832
66833
66834
66835
66836
66837
66838
66839
66840
66841
66842
66843
66844
66845
66846
66847
66848
66849
66850
66851
66852
66853
66854 class Glob
66855 {
66856
66857
66858
66859
66860
66861
66862
66863
66864
66865
66866 public static function toRegex($glob, $strictLeadingDot = true, $strictWildcardSlash = true, $delimiter = '#')
66867 {
66868 $firstByte = true;
66869 $escaping = false;
66870 $inCurlies = 0;
66871 $regex = '';
66872 $sizeGlob = strlen($glob);
66873 for ($i = 0; $i < $sizeGlob; ++$i) {
66874 $car = $glob[$i];
66875 if ($firstByte) {
66876 if ($strictLeadingDot && '.' !== $car) {
66877 $regex .= '(?=[^\.])';
66878 }
66879
66880 $firstByte = false;
66881 }
66882
66883 if ('/' === $car) {
66884 $firstByte = true;
66885 }
66886
66887 if ($delimiter === $car || '.' === $car || '(' === $car || ')' === $car || '|' === $car || '+' === $car || '^' === $car || '$' === $car) {
66888 $regex .= "\\$car";
66889 } elseif ('*' === $car) {
66890 $regex .= $escaping ? '\\*' : ($strictWildcardSlash ? '[^/]*' : '.*');
66891 } elseif ('?' === $car) {
66892 $regex .= $escaping ? '\\?' : ($strictWildcardSlash ? '[^/]' : '.');
66893 } elseif ('{' === $car) {
66894 $regex .= $escaping ? '\\{' : '(';
66895 if (!$escaping) {
66896 ++$inCurlies;
66897 }
66898 } elseif ('}' === $car && $inCurlies) {
66899 $regex .= $escaping ? '}' : ')';
66900 if (!$escaping) {
66901 --$inCurlies;
66902 }
66903 } elseif (',' === $car && $inCurlies) {
66904 $regex .= $escaping ? ',' : '|';
66905 } elseif ('\\' === $car) {
66906 if ($escaping) {
66907 $regex .= '\\\\';
66908 $escaping = false;
66909 } else {
66910 $escaping = true;
66911 }
66912
66913 continue;
66914 } else {
66915 $regex .= $car;
66916 }
66917 $escaping = false;
66918 }
66919
66920 return $delimiter.'^'.$regex.'$'.$delimiter;
66921 }
66922 }
66923 <?php
66924
66925
66926
66927
66928
66929
66930
66931
66932
66933
66934 namespace Symfony\Component\Finder\Iterator;
66935
66936
66937
66938
66939
66940
66941
66942
66943
66944 class CustomFilterIterator extends FilterIterator
66945 {
66946 private $filters = array();
66947
66948
66949
66950
66951
66952
66953
66954
66955
66956 public function __construct(\Iterator $iterator, array $filters)
66957 {
66958 foreach ($filters as $filter) {
66959 if (!is_callable($filter)) {
66960 throw new \InvalidArgumentException('Invalid PHP callback.');
66961 }
66962 }
66963 $this->filters = $filters;
66964
66965 parent::__construct($iterator);
66966 }
66967
66968
66969
66970
66971
66972
66973 public function accept()
66974 {
66975 $fileinfo = $this->current();
66976
66977 foreach ($this->filters as $filter) {
66978 if (false === call_user_func($filter, $fileinfo)) {
66979 return false;
66980 }
66981 }
66982
66983 return true;
66984 }
66985 }
66986 <?php
66987
66988
66989
66990
66991
66992
66993
66994
66995
66996
66997 namespace Symfony\Component\Finder\Iterator;
66998
66999 use Symfony\Component\Finder\Comparator\DateComparator;
67000
67001
67002
67003
67004
67005
67006 class DateRangeFilterIterator extends FilterIterator
67007 {
67008 private $comparators = array();
67009
67010
67011
67012
67013
67014
67015
67016 public function __construct(\Iterator $iterator, array $comparators)
67017 {
67018 $this->comparators = $comparators;
67019
67020 parent::__construct($iterator);
67021 }
67022
67023
67024
67025
67026
67027
67028 public function accept()
67029 {
67030 $fileinfo = $this->current();
67031
67032 if (!file_exists($fileinfo->getPathname())) {
67033 return false;
67034 }
67035
67036 $filedate = $fileinfo->getMTime();
67037 foreach ($this->comparators as $compare) {
67038 if (!$compare->test($filedate)) {
67039 return false;
67040 }
67041 }
67042
67043 return true;
67044 }
67045 }
67046 <?php
67047
67048
67049
67050
67051
67052
67053
67054
67055
67056
67057 namespace Symfony\Component\Finder\Iterator;
67058
67059
67060
67061
67062
67063
67064 class DepthRangeFilterIterator extends FilterIterator
67065 {
67066 private $minDepth = 0;
67067
67068
67069
67070
67071
67072
67073
67074
67075 public function __construct(\RecursiveIteratorIterator $iterator, $minDepth = 0, $maxDepth = PHP_INT_MAX)
67076 {
67077 $this->minDepth = $minDepth;
67078 $iterator->setMaxDepth(PHP_INT_MAX === $maxDepth ? -1 : $maxDepth);
67079
67080 parent::__construct($iterator);
67081 }
67082
67083
67084
67085
67086
67087
67088 public function accept()
67089 {
67090 return $this->getInnerIterator()->getDepth() >= $this->minDepth;
67091 }
67092 }
67093 <?php
67094
67095
67096
67097
67098
67099
67100
67101
67102
67103
67104 namespace Symfony\Component\Finder\Iterator;
67105
67106
67107
67108
67109
67110
67111 class ExcludeDirectoryFilterIterator extends FilterIterator implements \RecursiveIterator
67112 {
67113 private $iterator;
67114 private $isRecursive;
67115 private $excludedDirs = array();
67116 private $excludedPattern;
67117
67118
67119
67120
67121
67122
67123
67124 public function __construct(\Iterator $iterator, array $directories)
67125 {
67126 $this->iterator = $iterator;
67127 $this->isRecursive = $iterator instanceof \RecursiveIterator;
67128 $patterns = array();
67129 foreach ($directories as $directory) {
67130 $directory = rtrim($directory, '/');
67131 if (!$this->isRecursive || false !== strpos($directory, '/')) {
67132 $patterns[] = preg_quote($directory, '#');
67133 } else {
67134 $this->excludedDirs[$directory] = true;
67135 }
67136 }
67137 if ($patterns) {
67138 $this->excludedPattern = '#(?:^|/)(?:'.implode('|', $patterns).')(?:/|$)#';
67139 }
67140
67141 parent::__construct($iterator);
67142 }
67143
67144
67145
67146
67147
67148
67149 public function accept()
67150 {
67151 if ($this->isRecursive && isset($this->excludedDirs[$this->getFilename()]) && $this->isDir()) {
67152 return false;
67153 }
67154
67155 if ($this->excludedPattern) {
67156 $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
67157 $path = str_replace('\\', '/', $path);
67158
67159 return !preg_match($this->excludedPattern, $path);
67160 }
67161
67162 return true;
67163 }
67164
67165 public function hasChildren()
67166 {
67167 return $this->isRecursive && $this->iterator->hasChildren();
67168 }
67169
67170 public function getChildren()
67171 {
67172 $children = new self($this->iterator->getChildren(), array());
67173 $children->excludedDirs = $this->excludedDirs;
67174 $children->excludedPattern = $this->excludedPattern;
67175
67176 return $children;
67177 }
67178 }
67179 <?php
67180
67181
67182
67183
67184
67185
67186
67187
67188
67189
67190 namespace Symfony\Component\Finder\Iterator;
67191
67192 @trigger_error('The '.__NAMESPACE__.'\FilePathsIterator class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
67193
67194 use Symfony\Component\Finder\SplFileInfo;
67195
67196
67197
67198
67199
67200
67201
67202
67203 class FilePathsIterator extends \ArrayIterator
67204 {
67205
67206
67207
67208 private $baseDir;
67209
67210
67211
67212
67213 private $baseDirLength;
67214
67215
67216
67217
67218 private $subPath;
67219
67220
67221
67222
67223 private $subPathname;
67224
67225
67226
67227
67228 private $current;
67229
67230
67231
67232
67233
67234 public function __construct(array $paths, $baseDir)
67235 {
67236 $this->baseDir = $baseDir;
67237 $this->baseDirLength = strlen($baseDir);
67238
67239 parent::__construct($paths);
67240 }
67241
67242
67243
67244
67245
67246
67247
67248 public function __call($name, array $arguments)
67249 {
67250 return call_user_func_array(array($this->current(), $name), $arguments);
67251 }
67252
67253
67254
67255
67256
67257
67258 public function current()
67259 {
67260 return $this->current;
67261 }
67262
67263
67264
67265
67266 public function key()
67267 {
67268 return $this->current->getPathname();
67269 }
67270
67271 public function next()
67272 {
67273 parent::next();
67274 $this->buildProperties();
67275 }
67276
67277 public function rewind()
67278 {
67279 parent::rewind();
67280 $this->buildProperties();
67281 }
67282
67283
67284
67285
67286 public function getSubPath()
67287 {
67288 return $this->subPath;
67289 }
67290
67291
67292
67293
67294 public function getSubPathname()
67295 {
67296 return $this->subPathname;
67297 }
67298
67299 private function buildProperties()
67300 {
67301 $absolutePath = parent::current();
67302
67303 if ($this->baseDir === substr($absolutePath, 0, $this->baseDirLength)) {
67304 $this->subPathname = ltrim(substr($absolutePath, $this->baseDirLength), '/\\');
67305 $dir = dirname($this->subPathname);
67306 $this->subPath = '.' === $dir ? '' : $dir;
67307 } else {
67308 $this->subPath = $this->subPathname = '';
67309 }
67310
67311 $this->current = new SplFileInfo(parent::current(), $this->subPath, $this->subPathname);
67312 }
67313 }
67314 <?php
67315
67316
67317
67318
67319
67320
67321
67322
67323
67324
67325 namespace Symfony\Component\Finder\Iterator;
67326
67327
67328
67329
67330
67331
67332 class FileTypeFilterIterator extends FilterIterator
67333 {
67334 const ONLY_FILES = 1;
67335 const ONLY_DIRECTORIES = 2;
67336
67337 private $mode;
67338
67339
67340
67341
67342
67343
67344
67345 public function __construct(\Iterator $iterator, $mode)
67346 {
67347 $this->mode = $mode;
67348
67349 parent::__construct($iterator);
67350 }
67351
67352
67353
67354
67355
67356
67357 public function accept()
67358 {
67359 $fileinfo = $this->current();
67360 if (self::ONLY_DIRECTORIES === (self::ONLY_DIRECTORIES & $this->mode) && $fileinfo->isFile()) {
67361 return false;
67362 } elseif (self::ONLY_FILES === (self::ONLY_FILES & $this->mode) && $fileinfo->isDir()) {
67363 return false;
67364 }
67365
67366 return true;
67367 }
67368 }
67369 <?php
67370
67371
67372
67373
67374
67375
67376
67377
67378
67379
67380 namespace Symfony\Component\Finder\Iterator;
67381
67382
67383
67384
67385
67386
67387
67388 class FilecontentFilterIterator extends MultiplePcreFilterIterator
67389 {
67390
67391
67392
67393
67394
67395 public function accept()
67396 {
67397 if (!$this->matchRegexps && !$this->noMatchRegexps) {
67398 return true;
67399 }
67400
67401 $fileinfo = $this->current();
67402
67403 if ($fileinfo->isDir() || !$fileinfo->isReadable()) {
67404 return false;
67405 }
67406
67407 $content = $fileinfo->getContents();
67408 if (!$content) {
67409 return false;
67410 }
67411
67412 return $this->isAccepted($content);
67413 }
67414
67415
67416
67417
67418
67419
67420
67421
67422 protected function toRegex($str)
67423 {
67424 return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
67425 }
67426 }
67427 <?php
67428
67429
67430
67431
67432
67433
67434
67435
67436
67437
67438 namespace Symfony\Component\Finder\Iterator;
67439
67440 use Symfony\Component\Finder\Glob;
67441
67442
67443
67444
67445
67446
67447 class FilenameFilterIterator extends MultiplePcreFilterIterator
67448 {
67449
67450
67451
67452
67453
67454 public function accept()
67455 {
67456 return $this->isAccepted($this->current()->getFilename());
67457 }
67458
67459
67460
67461
67462
67463
67464
67465
67466
67467
67468
67469 protected function toRegex($str)
67470 {
67471 return $this->isRegex($str) ? $str : Glob::toRegex($str);
67472 }
67473 }
67474 <?php
67475
67476
67477
67478
67479
67480
67481
67482
67483
67484
67485 namespace Symfony\Component\Finder\Iterator;
67486
67487
67488
67489
67490
67491
67492
67493
67494
67495 abstract class FilterIterator extends \FilterIterator
67496 {
67497
67498
67499
67500
67501
67502
67503 public function rewind()
67504 {
67505 if (\PHP_VERSION_ID > 50607 || (\PHP_VERSION_ID > 50523 && \PHP_VERSION_ID < 50600)) {
67506 parent::rewind();
67507
67508 return;
67509 }
67510
67511 $iterator = $this;
67512 while ($iterator instanceof \OuterIterator) {
67513 $innerIterator = $iterator->getInnerIterator();
67514
67515 if ($innerIterator instanceof RecursiveDirectoryIterator) {
67516
67517  if ($innerIterator->isRewindable()) {
67518 $innerIterator->next();
67519 $innerIterator->rewind();
67520 }
67521 } elseif ($innerIterator instanceof \FilesystemIterator) {
67522 $innerIterator->next();
67523 $innerIterator->rewind();
67524 }
67525
67526 $iterator = $innerIterator;
67527 }
67528
67529 parent::rewind();
67530 }
67531 }
67532 <?php
67533
67534
67535
67536
67537
67538
67539
67540
67541
67542
67543 namespace Symfony\Component\Finder\Iterator;
67544
67545
67546
67547
67548
67549
67550 abstract class MultiplePcreFilterIterator extends FilterIterator
67551 {
67552 protected $matchRegexps = array();
67553 protected $noMatchRegexps = array();
67554
67555
67556
67557
67558
67559
67560
67561
67562 public function __construct(\Iterator $iterator, array $matchPatterns, array $noMatchPatterns)
67563 {
67564 foreach ($matchPatterns as $pattern) {
67565 $this->matchRegexps[] = $this->toRegex($pattern);
67566 }
67567
67568 foreach ($noMatchPatterns as $pattern) {
67569 $this->noMatchRegexps[] = $this->toRegex($pattern);
67570 }
67571
67572 parent::__construct($iterator);
67573 }
67574
67575
67576
67577
67578
67579
67580
67581
67582
67583
67584
67585
67586 protected function isAccepted($string)
67587 {
67588
67589  foreach ($this->noMatchRegexps as $regex) {
67590 if (preg_match($regex, $string)) {
67591 return false;
67592 }
67593 }
67594
67595
67596  if ($this->matchRegexps) {
67597 foreach ($this->matchRegexps as $regex) {
67598 if (preg_match($regex, $string)) {
67599 return true;
67600 }
67601 }
67602
67603 return false;
67604 }
67605
67606
67607  return true;
67608 }
67609
67610
67611
67612
67613
67614
67615
67616
67617 protected function isRegex($str)
67618 {
67619 if (preg_match('/^(.{3,}?)[imsxuADU]*$/', $str, $m)) {
67620 $start = substr($m[1], 0, 1);
67621 $end = substr($m[1], -1);
67622
67623 if ($start === $end) {
67624 return !preg_match('/[*?[:alnum:] \\\\]/', $start);
67625 }
67626
67627 foreach (array(array('{', '}'), array('(', ')'), array('[', ']'), array('<', '>')) as $delimiters) {
67628 if ($start === $delimiters[0] && $end === $delimiters[1]) {
67629 return true;
67630 }
67631 }
67632 }
67633
67634 return false;
67635 }
67636
67637
67638
67639
67640
67641
67642
67643
67644 abstract protected function toRegex($str);
67645 }
67646 <?php
67647
67648
67649
67650
67651
67652
67653
67654
67655
67656
67657 namespace Symfony\Component\Finder\Iterator;
67658
67659
67660
67661
67662
67663
67664
67665 class PathFilterIterator extends MultiplePcreFilterIterator
67666 {
67667
67668
67669
67670
67671
67672 public function accept()
67673 {
67674 $filename = $this->current()->getRelativePathname();
67675
67676 if ('\\' === DIRECTORY_SEPARATOR) {
67677 $filename = str_replace('\\', '/', $filename);
67678 }
67679
67680 return $this->isAccepted($filename);
67681 }
67682
67683
67684
67685
67686
67687
67688
67689
67690
67691
67692
67693
67694
67695
67696
67697 protected function toRegex($str)
67698 {
67699 return $this->isRegex($str) ? $str : '/'.preg_quote($str, '/').'/';
67700 }
67701 }
67702 <?php
67703
67704
67705
67706
67707
67708
67709
67710
67711
67712
67713 namespace Symfony\Component\Finder\Iterator;
67714
67715 use Symfony\Component\Finder\Exception\AccessDeniedException;
67716 use Symfony\Component\Finder\SplFileInfo;
67717
67718
67719
67720
67721
67722
67723 class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator
67724 {
67725
67726
67727
67728 private $ignoreUnreadableDirs;
67729
67730
67731
67732
67733 private $rewindable;
67734
67735
67736  private $rootPath;
67737 private $subPath;
67738 private $directorySeparator = '/';
67739
67740
67741
67742
67743
67744
67745
67746
67747
67748
67749 public function __construct($path, $flags, $ignoreUnreadableDirs = false)
67750 {
67751 if ($flags & (self::CURRENT_AS_PATHNAME | self::CURRENT_AS_SELF)) {
67752 throw new \RuntimeException('This iterator only support returning current as fileinfo.');
67753 }
67754
67755 parent::__construct($path, $flags);
67756 $this->ignoreUnreadableDirs = $ignoreUnreadableDirs;
67757 $this->rootPath = (string) $path;
67758 if ('/' !== DIRECTORY_SEPARATOR && !($flags & self::UNIX_PATHS)) {
67759 $this->directorySeparator = DIRECTORY_SEPARATOR;
67760 }
67761 }
67762
67763
67764
67765
67766
67767
67768 public function current()
67769 {
67770
67771
67772 if (null === $subPathname = $this->subPath) {
67773 $subPathname = $this->subPath = (string) $this->getSubPath();
67774 }
67775 if ('' !== $subPathname) {
67776 $subPathname .= $this->directorySeparator;
67777 }
67778 $subPathname .= $this->getFilename();
67779
67780 return new SplFileInfo($this->rootPath.$this->directorySeparator.$subPathname, $this->subPath, $subPathname);
67781 }
67782
67783
67784
67785
67786
67787
67788 public function getChildren()
67789 {
67790 try {
67791 $children = parent::getChildren();
67792
67793 if ($children instanceof self) {
67794
67795  $children->ignoreUnreadableDirs = $this->ignoreUnreadableDirs;
67796
67797
67798  $children->rewindable = &$this->rewindable;
67799 $children->rootPath = $this->rootPath;
67800 }
67801
67802 return $children;
67803 } catch (\UnexpectedValueException $e) {
67804 if ($this->ignoreUnreadableDirs) {
67805
67806  return new \RecursiveArrayIterator(array());
67807 } else {
67808 throw new AccessDeniedException($e->getMessage(), $e->getCode(), $e);
67809 }
67810 }
67811 }
67812
67813
67814
67815
67816 public function rewind()
67817 {
67818 if (false === $this->isRewindable()) {
67819 return;
67820 }
67821
67822
67823  if (\PHP_VERSION_ID < 50523 || \PHP_VERSION_ID >= 50600 && \PHP_VERSION_ID < 50607) {
67824 parent::next();
67825 }
67826
67827 parent::rewind();
67828 }
67829
67830
67831
67832
67833
67834
67835 public function isRewindable()
67836 {
67837 if (null !== $this->rewindable) {
67838 return $this->rewindable;
67839 }
67840
67841
67842  if ('' === $this->getPath()) {
67843 return $this->rewindable = false;
67844 }
67845
67846 if (false !== $stream = @opendir($this->getPath())) {
67847 $infos = stream_get_meta_data($stream);
67848 closedir($stream);
67849
67850 if ($infos['seekable']) {
67851 return $this->rewindable = true;
67852 }
67853 }
67854
67855 return $this->rewindable = false;
67856 }
67857 }
67858 <?php
67859
67860
67861
67862
67863
67864
67865
67866
67867
67868
67869 namespace Symfony\Component\Finder\Iterator;
67870
67871 use Symfony\Component\Finder\Comparator\NumberComparator;
67872
67873
67874
67875
67876
67877
67878 class SizeRangeFilterIterator extends FilterIterator
67879 {
67880 private $comparators = array();
67881
67882
67883
67884
67885
67886
67887
67888 public function __construct(\Iterator $iterator, array $comparators)
67889 {
67890 $this->comparators = $comparators;
67891
67892 parent::__construct($iterator);
67893 }
67894
67895
67896
67897
67898
67899
67900 public function accept()
67901 {
67902 $fileinfo = $this->current();
67903 if (!$fileinfo->isFile()) {
67904 return true;
67905 }
67906
67907 $filesize = $fileinfo->getSize();
67908 foreach ($this->comparators as $compare) {
67909 if (!$compare->test($filesize)) {
67910 return false;
67911 }
67912 }
67913
67914 return true;
67915 }
67916 }
67917 <?php
67918
67919
67920
67921
67922
67923
67924
67925
67926
67927
67928 namespace Symfony\Component\Finder\Iterator;
67929
67930
67931
67932
67933
67934
67935 class SortableIterator implements \IteratorAggregate
67936 {
67937 const SORT_BY_NAME = 1;
67938 const SORT_BY_TYPE = 2;
67939 const SORT_BY_ACCESSED_TIME = 3;
67940 const SORT_BY_CHANGED_TIME = 4;
67941 const SORT_BY_MODIFIED_TIME = 5;
67942
67943 private $iterator;
67944 private $sort;
67945
67946
67947
67948
67949
67950
67951
67952
67953
67954 public function __construct(\Traversable $iterator, $sort)
67955 {
67956 $this->iterator = $iterator;
67957
67958 if (self::SORT_BY_NAME === $sort) {
67959 $this->sort = function ($a, $b) {
67960 return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
67961 };
67962 } elseif (self::SORT_BY_TYPE === $sort) {
67963 $this->sort = function ($a, $b) {
67964 if ($a->isDir() && $b->isFile()) {
67965 return -1;
67966 } elseif ($a->isFile() && $b->isDir()) {
67967 return 1;
67968 }
67969
67970 return strcmp($a->getRealpath() ?: $a->getPathname(), $b->getRealpath() ?: $b->getPathname());
67971 };
67972 } elseif (self::SORT_BY_ACCESSED_TIME === $sort) {
67973 $this->sort = function ($a, $b) {
67974 return $a->getATime() - $b->getATime();
67975 };
67976 } elseif (self::SORT_BY_CHANGED_TIME === $sort) {
67977 $this->sort = function ($a, $b) {
67978 return $a->getCTime() - $b->getCTime();
67979 };
67980 } elseif (self::SORT_BY_MODIFIED_TIME === $sort) {
67981 $this->sort = function ($a, $b) {
67982 return $a->getMTime() - $b->getMTime();
67983 };
67984 } elseif (is_callable($sort)) {
67985 $this->sort = $sort;
67986 } else {
67987 throw new \InvalidArgumentException('The SortableIterator takes a PHP callable or a valid built-in sort algorithm as an argument.');
67988 }
67989 }
67990
67991 public function getIterator()
67992 {
67993 $array = iterator_to_array($this->iterator, true);
67994 uasort($array, $this->sort);
67995
67996 return new \ArrayIterator($array);
67997 }
67998 }
67999 Copyright (c) 2004-2017 Fabien Potencier
68000
68001 Permission is hereby granted, free of charge, to any person obtaining a copy
68002 of this software and associated documentation files (the "Software"), to deal
68003 in the Software without restriction, including without limitation the rights
68004 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
68005 copies of the Software, and to permit persons to whom the Software is furnished
68006 to do so, subject to the following conditions:
68007
68008 The above copyright notice and this permission notice shall be included in all
68009 copies or substantial portions of the Software.
68010
68011 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
68012 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
68013 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
68014 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
68015 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
68016 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
68017 THE SOFTWARE.
68018 <?php
68019
68020
68021
68022
68023
68024
68025
68026
68027
68028
68029 namespace Symfony\Component\Finder\Shell;
68030
68031 @trigger_error('The '.__NAMESPACE__.'\Command class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68032
68033
68034
68035
68036
68037
68038 class Command
68039 {
68040
68041
68042
68043 private $parent;
68044
68045
68046
68047
68048 private $bits = array();
68049
68050
68051
68052
68053 private $labels = array();
68054
68055
68056
68057
68058 private $errorHandler;
68059
68060
68061
68062
68063
68064
68065 public function __construct(Command $parent = null)
68066 {
68067 $this->parent = $parent;
68068 }
68069
68070
68071
68072
68073
68074
68075 public function __toString()
68076 {
68077 return $this->join();
68078 }
68079
68080
68081
68082
68083
68084
68085
68086
68087 public static function create(Command $parent = null)
68088 {
68089 return new self($parent);
68090 }
68091
68092
68093
68094
68095
68096
68097
68098
68099 public static function escape($input)
68100 {
68101 return escapeshellcmd($input);
68102 }
68103
68104
68105
68106
68107
68108
68109
68110
68111 public static function quote($input)
68112 {
68113 return escapeshellarg($input);
68114 }
68115
68116
68117
68118
68119
68120
68121
68122
68123 public function add($bit)
68124 {
68125 $this->bits[] = $bit;
68126
68127 return $this;
68128 }
68129
68130
68131
68132
68133
68134
68135
68136
68137 public function top($bit)
68138 {
68139 array_unshift($this->bits, $bit);
68140
68141 foreach ($this->labels as $label => $index) {
68142 $this->labels[$label] += 1;
68143 }
68144
68145 return $this;
68146 }
68147
68148
68149
68150
68151
68152
68153
68154
68155 public function arg($arg)
68156 {
68157 $this->bits[] = self::quote($arg);
68158
68159 return $this;
68160 }
68161
68162
68163
68164
68165
68166
68167
68168
68169 public function cmd($esc)
68170 {
68171 $this->bits[] = self::escape($esc);
68172
68173 return $this;
68174 }
68175
68176
68177
68178
68179
68180
68181
68182
68183
68184
68185 public function ins($label)
68186 {
68187 if (isset($this->labels[$label])) {
68188 throw new \RuntimeException(sprintf('Label "%s" already exists.', $label));
68189 }
68190
68191 $this->bits[] = self::create($this);
68192 $this->labels[$label] = count($this->bits) - 1;
68193
68194 return $this->bits[$this->labels[$label]];
68195 }
68196
68197
68198
68199
68200
68201
68202
68203
68204
68205
68206 public function get($label)
68207 {
68208 if (!isset($this->labels[$label])) {
68209 throw new \RuntimeException(sprintf('Label "%s" does not exist.', $label));
68210 }
68211
68212 return $this->bits[$this->labels[$label]];
68213 }
68214
68215
68216
68217
68218
68219
68220
68221
68222 public function end()
68223 {
68224 if (null === $this->parent) {
68225 throw new \RuntimeException('Calling end on root command doesn\'t make sense.');
68226 }
68227
68228 return $this->parent;
68229 }
68230
68231
68232
68233
68234
68235
68236 public function length()
68237 {
68238 return count($this->bits);
68239 }
68240
68241
68242
68243
68244
68245
68246 public function setErrorHandler(\Closure $errorHandler)
68247 {
68248 $this->errorHandler = $errorHandler;
68249
68250 return $this;
68251 }
68252
68253
68254
68255
68256 public function getErrorHandler()
68257 {
68258 return $this->errorHandler;
68259 }
68260
68261
68262
68263
68264
68265
68266
68267
68268 public function execute()
68269 {
68270 if (null === $errorHandler = $this->errorHandler) {
68271 exec($this->join(), $output);
68272 } else {
68273 $process = proc_open($this->join(), array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes);
68274 $output = preg_split('~(\r\n|\r|\n)~', stream_get_contents($pipes[1]), -1, PREG_SPLIT_NO_EMPTY);
68275
68276 if ($error = stream_get_contents($pipes[2])) {
68277 $errorHandler($error);
68278 }
68279
68280 proc_close($process);
68281 }
68282
68283 return $output ?: array();
68284 }
68285
68286
68287
68288
68289
68290
68291 public function join()
68292 {
68293 return implode(' ', array_filter(
68294 array_map(function ($bit) {
68295 return $bit instanceof Command ? $bit->join() : ($bit ?: null);
68296 }, $this->bits),
68297 function ($bit) { return null !== $bit; }
68298 ));
68299 }
68300
68301
68302
68303
68304
68305
68306
68307
68308
68309 public function addAtIndex($bit, $index)
68310 {
68311 array_splice($this->bits, $index, 0, $bit instanceof self ? array($bit) : $bit);
68312
68313 return $this;
68314 }
68315 }
68316 <?php
68317
68318
68319
68320
68321
68322
68323
68324
68325
68326
68327 namespace Symfony\Component\Finder\Shell;
68328
68329 @trigger_error('The '.__NAMESPACE__.'\Shell class is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
68330
68331
68332
68333
68334
68335
68336 class Shell
68337 {
68338 const TYPE_UNIX = 1;
68339 const TYPE_DARWIN = 2;
68340 const TYPE_CYGWIN = 3;
68341 const TYPE_WINDOWS = 4;
68342 const TYPE_BSD = 5;
68343
68344
68345
68346
68347 private $type;
68348
68349
68350
68351
68352
68353
68354 public function getType()
68355 {
68356 if (null === $this->type) {
68357 $this->type = $this->guessType();
68358 }
68359
68360 return $this->type;
68361 }
68362
68363
68364
68365
68366
68367
68368
68369
68370 public function testCommand($command)
68371 {
68372 if (!function_exists('exec')) {
68373 return false;
68374 }
68375
68376
68377  $testCommand = 'which ';
68378 if (self::TYPE_WINDOWS === $this->type) {
68379 $testCommand = 'where ';
68380 }
68381
68382 $command = escapeshellcmd($command);
68383
68384 exec($testCommand.$command, $output, $code);
68385
68386 return 0 === $code && count($output) > 0;
68387 }
68388
68389
68390
68391
68392
68393
68394 private function guessType()
68395 {
68396 $os = strtolower(PHP_OS);
68397
68398 if (false !== strpos($os, 'cygwin')) {
68399 return self::TYPE_CYGWIN;
68400 }
68401
68402 if (false !== strpos($os, 'darwin')) {
68403 return self::TYPE_DARWIN;
68404 }
68405
68406 if (false !== strpos($os, 'bsd')) {
68407 return self::TYPE_BSD;
68408 }
68409
68410 if (0 === strpos($os, 'win')) {
68411 return self::TYPE_WINDOWS;
68412 }
68413
68414 return self::TYPE_UNIX;
68415 }
68416 }
68417 <?php
68418
68419
68420
68421
68422
68423
68424
68425
68426
68427
68428 namespace Symfony\Component\Finder;
68429
68430
68431
68432
68433
68434
68435 class SplFileInfo extends \SplFileInfo
68436 {
68437 private $relativePath;
68438 private $relativePathname;
68439
68440
68441
68442
68443
68444
68445
68446
68447 public function __construct($file, $relativePath, $relativePathname)
68448 {
68449 parent::__construct($file);
68450 $this->relativePath = $relativePath;
68451 $this->relativePathname = $relativePathname;
68452 }
68453
68454
68455
68456
68457
68458
68459
68460
68461 public function getRelativePath()
68462 {
68463 return $this->relativePath;
68464 }
68465
68466
68467
68468
68469
68470
68471
68472
68473 public function getRelativePathname()
68474 {
68475 return $this->relativePathname;
68476 }
68477
68478
68479
68480
68481
68482
68483
68484
68485 public function getContents()
68486 {
68487 $level = error_reporting(0);
68488 $content = file_get_contents($this->getPathname());
68489 error_reporting($level);
68490 if (false === $content) {
68491 $error = error_get_last();
68492 throw new \RuntimeException($error['message']);
68493 }
68494
68495 return $content;
68496 }
68497 }
68498 Copyright (c) 2014-2016 Fabien Potencier
68499
68500 Permission is hereby granted, free of charge, to any person obtaining a copy
68501 of this software and associated documentation files (the "Software"), to deal
68502 in the Software without restriction, including without limitation the rights
68503 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
68504 copies of the Software, and to permit persons to whom the Software is furnished
68505 to do so, subject to the following conditions:
68506
68507 The above copyright notice and this permission notice shall be included in all
68508 copies or substantial portions of the Software.
68509
68510 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
68511 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
68512 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
68513 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
68514 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
68515 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
68516 THE SOFTWARE.
68517 <?php
68518
68519
68520
68521
68522
68523
68524
68525
68526
68527
68528 namespace Symfony\Polyfill\Mbstring;
68529
68530
68531
68532
68533
68534
68535
68536
68537
68538
68539
68540
68541
68542
68543
68544
68545
68546
68547
68548
68549
68550
68551
68552
68553
68554
68555
68556
68557
68558
68559
68560
68561
68562
68563
68564
68565
68566
68567
68568
68569
68570
68571
68572
68573
68574
68575
68576
68577
68578
68579
68580
68581
68582 final class Mbstring
68583 {
68584 const MB_CASE_FOLD = PHP_INT_MAX;
68585
68586 private static $encodingList = array('ASCII', 'UTF-8');
68587 private static $language = 'neutral';
68588 private static $internalEncoding = 'UTF-8';
68589 private static $caseFold = array(
68590 array('µ','ſ',"\xCD\x85",'ς',"\xCF\x90","\xCF\x91","\xCF\x95","\xCF\x96","\xCF\xB0","\xCF\xB1","\xCF\xB5","\xE1\xBA\x9B","\xE1\xBE\xBE"),
68591 array('μ','s','ι', 'σ','β', 'θ', 'φ', 'π', 'κ', 'ρ', 'ε', "\xE1\xB9\xA1",'ι'),
68592 );
68593
68594 public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
68595 {
68596 if (is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
68597 $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
68598 } else {
68599 $fromEncoding = self::getEncoding($fromEncoding);
68600 }
68601
68602 $toEncoding = self::getEncoding($toEncoding);
68603
68604 if ('BASE64' === $fromEncoding) {
68605 $s = base64_decode($s);
68606 $fromEncoding = $toEncoding;
68607 }
68608
68609 if ('BASE64' === $toEncoding) {
68610 return base64_encode($s);
68611 }
68612
68613 if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
68614 if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
68615 $fromEncoding = 'Windows-1252';
68616 }
68617 if ('UTF-8' !== $fromEncoding) {
68618 $s = iconv($fromEncoding, 'UTF-8//IGNORE', $s);
68619 }
68620
68621 return preg_replace_callback('/[\x80-\xFF]+/', array(__CLASS__, 'html_encoding_callback'), $s);
68622 }
68623
68624 if ('HTML-ENTITIES' === $fromEncoding) {
68625 $s = html_entity_decode($s, ENT_COMPAT, 'UTF-8');
68626 $fromEncoding = 'UTF-8';
68627 }
68628
68629 return iconv($fromEncoding, $toEncoding.'//IGNORE', $s);
68630 }
68631
68632 public static function mb_convert_variables($toEncoding, $fromEncoding, &$a = null, &$b = null, &$c = null, &$d = null, &$e = null, &$f = null)
68633 {
68634 $vars = array(&$a, &$b, &$c, &$d, &$e, &$f);
68635
68636 $ok = true;
68637 array_walk_recursive($vars, function (&$v) use (&$ok, $toEncoding, $fromEncoding) {
68638 if (false === $v = Mbstring::mb_convert_encoding($v, $toEncoding, $fromEncoding)) {
68639 $ok = false;
68640 }
68641 });
68642
68643 return $ok ? $fromEncoding : false;
68644 }
68645
68646 public static function mb_decode_mimeheader($s)
68647 {
68648 return iconv_mime_decode($s, 2, self::$internalEncoding);
68649 }
68650
68651 public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
68652 {
68653 trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', E_USER_WARNING);
68654 }
68655
68656 public static function mb_convert_case($s, $mode, $encoding = null)
68657 {
68658 if ('' === $s .= '') {
68659 return '';
68660 }
68661
68662 $encoding = self::getEncoding($encoding);
68663
68664 if ('UTF-8' === $encoding) {
68665 $encoding = null;
68666 if (!preg_match('//u', $s)) {
68667 $s = @iconv('UTF-8', 'UTF-8//IGNORE', $s);
68668 }
68669 } else {
68670 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
68671 }
68672
68673 if (MB_CASE_TITLE == $mode) {
68674 $s = preg_replace_callback('/\b\p{Ll}/u', array(__CLASS__, 'title_case_upper'), $s);
68675 $s = preg_replace_callback('/\B[\p{Lu}\p{Lt}]+/u', array(__CLASS__, 'title_case_lower'), $s);
68676 } else {
68677 if (MB_CASE_UPPER == $mode) {
68678 static $upper = null;
68679 if (null === $upper) {
68680 $upper = self::getData('upperCase');
68681 }
68682 $map = $upper;
68683 } else {
68684 if (self::MB_CASE_FOLD === $mode) {
68685 $s = str_replace(self::$caseFold[0], self::$caseFold[1], $s);
68686 }
68687
68688 static $lower = null;
68689 if (null === $lower) {
68690 $lower = self::getData('lowerCase');
68691 }
68692 $map = $lower;
68693 }
68694
68695 static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4);
68696
68697 $i = 0;
68698 $len = strlen($s);
68699
68700 while ($i < $len) {
68701 $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"];
68702 $uchr = substr($s, $i, $ulen);
68703 $i += $ulen;
68704
68705 if (isset($map[$uchr])) {
68706 $uchr = $map[$uchr];
68707 $nlen = strlen($uchr);
68708
68709 if ($nlen == $ulen) {
68710 $nlen = $i;
68711 do {
68712 $s[--$nlen] = $uchr[--$ulen];
68713 } while ($ulen);
68714 } else {
68715 $s = substr_replace($s, $uchr, $i - $ulen, $ulen);
68716 $len += $nlen - $ulen;
68717 $i += $nlen - $ulen;
68718 }
68719 }
68720 }
68721 }
68722
68723 if (null === $encoding) {
68724 return $s;
68725 }
68726
68727 return iconv('UTF-8', $encoding.'//IGNORE', $s);
68728 }
68729
68730 public static function mb_internal_encoding($encoding = null)
68731 {
68732 if (null === $encoding) {
68733 return self::$internalEncoding;
68734 }
68735
68736 $encoding = self::getEncoding($encoding);
68737
68738 if ('UTF-8' === $encoding || false !== @iconv($encoding, $encoding, ' ')) {
68739 self::$internalEncoding = $encoding;
68740
68741 return true;
68742 }
68743
68744 return false;
68745 }
68746
68747 public static function mb_language($lang = null)
68748 {
68749 if (null === $lang) {
68750 return self::$language;
68751 }
68752
68753 switch ($lang = strtolower($lang)) {
68754 case 'uni':
68755 case 'neutral':
68756 self::$language = $lang;
68757
68758 return true;
68759 }
68760
68761 return false;
68762 }
68763
68764 public static function mb_list_encodings()
68765 {
68766 return array('UTF-8');
68767 }
68768
68769 public static function mb_encoding_aliases($encoding)
68770 {
68771 switch (strtoupper($encoding)) {
68772 case 'UTF8':
68773 case 'UTF-8':
68774 return array('utf8');
68775 }
68776
68777 return false;
68778 }
68779
68780 public static function mb_check_encoding($var = null, $encoding = null)
68781 {
68782 if (null === $encoding) {
68783 if (null === $var) {
68784 return false;
68785 }
68786 $encoding = self::$internalEncoding;
68787 }
68788
68789 return self::mb_detect_encoding($var, array($encoding)) || false !== @iconv($encoding, $encoding, $var);
68790 }
68791
68792 public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
68793 {
68794 if (null === $encodingList) {
68795 $encodingList = self::$encodingList;
68796 } else {
68797 if (!is_array($encodingList)) {
68798 $encodingList = array_map('trim', explode(',', $encodingList));
68799 }
68800 $encodingList = array_map('strtoupper', $encodingList);
68801 }
68802
68803 foreach ($encodingList as $enc) {
68804 switch ($enc) {
68805 case 'ASCII':
68806 if (!preg_match('/[\x80-\xFF]/', $str)) {
68807 return $enc;
68808 }
68809 break;
68810
68811 case 'UTF8':
68812 case 'UTF-8':
68813 if (preg_match('//u', $str)) {
68814 return 'UTF-8';
68815 }
68816 break;
68817
68818 default:
68819 if (0 === strncmp($enc, 'ISO-8859-', 9)) {
68820 return $enc;
68821 }
68822 }
68823 }
68824
68825 return false;
68826 }
68827
68828 public static function mb_detect_order($encodingList = null)
68829 {
68830 if (null === $encodingList) {
68831 return self::$encodingList;
68832 }
68833
68834 if (!is_array($encodingList)) {
68835 $encodingList = array_map('trim', explode(',', $encodingList));
68836 }
68837 $encodingList = array_map('strtoupper', $encodingList);
68838
68839 foreach ($encodingList as $enc) {
68840 switch ($enc) {
68841 default:
68842 if (strncmp($enc, 'ISO-8859-', 9)) {
68843 return false;
68844 }
68845 case 'ASCII':
68846 case 'UTF8':
68847 case 'UTF-8':
68848 }
68849 }
68850
68851 self::$encodingList = $encodingList;
68852
68853 return true;
68854 }
68855
68856 public static function mb_strlen($s, $encoding = null)
68857 {
68858 $encoding = self::getEncoding($encoding);
68859 if ('CP850' === $encoding || 'ASCII' === $encoding) {
68860 return strlen($s);
68861 }
68862
68863 return @iconv_strlen($s, $encoding);
68864 }
68865
68866 public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
68867 {
68868 $encoding = self::getEncoding($encoding);
68869 if ('CP850' === $encoding || 'ASCII' === $encoding) {
68870 return strpos($haystack, $needle, $offset);
68871 }
68872
68873 if ('' === $needle .= '') {
68874 trigger_error(__METHOD__.': Empty delimiter', E_USER_WARNING);
68875
68876 return false;
68877 }
68878
68879 return iconv_strpos($haystack, $needle, $offset, $encoding);
68880 }
68881
68882 public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
68883 {
68884 $encoding = self::getEncoding($encoding);
68885 if ('CP850' === $encoding || 'ASCII' === $encoding) {
68886 return strrpos($haystack, $needle, $offset);
68887 }
68888
68889 if ($offset != (int) $offset) {
68890 $offset = 0;
68891 } elseif ($offset = (int) $offset) {
68892 if ($offset < 0) {
68893 $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
68894 $offset = 0;
68895 } else {
68896 $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
68897 }
68898 }
68899
68900 $pos = iconv_strrpos($haystack, $needle, $encoding);
68901
68902 return false !== $pos ? $offset + $pos : false;
68903 }
68904
68905 public static function mb_strtolower($s, $encoding = null)
68906 {
68907 return self::mb_convert_case($s, MB_CASE_LOWER, $encoding);
68908 }
68909
68910 public static function mb_strtoupper($s, $encoding = null)
68911 {
68912 return self::mb_convert_case($s, MB_CASE_UPPER, $encoding);
68913 }
68914
68915 public static function mb_substitute_character($c = null)
68916 {
68917 if (0 === strcasecmp($c, 'none')) {
68918 return true;
68919 }
68920
68921 return null !== $c ? false : 'none';
68922 }
68923
68924 public static function mb_substr($s, $start, $length = null, $encoding = null)
68925 {
68926 $encoding = self::getEncoding($encoding);
68927 if ('CP850' === $encoding || 'ASCII' === $encoding) {
68928 return substr($s, $start, null === $length ? 2147483647 : $length);
68929 }
68930
68931 if ($start < 0) {
68932 $start = iconv_strlen($s, $encoding) + $start;
68933 if ($start < 0) {
68934 $start = 0;
68935 }
68936 }
68937
68938 if (null === $length) {
68939 $length = 2147483647;
68940 } elseif ($length < 0) {
68941 $length = iconv_strlen($s, $encoding) + $length - $start;
68942 if ($length < 0) {
68943 return '';
68944 }
68945 }
68946
68947 return iconv_substr($s, $start, $length, $encoding).'';
68948 }
68949
68950 public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
68951 {
68952 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
68953 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
68954
68955 return self::mb_strpos($haystack, $needle, $offset, $encoding);
68956 }
68957
68958 public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
68959 {
68960 $pos = self::mb_stripos($haystack, $needle, 0, $encoding);
68961
68962 return self::getSubpart($pos, $part, $haystack, $encoding);
68963 }
68964
68965 public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
68966 {
68967 $encoding = self::getEncoding($encoding);
68968 if ('CP850' === $encoding || 'ASCII' === $encoding) {
68969 return strrchr($haystack, $needle, $part);
68970 }
68971 $needle = self::mb_substr($needle, 0, 1, $encoding);
68972 $pos = iconv_strrpos($haystack, $needle, $encoding);
68973
68974 return self::getSubpart($pos, $part, $haystack, $encoding);
68975 }
68976
68977 public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
68978 {
68979 $needle = self::mb_substr($needle, 0, 1, $encoding);
68980 $pos = self::mb_strripos($haystack, $needle, $encoding);
68981
68982 return self::getSubpart($pos, $part, $haystack, $encoding);
68983 }
68984
68985 public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
68986 {
68987 $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
68988 $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
68989
68990 return self::mb_strrpos($haystack, $needle, $offset, $encoding);
68991 }
68992
68993 public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
68994 {
68995 $pos = strpos($haystack, $needle);
68996 if (false === $pos) {
68997 return false;
68998 }
68999 if ($part) {
69000 return substr($haystack, 0, $pos);
69001 }
69002
69003 return substr($haystack, $pos);
69004 }
69005
69006 public static function mb_get_info($type = 'all')
69007 {
69008 $info = array(
69009 'internal_encoding' => self::$internalEncoding,
69010 'http_output' => 'pass',
69011 'http_output_conv_mimetypes' => '^(text/|application/xhtml\+xml)',
69012 'func_overload' => 0,
69013 'func_overload_list' => 'no overload',
69014 'mail_charset' => 'UTF-8',
69015 'mail_header_encoding' => 'BASE64',
69016 'mail_body_encoding' => 'BASE64',
69017 'illegal_chars' => 0,
69018 'encoding_translation' => 'Off',
69019 'language' => self::$language,
69020 'detect_order' => self::$encodingList,
69021 'substitute_character' => 'none',
69022 'strict_detection' => 'Off',
69023 );
69024
69025 if ('all' === $type) {
69026 return $info;
69027 }
69028 if (isset($info[$type])) {
69029 return $info[$type];
69030 }
69031
69032 return false;
69033 }
69034
69035 public static function mb_http_input($type = '')
69036 {
69037 return false;
69038 }
69039
69040 public static function mb_http_output($encoding = null)
69041 {
69042 return null !== $encoding ? 'pass' === $encoding : 'pass';
69043 }
69044
69045 public static function mb_strwidth($s, $encoding = null)
69046 {
69047 $encoding = self::getEncoding($encoding);
69048
69049 if ('UTF-8' !== $encoding) {
69050 $s = iconv($encoding, 'UTF-8//IGNORE', $s);
69051 }
69052
69053 $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);
69054
69055 return ($wide << 1) + iconv_strlen($s, 'UTF-8');
69056 }
69057
69058 public static function mb_substr_count($haystack, $needle, $encoding = null)
69059 {
69060 return substr_count($haystack, $needle);
69061 }
69062
69063 public static function mb_output_handler($contents, $status)
69064 {
69065 return $contents;
69066 }
69067
69068 public static function mb_chr($code, $encoding = null)
69069 {
69070 if (0x80 > $code %= 0x200000) {
69071 $s = chr($code);
69072 } elseif (0x800 > $code) {
69073 $s = chr(0xC0 | $code >> 6).chr(0x80 | $code & 0x3F);
69074 } elseif (0x10000 > $code) {
69075 $s = chr(0xE0 | $code >> 12).chr(0x80 | $code >> 6 & 0x3F).chr(0x80 | $code & 0x3F);
69076 } else {
69077 $s = chr(0xF0 | $code >> 18).chr(0x80 | $code >> 12 & 0x3F).chr(0x80 | $code >> 6 & 0x3F).chr(0x80 | $code & 0x3F);
69078 }
69079
69080 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
69081 $s = mb_convert_encoding($s, $encoding, 'UTF-8');
69082 }
69083
69084 return $s;
69085 }
69086
69087 public static function mb_ord($s, $encoding = null)
69088 {
69089 if ('UTF-8' !== $encoding = self::getEncoding($encoding)) {
69090 $s = mb_convert_encoding($s, 'UTF-8', $encoding);
69091 }
69092
69093 $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0;
69094 if (0xF0 <= $code) {
69095 return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80;
69096 }
69097 if (0xE0 <= $code) {
69098 return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80;
69099 }
69100 if (0xC0 <= $code) {
69101 return (($code - 0xC0) << 6) + $s[2] - 0x80;
69102 }
69103
69104 return $code;
69105 }
69106
69107 private static function getSubpart($pos, $part, $haystack, $encoding)
69108 {
69109 if (false === $pos) {
69110 return false;
69111 }
69112 if ($part) {
69113 return self::mb_substr($haystack, 0, $pos, $encoding);
69114 }
69115
69116 return self::mb_substr($haystack, $pos, null, $encoding);
69117 }
69118
69119 private static function html_encoding_callback($m)
69120 {
69121 $i = 1;
69122 $entities = '';
69123 $m = unpack('C*', htmlentities($m[0], ENT_COMPAT, 'UTF-8'));
69124
69125 while (isset($m[$i])) {
69126 if (0x80 > $m[$i]) {
69127 $entities .= chr($m[$i++]);
69128 continue;
69129 }
69130 if (0xF0 <= $m[$i]) {
69131 $c = (($m[$i++] - 0xF0) << 18) + (($m[$i++] - 0x80) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
69132 } elseif (0xE0 <= $m[$i]) {
69133 $c = (($m[$i++] - 0xE0) << 12) + (($m[$i++] - 0x80) << 6) + $m[$i++] - 0x80;
69134 } else {
69135 $c = (($m[$i++] - 0xC0) << 6) + $m[$i++] - 0x80;
69136 }
69137
69138 $entities .= '&#'.$c.';';
69139 }
69140
69141 return $entities;
69142 }
69143
69144 private static function title_case_lower($s)
69145 {
69146 return self::mb_convert_case($s[0], MB_CASE_LOWER, 'UTF-8');
69147 }
69148
69149 private static function title_case_upper($s)
69150 {
69151 return self::mb_convert_case($s[0], MB_CASE_UPPER, 'UTF-8');
69152 }
69153
69154 private static function getData($file)
69155 {
69156 if (file_exists($file = __DIR__.'/Resources/unidata/'.$file.'.php')) {
69157 return require $file;
69158 }
69159
69160 return false;
69161 }
69162
69163 private static function getEncoding($encoding)
69164 {
69165 if (null === $encoding) {
69166 return self::$internalEncoding;
69167 }
69168
69169 $encoding = strtoupper($encoding);
69170
69171 if ('8BIT' === $encoding || 'BINARY' === $encoding) {
69172 return 'CP850';
69173 }
69174 if ('UTF8' === $encoding) {
69175 return 'UTF-8';
69176 }
69177
69178 return $encoding;
69179 }
69180 }
69181 <?php
69182
69183 static $data = array (
69184 'A' => 'a',
69185 'B' => 'b',
69186 'C' => 'c',
69187 'D' => 'd',
69188 'E' => 'e',
69189 'F' => 'f',
69190 'G' => 'g',
69191 'H' => 'h',
69192 'I' => 'i',
69193 'J' => 'j',
69194 'K' => 'k',
69195 'L' => 'l',
69196 'M' => 'm',
69197 'N' => 'n',
69198 'O' => 'o',
69199 'P' => 'p',
69200 'Q' => 'q',
69201 'R' => 'r',
69202 'S' => 's',
69203 'T' => 't',
69204 'U' => 'u',
69205 'V' => 'v',
69206 'W' => 'w',
69207 'X' => 'x',
69208 'Y' => 'y',
69209 'Z' => 'z',
69210 'À' => 'à',
69211 'Á' => 'á',
69212 'Â' => 'â',
69213 'Ã' => 'ã',
69214 'Ä' => 'ä',
69215 'Å' => 'å',
69216 'Æ' => 'æ',
69217 'Ç' => 'ç',
69218 'È' => 'è',
69219 'É' => 'é',
69220 'Ê' => 'ê',
69221 'Ë' => 'ë',
69222 'Ì' => 'ì',
69223 'Í' => 'í',
69224 'Î' => 'î',
69225 'Ï' => 'ï',
69226 'Ð' => 'ð',
69227 'Ñ' => 'ñ',
69228 'Ò' => 'ò',
69229 'Ó' => 'ó',
69230 'Ô' => 'ô',
69231 'Õ' => 'õ',
69232 'Ö' => 'ö',
69233 'Ø' => 'ø',
69234 'Ù' => 'ù',
69235 'Ú' => 'ú',
69236 'Û' => 'û',
69237 'Ü' => 'ü',
69238 'Ý' => 'ý',
69239 'Þ' => 'þ',
69240 'Ā' => 'ā',
69241 'Ă' => 'ă',
69242 'Ą' => 'ą',
69243 'Ć' => 'ć',
69244 'Ĉ' => 'ĉ',
69245 'Ċ' => 'ċ',
69246 'Č' => 'č',
69247 'Ď' => 'ď',
69248 'Đ' => 'đ',
69249 'Ē' => 'ē',
69250 'Ĕ' => 'ĕ',
69251 'Ė' => 'ė',
69252 'Ę' => 'ę',
69253 'Ě' => 'ě',
69254 'Ĝ' => 'ĝ',
69255 'Ğ' => 'ğ',
69256 'Ġ' => 'ġ',
69257 'Ģ' => 'ģ',
69258 'Ĥ' => 'ĥ',
69259 'Ħ' => 'ħ',
69260 'Ĩ' => 'ĩ',
69261 'Ī' => 'ī',
69262 'Ĭ' => 'ĭ',
69263 'Į' => 'į',
69264 'İ' => 'i',
69265 'IJ' => 'ij',
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 'Ɛ' => 'ɛ',
69314 'Ƒ' => 'ƒ',
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 'DŽ' => 'dž',
69340 'Dž' => 'dž',
69341 'LJ' => 'lj',
69342 'Lj' => 'lj',
69343 'NJ' => 'nj',
69344 'Nj' => 'nj',
69345 'Ǎ' => 'ǎ',
69346 'Ǐ' => 'ǐ',
69347 'Ǒ' => 'ǒ',
69348 'Ǔ' => 'ǔ',
69349 'Ǖ' => 'ǖ',
69350 'Ǘ' => 'ǘ',
69351 'Ǚ' => 'ǚ',
69352 'Ǜ' => 'ǜ',
69353 'Ǟ' => 'ǟ',
69354 'Ǡ' => 'ǡ',
69355 'Ǣ' => 'ǣ',
69356 'Ǥ' => 'ǥ',
69357 'Ǧ' => 'ǧ',
69358 'Ǩ' => 'ǩ',
69359 'Ǫ' => 'ǫ',
69360 'Ǭ' => 'ǭ',
69361 'Ǯ' => 'ǯ',
69362 'DZ' => 'dz',
69363 'Dz' => 'dz',
69364 'Ǵ' => 'ǵ',
69365 'Ƕ' => 'ƕ',
69366 'Ƿ' => 'ƿ',
69367 'Ǹ' => 'ǹ',
69368 'Ǻ' => 'ǻ',
69369 'Ǽ' => 'ǽ',
69370 'Ǿ' => 'ǿ',
69371 'Ȁ' => 'ȁ',
69372 'Ȃ' => 'ȃ',
69373 'Ȅ' => 'ȅ',
69374 'Ȇ' => 'ȇ',
69375 'Ȉ' => 'ȉ',
69376 'Ȋ' => 'ȋ',
69377 'Ȍ' => 'ȍ',
69378 'Ȏ' => 'ȏ',
69379 'Ȑ' => 'ȑ',
69380 'Ȓ' => 'ȓ',
69381 'Ȕ' => 'ȕ',
69382 'Ȗ' => 'ȗ',
69383 'Ș' => 'ș',
69384 'Ț' => 'ț',
69385 'Ȝ' => 'ȝ',
69386 'Ȟ' => 'ȟ',
69387 'Ƞ' => 'ƞ',
69388 'Ȣ' => 'ȣ',
69389 'Ȥ' => 'ȥ',
69390 'Ȧ' => 'ȧ',
69391 'Ȩ' => 'ȩ',
69392 'Ȫ' => 'ȫ',
69393 'Ȭ' => 'ȭ',
69394 'Ȯ' => 'ȯ',
69395 'Ȱ' => 'ȱ',
69396 'Ȳ' => 'ȳ',
69397 'Ⱥ' => 'ⱥ',
69398 'Ȼ' => 'ȼ',
69399 'Ƚ' => 'ƚ',
69400 'Ⱦ' => 'ⱦ',
69401 'Ɂ' => 'ɂ',
69402 'Ƀ' => 'ƀ',
69403 'Ʉ' => 'ʉ',
69404 'Ʌ' => 'ʌ',
69405 'Ɇ' => 'ɇ',
69406 'Ɉ' => 'ɉ',
69407 'Ɋ' => 'ɋ',
69408 'Ɍ' => 'ɍ',
69409 'Ɏ' => 'ɏ',
69410 'Ͱ' => 'ͱ',
69411 'Ͳ' => 'ͳ',
69412 'Ͷ' => 'ͷ',
69413 'Ϳ' => 'ϳ',
69414 'Ά' => 'ά',
69415 'Έ' => 'έ',
69416 'Ή' => 'ή',
69417 'Ί' => 'ί',
69418 'Ό' => 'ό',
69419 'Ύ' => 'ύ',
69420 'Ώ' => 'ώ',
69421 'Α' => 'α',
69422 'Β' => 'β',
69423 'Γ' => 'γ',
69424 'Δ' => 'δ',
69425 'Ε' => 'ε',
69426 'Ζ' => 'ζ',
69427 'Η' => 'η',
69428 'Θ' => 'θ',
69429 'Ι' => 'ι',
69430 'Κ' => 'κ',
69431 'Λ' => 'λ',
69432 'Μ' => 'μ',
69433 'Ν' => 'ν',
69434 'Ξ' => 'ξ',
69435 'Ο' => 'ο',
69436 'Π' => 'π',
69437 'Ρ' => 'ρ',
69438 'Σ' => 'σ',
69439 'Τ' => 'τ',
69440 'Υ' => 'υ',
69441 'Φ' => 'φ',
69442 'Χ' => 'χ',
69443 'Ψ' => 'ψ',
69444 'Ω' => 'ω',
69445 'Ϊ' => 'ϊ',
69446 'Ϋ' => 'ϋ',
69447 'Ϗ' => 'ϗ',
69448 'Ϙ' => 'ϙ',
69449 'Ϛ' => 'ϛ',
69450 'Ϝ' => 'ϝ',
69451 'Ϟ' => 'ϟ',
69452 'Ϡ' => 'ϡ',
69453 'Ϣ' => 'ϣ',
69454 'Ϥ' => 'ϥ',
69455 'Ϧ' => 'ϧ',
69456 'Ϩ' => 'ϩ',
69457 'Ϫ' => 'ϫ',
69458 'Ϭ' => 'ϭ',
69459 'Ϯ' => 'ϯ',
69460 'ϴ' => 'θ',
69461 'Ϸ' => 'ϸ',
69462 'Ϲ' => 'ϲ',
69463 'Ϻ' => 'ϻ',
69464 'Ͻ' => 'ͻ',
69465 'Ͼ' => 'ͼ',
69466 'Ͽ' => 'ͽ',
69467 'Ѐ' => 'ѐ',
69468 'Ё' => 'ё',
69469 'Ђ' => 'ђ',
69470 'Ѓ' => 'ѓ',
69471 'Є' => 'є',
69472 'Ѕ' => 'ѕ',
69473 'І' => 'і',
69474 'Ї' => 'ї',
69475 'Ј' => 'ј',
69476 'Љ' => 'љ',
69477 'Њ' => 'њ',
69478 'Ћ' => 'ћ',
69479 'Ќ' => 'ќ',
69480 'Ѝ' => 'ѝ',
69481 'Ў' => 'ў',
69482 'Џ' => 'џ',
69483 'А' => 'а',
69484 'Б' => 'б',
69485 'В' => 'в',
69486 'Г' => 'г',
69487 'Д' => 'д',
69488 'Е' => 'е',
69489 'Ж' => 'ж',
69490 'З' => 'з',
69491 'И' => 'и',
69492 'Й' => 'й',
69493 'К' => 'к',
69494 'Л' => 'л',
69495 'М' => 'м',
69496 'Н' => 'н',
69497 'О' => 'о',
69498 'П' => 'п',
69499 'Р' => 'р',
69500 'С' => 'с',
69501 'Т' => 'т',
69502 'У' => 'у',
69503 'Ф' => 'ф',
69504 'Х' => 'х',
69505 'Ц' => 'ц',
69506 'Ч' => 'ч',
69507 'Ш' => 'ш',
69508 'Щ' => 'щ',
69509 'Ъ' => 'ъ',
69510 'Ы' => 'ы',
69511 'Ь' => 'ь',
69512 'Э' => 'э',
69513 'Ю' => 'ю',
69514 'Я' => 'я',
69515 'Ѡ' => 'ѡ',
69516 'Ѣ' => 'ѣ',
69517 'Ѥ' => 'ѥ',
69518 'Ѧ' => 'ѧ',
69519 'Ѩ' => 'ѩ',
69520 'Ѫ' => 'ѫ',
69521 'Ѭ' => 'ѭ',
69522 'Ѯ' => 'ѯ',
69523 'Ѱ' => 'ѱ',
69524 'Ѳ' => 'ѳ',
69525 'Ѵ' => 'ѵ',
69526 'Ѷ' => 'ѷ',
69527 'Ѹ' => 'ѹ',
69528 'Ѻ' => 'ѻ',
69529 'Ѽ' => 'ѽ',
69530 'Ѿ' => 'ѿ',
69531 'Ҁ' => 'ҁ',
69532 'Ҋ' => 'ҋ',
69533 'Ҍ' => 'ҍ',
69534 'Ҏ' => 'ҏ',
69535 'Ґ' => 'ґ',
69536 'Ғ' => 'ғ',
69537 'Ҕ' => 'ҕ',
69538 'Җ' => 'җ',
69539 'Ҙ' => 'ҙ',
69540 'Қ' => 'қ',
69541 'Ҝ' => 'ҝ',
69542 'Ҟ' => 'ҟ',
69543 'Ҡ' => 'ҡ',
69544 'Ң' => 'ң',
69545 'Ҥ' => 'ҥ',
69546 'Ҧ' => 'ҧ',
69547 'Ҩ' => 'ҩ',
69548 'Ҫ' => 'ҫ',
69549 'Ҭ' => 'ҭ',
69550 'Ү' => 'ү',
69551 'Ұ' => 'ұ',
69552 'Ҳ' => 'ҳ',
69553 'Ҵ' => 'ҵ',
69554 'Ҷ' => 'ҷ',
69555 'Ҹ' => 'ҹ',
69556 'Һ' => 'һ',
69557 'Ҽ' => 'ҽ',
69558 'Ҿ' => 'ҿ',
69559 'Ӏ' => 'ӏ',
69560 'Ӂ' => 'ӂ',
69561 'Ӄ' => 'ӄ',
69562 'Ӆ' => 'ӆ',
69563 'Ӈ' => 'ӈ',
69564 'Ӊ' => 'ӊ',
69565 'Ӌ' => 'ӌ',
69566 'Ӎ' => 'ӎ',
69567 'Ӑ' => 'ӑ',
69568 'Ӓ' => 'ӓ',
69569 'Ӕ' => 'ӕ',
69570 'Ӗ' => 'ӗ',
69571 'Ә' => 'ә',
69572 'Ӛ' => 'ӛ',
69573 'Ӝ' => 'ӝ',
69574 'Ӟ' => 'ӟ',
69575 'Ӡ' => 'ӡ',
69576 'Ӣ' => 'ӣ',
69577 'Ӥ' => 'ӥ',
69578 'Ӧ' => 'ӧ',
69579 'Ө' => 'ө',
69580 'Ӫ' => 'ӫ',
69581 'Ӭ' => 'ӭ',
69582 'Ӯ' => 'ӯ',
69583 'Ӱ' => 'ӱ',
69584 'Ӳ' => 'ӳ',
69585 'Ӵ' => 'ӵ',
69586 'Ӷ' => 'ӷ',
69587 'Ӹ' => 'ӹ',
69588 'Ӻ' => 'ӻ',
69589 'Ӽ' => 'ӽ',
69590 'Ӿ' => 'ӿ',
69591 'Ԁ' => 'ԁ',
69592 'Ԃ' => 'ԃ',
69593 'Ԅ' => 'ԅ',
69594 'Ԇ' => 'ԇ',
69595 'Ԉ' => 'ԉ',
69596 'Ԋ' => 'ԋ',
69597 'Ԍ' => 'ԍ',
69598 'Ԏ' => 'ԏ',
69599 'Ԑ' => 'ԑ',
69600 'Ԓ' => 'ԓ',
69601 'Ԕ' => 'ԕ',
69602 'Ԗ' => 'ԗ',
69603 'Ԙ' => 'ԙ',
69604 'Ԛ' => 'ԛ',
69605 'Ԝ' => 'ԝ',
69606 'Ԟ' => 'ԟ',
69607 'Ԡ' => 'ԡ',
69608 'Ԣ' => 'ԣ',
69609 'Ԥ' => 'ԥ',
69610 'Ԧ' => 'ԧ',
69611 'Ԩ' => 'ԩ',
69612 'Ԫ' => 'ԫ',
69613 'Ԭ' => 'ԭ',
69614 'Ԯ' => 'ԯ',
69615 'Ա' => 'ա',
69616 'Բ' => 'բ',
69617 'Գ' => 'գ',
69618 'Դ' => 'դ',
69619 'Ե' => 'ե',
69620 'Զ' => 'զ',
69621 'Է' => 'է',
69622 'Ը' => 'ը',
69623 'Թ' => 'թ',
69624 'Ժ' => 'ժ',
69625 'Ի' => 'ի',
69626 'Լ' => 'լ',
69627 'Խ' => 'խ',
69628 'Ծ' => 'ծ',
69629 'Կ' => 'կ',
69630 'Հ' => 'հ',
69631 'Ձ' => 'ձ',
69632 'Ղ' => 'ղ',
69633 'Ճ' => 'ճ',
69634 'Մ' => 'մ',
69635 'Յ' => 'յ',
69636 'Ն' => 'ն',
69637 'Շ' => 'շ',
69638 'Ո' => 'ո',
69639 'Չ' => 'չ',
69640 'Պ' => 'պ',
69641 'Ջ' => 'ջ',
69642 'Ռ' => 'ռ',
69643 'Ս' => 'ս',
69644 'Վ' => 'վ',
69645 'Տ' => 'տ',
69646 'Ր' => 'ր',
69647 'Ց' => 'ց',
69648 'Ւ' => 'ւ',
69649 'Փ' => 'փ',
69650 'Ք' => 'ք',
69651 'Օ' => 'օ',
69652 'Ֆ' => 'ֆ',
69653 'Ⴀ' => 'ⴀ',
69654 'Ⴁ' => 'ⴁ',
69655 'Ⴂ' => 'ⴂ',
69656 'Ⴃ' => 'ⴃ',
69657 'Ⴄ' => 'ⴄ',
69658 'Ⴅ' => 'ⴅ',
69659 'Ⴆ' => 'ⴆ',
69660 'Ⴇ' => 'ⴇ',
69661 'Ⴈ' => 'ⴈ',
69662 'Ⴉ' => 'ⴉ',
69663 'Ⴊ' => 'ⴊ',
69664 'Ⴋ' => 'ⴋ',
69665 'Ⴌ' => 'ⴌ',
69666 'Ⴍ' => 'ⴍ',
69667 'Ⴎ' => 'ⴎ',
69668 'Ⴏ' => 'ⴏ',
69669 'Ⴐ' => 'ⴐ',
69670 'Ⴑ' => 'ⴑ',
69671 'Ⴒ' => 'ⴒ',
69672 'Ⴓ' => 'ⴓ',
69673 'Ⴔ' => 'ⴔ',
69674 'Ⴕ' => 'ⴕ',
69675 'Ⴖ' => 'ⴖ',
69676 'Ⴗ' => 'ⴗ',
69677 'Ⴘ' => 'ⴘ',
69678 'Ⴙ' => 'ⴙ',
69679 'Ⴚ' => 'ⴚ',
69680 'Ⴛ' => 'ⴛ',
69681 'Ⴜ' => 'ⴜ',
69682 'Ⴝ' => 'ⴝ',
69683 'Ⴞ' => 'ⴞ',
69684 'Ⴟ' => 'ⴟ',
69685 'Ⴠ' => 'ⴠ',
69686 'Ⴡ' => 'ⴡ',
69687 'Ⴢ' => 'ⴢ',
69688 'Ⴣ' => 'ⴣ',
69689 'Ⴤ' => 'ⴤ',
69690 'Ⴥ' => 'ⴥ',
69691 'Ⴧ' => 'ⴧ',
69692 'Ⴭ' => 'ⴭ',
69693 'Ḁ' => 'ḁ',
69694 'Ḃ' => 'ḃ',
69695 'Ḅ' => 'ḅ',
69696 'Ḇ' => 'ḇ',
69697 'Ḉ' => 'ḉ',
69698 'Ḋ' => 'ḋ',
69699 'Ḍ' => 'ḍ',
69700 'Ḏ' => 'ḏ',
69701 'Ḑ' => 'ḑ',
69702 'Ḓ' => 'ḓ',
69703 'Ḕ' => 'ḕ',
69704 'Ḗ' => 'ḗ',
69705 'Ḙ' => 'ḙ',
69706 'Ḛ' => 'ḛ',
69707 'Ḝ' => 'ḝ',
69708 'Ḟ' => 'ḟ',
69709 'Ḡ' => 'ḡ',
69710 'Ḣ' => 'ḣ',
69711 'Ḥ' => 'ḥ',
69712 'Ḧ' => 'ḧ',
69713 'Ḩ' => 'ḩ',
69714 'Ḫ' => 'ḫ',
69715 'Ḭ' => 'ḭ',
69716 'Ḯ' => 'ḯ',
69717 'Ḱ' => 'ḱ',
69718 'Ḳ' => 'ḳ',
69719 'Ḵ' => 'ḵ',
69720 'Ḷ' => 'ḷ',
69721 'Ḹ' => 'ḹ',
69722 'Ḻ' => 'ḻ',
69723 'Ḽ' => 'ḽ',
69724 'Ḿ' => 'ḿ',
69725 'Ṁ' => 'ṁ',
69726 'Ṃ' => 'ṃ',
69727 'Ṅ' => 'ṅ',
69728 'Ṇ' => 'ṇ',
69729 'Ṉ' => 'ṉ',
69730 'Ṋ' => 'ṋ',
69731 'Ṍ' => 'ṍ',
69732 'Ṏ' => 'ṏ',
69733 'Ṑ' => 'ṑ',
69734 'Ṓ' => 'ṓ',
69735 'Ṕ' => 'ṕ',
69736 'Ṗ' => 'ṗ',
69737 'Ṙ' => 'ṙ',
69738 'Ṛ' => 'ṛ',
69739 'Ṝ' => 'ṝ',
69740 'Ṟ' => 'ṟ',
69741 'Ṡ' => 'ṡ',
69742 'Ṣ' => 'ṣ',
69743 'Ṥ' => 'ṥ',
69744 'Ṧ' => 'ṧ',
69745 'Ṩ' => 'ṩ',
69746 'Ṫ' => 'ṫ',
69747 'Ṭ' => 'ṭ',
69748 'Ṯ' => 'ṯ',
69749 'Ṱ' => 'ṱ',
69750 'Ṳ' => 'ṳ',
69751 'Ṵ' => 'ṵ',
69752 'Ṷ' => 'ṷ',
69753 'Ṹ' => 'ṹ',
69754 'Ṻ' => 'ṻ',
69755 'Ṽ' => 'ṽ',
69756 'Ṿ' => 'ṿ',
69757 'Ẁ' => 'ẁ',
69758 'Ẃ' => 'ẃ',
69759 'Ẅ' => 'ẅ',
69760 'Ẇ' => 'ẇ',
69761 'Ẉ' => 'ẉ',
69762 'Ẋ' => 'ẋ',
69763 'Ẍ' => 'ẍ',
69764 'Ẏ' => 'ẏ',
69765 'Ẑ' => 'ẑ',
69766 'Ẓ' => 'ẓ',
69767 'Ẕ' => 'ẕ',
69768 'ẞ' => 'ß',
69769 'Ạ' => 'ạ',
69770 'Ả' => 'ả',
69771 'Ấ' => 'ấ',
69772 'Ầ' => 'ầ',
69773 'Ẩ' => 'ẩ',
69774 'Ẫ' => 'ẫ',
69775 'Ậ' => 'ậ',
69776 'Ắ' => 'ắ',
69777 'Ằ' => 'ằ',
69778 'Ẳ' => 'ẳ',
69779 'Ẵ' => 'ẵ',
69780 'Ặ' => 'ặ',
69781 'Ẹ' => 'ẹ',
69782 'Ẻ' => 'ẻ',
69783 'Ẽ' => 'ẽ',
69784 'Ế' => 'ế',
69785 'Ề' => 'ề',
69786 'Ể' => 'ể',
69787 'Ễ' => 'ễ',
69788 'Ệ' => 'ệ',
69789 'Ỉ' => 'ỉ',
69790 'Ị' => 'ị',
69791 'Ọ' => 'ọ',
69792 'Ỏ' => 'ỏ',
69793 'Ố' => 'ố',
69794 'Ồ' => 'ồ',
69795 'Ổ' => 'ổ',
69796 'Ỗ' => 'ỗ',
69797 'Ộ' => 'ộ',
69798 'Ớ' => 'ớ',
69799 'Ờ' => 'ờ',
69800 'Ở' => 'ở',
69801 'Ỡ' => 'ỡ',
69802 'Ợ' => 'ợ',
69803 'Ụ' => 'ụ',
69804 'Ủ' => 'ủ',
69805 'Ứ' => 'ứ',
69806 'Ừ' => 'ừ',
69807 'Ử' => 'ử',
69808 'Ữ' => 'ữ',
69809 'Ự' => 'ự',
69810 'Ỳ' => 'ỳ',
69811 'Ỵ' => 'ỵ',
69812 'Ỷ' => 'ỷ',
69813 'Ỹ' => 'ỹ',
69814 'Ỻ' => 'ỻ',
69815 'Ỽ' => 'ỽ',
69816 'Ỿ' => 'ỿ',
69817 'Ἀ' => 'ἀ',
69818 'Ἁ' => 'ἁ',
69819 'Ἂ' => 'ἂ',
69820 'Ἃ' => 'ἃ',
69821 'Ἄ' => 'ἄ',
69822 'Ἅ' => 'ἅ',
69823 'Ἆ' => 'ἆ',
69824 'Ἇ' => 'ἇ',
69825 'Ἐ' => 'ἐ',
69826 'Ἑ' => 'ἑ',
69827 'Ἒ' => 'ἒ',
69828 'Ἓ' => 'ἓ',
69829 'Ἔ' => 'ἔ',
69830 'Ἕ' => 'ἕ',
69831 'Ἠ' => 'ἠ',
69832 'Ἡ' => 'ἡ',
69833 'Ἢ' => 'ἢ',
69834 'Ἣ' => 'ἣ',
69835 'Ἤ' => 'ἤ',
69836 'Ἥ' => 'ἥ',
69837 'Ἦ' => 'ἦ',
69838 'Ἧ' => 'ἧ',
69839 'Ἰ' => 'ἰ',
69840 'Ἱ' => 'ἱ',
69841 'Ἲ' => 'ἲ',
69842 'Ἳ' => 'ἳ',
69843 'Ἴ' => 'ἴ',
69844 'Ἵ' => 'ἵ',
69845 'Ἶ' => 'ἶ',
69846 'Ἷ' => 'ἷ',
69847 'Ὀ' => 'ὀ',
69848 'Ὁ' => 'ὁ',
69849 'Ὂ' => 'ὂ',
69850 'Ὃ' => 'ὃ',
69851 'Ὄ' => 'ὄ',
69852 'Ὅ' => 'ὅ',
69853 'Ὑ' => 'ὑ',
69854 'Ὓ' => 'ὓ',
69855 'Ὕ' => 'ὕ',
69856 'Ὗ' => 'ὗ',
69857 'Ὠ' => 'ὠ',
69858 'Ὡ' => 'ὡ',
69859 'Ὢ' => 'ὢ',
69860 'Ὣ' => 'ὣ',
69861 'Ὤ' => 'ὤ',
69862 'Ὥ' => 'ὥ',
69863 'Ὦ' => 'ὦ',
69864 'Ὧ' => 'ὧ',
69865 'ᾈ' => 'ᾀ',
69866 'ᾉ' => 'ᾁ',
69867 'ᾊ' => 'ᾂ',
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 'K' => 'k',
69915 'Å' => 'å',
69916 'Ⅎ' => 'ⅎ',
69917 'Ⅰ' => 'ⅰ',
69918 'Ⅱ' => 'ⅱ',
69919 'Ⅲ' => 'ⅲ',
69920 'Ⅳ' => 'ⅳ',
69921 'Ⅴ' => 'ⅴ',
69922 'Ⅵ' => 'ⅵ',
69923 'Ⅶ' => 'ⅶ',
69924 'Ⅷ' => 'ⅷ',
69925 'Ⅸ' => 'ⅸ',
69926 'Ⅹ' => 'ⅹ',
69927 'Ⅺ' => 'ⅺ',
69928 'Ⅻ' => 'ⅻ',
69929 'Ⅼ' => 'ⅼ',
69930 'Ⅽ' => 'ⅽ',
69931 'Ⅾ' => 'ⅾ',
69932 'Ⅿ' => 'ⅿ',
69933 'Ↄ' => 'ↄ',
69934 'Ⓐ' => 'ⓐ',
69935 'Ⓑ' => 'ⓑ',
69936 'Ⓒ' => 'ⓒ',
69937 'Ⓓ' => 'ⓓ',
69938 'Ⓔ' => 'ⓔ',
69939 'Ⓕ' => 'ⓕ',
69940 'Ⓖ' => 'ⓖ',
69941 'Ⓗ' => 'ⓗ',
69942 'Ⓘ' => 'ⓘ',
69943 'Ⓙ' => 'ⓙ',
69944 'Ⓚ' => 'ⓚ',
69945 'Ⓛ' => 'ⓛ',
69946 'Ⓜ' => 'ⓜ',
69947 'Ⓝ' => 'ⓝ',
69948 'Ⓞ' => 'ⓞ',
69949 'Ⓟ' => 'ⓟ',
69950 'Ⓠ' => 'ⓠ',
69951 'Ⓡ' => 'ⓡ',
69952 'Ⓢ' => 'ⓢ',
69953 'Ⓣ' => 'ⓣ',
69954 'Ⓤ' => 'ⓤ',
69955 'Ⓥ' => 'ⓥ',
69956 'Ⓦ' => 'ⓦ',
69957 'Ⓧ' => 'ⓧ',
69958 'Ⓨ' => 'ⓨ',
69959 'Ⓩ' => 'ⓩ',
69960 'Ⰰ' => 'ⰰ',
69961 'Ⰱ' => 'ⰱ',
69962 'Ⰲ' => 'ⰲ',
69963 'Ⰳ' => 'ⰳ',
69964 'Ⰴ' => 'ⰴ',
69965 'Ⰵ' => 'ⰵ',
69966 'Ⰶ' => 'ⰶ',
69967 'Ⰷ' => 'ⰷ',
69968 'Ⰸ' => 'ⰸ',
69969 'Ⰹ' => 'ⰹ',
69970 'Ⰺ' => 'ⰺ',
69971 'Ⰻ' => 'ⰻ',
69972 'Ⰼ' => 'ⰼ',
69973 'Ⰽ' => 'ⰽ',
69974 'Ⰾ' => 'ⰾ',
69975 'Ⰿ' => 'ⰿ',
69976 'Ⱀ' => 'ⱀ',
69977 'Ⱁ' => 'ⱁ',
69978 'Ⱂ' => 'ⱂ',
69979 'Ⱃ' => 'ⱃ',
69980 'Ⱄ' => 'ⱄ',
69981 'Ⱅ' => 'ⱅ',
69982 'Ⱆ' => 'ⱆ',
69983 'Ⱇ' => 'ⱇ',
69984 'Ⱈ' => 'ⱈ',
69985 'Ⱉ' => 'ⱉ',
69986 'Ⱊ' => 'ⱊ',
69987 'Ⱋ' => 'ⱋ',
69988 'Ⱌ' => 'ⱌ',
69989 'Ⱍ' => 'ⱍ',
69990 'Ⱎ' => 'ⱎ',
69991 'Ⱏ' => 'ⱏ',
69992 'Ⱐ' => 'ⱐ',
69993 'Ⱑ' => 'ⱑ',
69994 'Ⱒ' => 'ⱒ',
69995 'Ⱓ' => 'ⱓ',
69996 'Ⱔ' => 'ⱔ',
69997 'Ⱕ' => 'ⱕ',
69998 'Ⱖ' => 'ⱖ',
69999 'Ⱗ' => 'ⱗ',
70000 'Ⱘ' => 'ⱘ',
70001 'Ⱙ' => 'ⱙ',
70002 'Ⱚ' => 'ⱚ',
70003 'Ⱛ' => 'ⱛ',
70004 'Ⱜ' => 'ⱜ',
70005 'Ⱝ' => 'ⱝ',
70006 'Ⱞ' => 'ⱞ',
70007 'Ⱡ' => 'ⱡ',
70008 'Ɫ' => 'ɫ',
70009 'Ᵽ' => 'ᵽ',
70010 'Ɽ' => 'ɽ',
70011 'Ⱨ' => 'ⱨ',
70012 'Ⱪ' => 'ⱪ',
70013 'Ⱬ' => 'ⱬ',
70014 'Ɑ' => 'ɑ',
70015 'Ɱ' => 'ɱ',
70016 'Ɐ' => 'ɐ',
70017 'Ɒ' => 'ɒ',
70018 'Ⱳ' => 'ⱳ',
70019 'Ⱶ' => 'ⱶ',
70020 'Ȿ' => 'ȿ',
70021 'Ɀ' => 'ɀ',
70022 'Ⲁ' => 'ⲁ',
70023 'Ⲃ' => 'ⲃ',
70024 'Ⲅ' => 'ⲅ',
70025 'Ⲇ' => 'ⲇ',
70026 'Ⲉ' => 'ⲉ',
70027 'Ⲋ' => 'ⲋ',
70028 'Ⲍ' => 'ⲍ',
70029 'Ⲏ' => 'ⲏ',
70030 'Ⲑ' => 'ⲑ',
70031 'Ⲓ' => 'ⲓ',
70032 'Ⲕ' => 'ⲕ',
70033 'Ⲗ' => 'ⲗ',
70034 'Ⲙ' => 'ⲙ',
70035 'Ⲛ' => 'ⲛ',
70036 'Ⲝ' => 'ⲝ',
70037 'Ⲟ' => 'ⲟ',
70038 'Ⲡ' => 'ⲡ',
70039 'Ⲣ' => 'ⲣ',
70040 'Ⲥ' => 'ⲥ',
70041 'Ⲧ' => 'ⲧ',
70042 'Ⲩ' => 'ⲩ',
70043 'Ⲫ' => 'ⲫ',
70044 'Ⲭ' => 'ⲭ',
70045 'Ⲯ' => 'ⲯ',
70046 'Ⲱ' => 'ⲱ',
70047 'Ⲳ' => 'ⲳ',
70048 'Ⲵ' => 'ⲵ',
70049 'Ⲷ' => 'ⲷ',
70050 'Ⲹ' => 'ⲹ',
70051 'Ⲻ' => 'ⲻ',
70052 'Ⲽ' => 'ⲽ',
70053 'Ⲿ' => 'ⲿ',
70054 'Ⳁ' => 'ⳁ',
70055 'Ⳃ' => 'ⳃ',
70056 'Ⳅ' => 'ⳅ',
70057 'Ⳇ' => 'ⳇ',
70058 'Ⳉ' => 'ⳉ',
70059 'Ⳋ' => 'ⳋ',
70060 'Ⳍ' => 'ⳍ',
70061 'Ⳏ' => 'ⳏ',
70062 'Ⳑ' => 'ⳑ',
70063 'Ⳓ' => 'ⳓ',
70064 'Ⳕ' => 'ⳕ',
70065 'Ⳗ' => 'ⳗ',
70066 'Ⳙ' => 'ⳙ',
70067 'Ⳛ' => 'ⳛ',
70068 'Ⳝ' => 'ⳝ',
70069 'Ⳟ' => 'ⳟ',
70070 'Ⳡ' => 'ⳡ',
70071 'Ⳣ' => 'ⳣ',
70072 'Ⳬ' => 'ⳬ',
70073 'Ⳮ' => 'ⳮ',
70074 'Ⳳ' => 'ⳳ',
70075 'Ꙁ' => 'ꙁ',
70076 'Ꙃ' => 'ꙃ',
70077 'Ꙅ' => 'ꙅ',
70078 'Ꙇ' => 'ꙇ',
70079 'Ꙉ' => 'ꙉ',
70080 'Ꙋ' => 'ꙋ',
70081 'Ꙍ' => 'ꙍ',
70082 'Ꙏ' => 'ꙏ',
70083 'Ꙑ' => 'ꙑ',
70084 'Ꙓ' => 'ꙓ',
70085 'Ꙕ' => 'ꙕ',
70086 'Ꙗ' => 'ꙗ',
70087 'Ꙙ' => 'ꙙ',
70088 'Ꙛ' => 'ꙛ',
70089 'Ꙝ' => 'ꙝ',
70090 'Ꙟ' => 'ꙟ',
70091 'Ꙡ' => 'ꙡ',
70092 'Ꙣ' => 'ꙣ',
70093 'Ꙥ' => 'ꙥ',
70094 'Ꙧ' => 'ꙧ',
70095 'Ꙩ' => 'ꙩ',
70096 'Ꙫ' => 'ꙫ',
70097 'Ꙭ' => 'ꙭ',
70098 'Ꚁ' => 'ꚁ',
70099 'Ꚃ' => 'ꚃ',
70100 'Ꚅ' => 'ꚅ',
70101 'Ꚇ' => 'ꚇ',
70102 'Ꚉ' => 'ꚉ',
70103 'Ꚋ' => 'ꚋ',
70104 'Ꚍ' => 'ꚍ',
70105 'Ꚏ' => 'ꚏ',
70106 'Ꚑ' => 'ꚑ',
70107 'Ꚓ' => 'ꚓ',
70108 'Ꚕ' => 'ꚕ',
70109 'Ꚗ' => 'ꚗ',
70110 'Ꚙ' => 'ꚙ',
70111 'Ꚛ' => 'ꚛ',
70112 'Ꜣ' => 'ꜣ',
70113 'Ꜥ' => 'ꜥ',
70114 'Ꜧ' => 'ꜧ',
70115 'Ꜩ' => 'ꜩ',
70116 'Ꜫ' => 'ꜫ',
70117 'Ꜭ' => 'ꜭ',
70118 'Ꜯ' => 'ꜯ',
70119 'Ꜳ' => 'ꜳ',
70120 'Ꜵ' => 'ꜵ',
70121 'Ꜷ' => 'ꜷ',
70122 'Ꜹ' => 'ꜹ',
70123 'Ꜻ' => 'ꜻ',
70124 'Ꜽ' => 'ꜽ',
70125 'Ꜿ' => 'ꜿ',
70126 'Ꝁ' => 'ꝁ',
70127 'Ꝃ' => 'ꝃ',
70128 'Ꝅ' => 'ꝅ',
70129 'Ꝇ' => 'ꝇ',
70130 'Ꝉ' => 'ꝉ',
70131 'Ꝋ' => 'ꝋ',
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 'A' => 'a',
70179 'B' => 'b',
70180 'C' => 'c',
70181 'D' => 'd',
70182 'E' => 'e',
70183 'F' => 'f',
70184 'G' => 'g',
70185 'H' => 'h',
70186 'I' => 'i',
70187 'J' => 'j',
70188 'K' => 'k',
70189 'L' => 'l',
70190 'M' => 'm',
70191 'N' => 'n',
70192 'O' => 'o',
70193 'P' => 'p',
70194 'Q' => 'q',
70195 'R' => 'r',
70196 'S' => 's',
70197 'T' => 't',
70198 'U' => 'u',
70199 'V' => 'v',
70200 'W' => 'w',
70201 'X' => 'x',
70202 'Y' => 'y',
70203 'Z' => 'z',
70204 '𐐀' => '𐐨',
70205 '𐐁' => '𐐩',
70206 '𐐂' => '𐐪',
70207 '𐐃' => '𐐫',
70208 '𐐄' => '𐐬',
70209 '𐐅' => '𐐭',
70210 '𐐆' => '𐐮',
70211 '𐐇' => '𐐯',
70212 '𐐈' => '𐐰',
70213 '𐐉' => '𐐱',
70214 '𐐊' => '𐐲',
70215 '𐐋' => '𐐳',
70216 '𐐌' => '𐐴',
70217 '𐐍' => '𐐵',
70218 '𐐎' => '𐐶',
70219 '𐐏' => '𐐷',
70220 '𐐐' => '𐐸',
70221 '𐐑' => '𐐹',
70222 '𐐒' => '𐐺',
70223 '𐐓' => '𐐻',
70224 '𐐔' => '𐐼',
70225 '𐐕' => '𐐽',
70226 '𐐖' => '𐐾',
70227 '𐐗' => '𐐿',
70228 '𐐘' => '𐑀',
70229 '𐐙' => '𐑁',
70230 '𐐚' => '𐑂',
70231 '𐐛' => '𐑃',
70232 '𐐜' => '𐑄',
70233 '𐐝' => '𐑅',
70234 '𐐞' => '𐑆',
70235 '𐐟' => '𐑇',
70236 '𐐠' => '𐑈',
70237 '𐐡' => '𐑉',
70238 '𐐢' => '𐑊',
70239 '𐐣' => '𐑋',
70240 '𐐤' => '𐑌',
70241 '𐐥' => '𐑍',
70242 '𐐦' => '𐑎',
70243 '𐐧' => '𐑏',
70244 '𑢠' => '𑣀',
70245 '𑢡' => '𑣁',
70246 '𑢢' => '𑣂',
70247 '𑢣' => '𑣃',
70248 '𑢤' => '𑣄',
70249 '𑢥' => '𑣅',
70250 '𑢦' => '𑣆',
70251 '𑢧' => '𑣇',
70252 '𑢨' => '𑣈',
70253 '𑢩' => '𑣉',
70254 '𑢪' => '𑣊',
70255 '𑢫' => '𑣋',
70256 '𑢬' => '𑣌',
70257 '𑢭' => '𑣍',
70258 '𑢮' => '𑣎',
70259 '𑢯' => '𑣏',
70260 '𑢰' => '𑣐',
70261 '𑢱' => '𑣑',
70262 '𑢲' => '𑣒',
70263 '𑢳' => '𑣓',
70264 '𑢴' => '𑣔',
70265 '𑢵' => '𑣕',
70266 '𑢶' => '𑣖',
70267 '𑢷' => '𑣗',
70268 '𑢸' => '𑣘',
70269 '𑢹' => '𑣙',
70270 '𑢺' => '𑣚',
70271 '𑢻' => '𑣛',
70272 '𑢼' => '𑣜',
70273 '𑢽' => '𑣝',
70274 '𑢾' => '𑣞',
70275 '𑢿' => '𑣟',
70276 );
70277
70278 $result =& $data;
70279 unset($data);
70280
70281 return $result;
70282 <?php
70283
70284 static $data = array (
70285 'a' => 'A',
70286 'b' => 'B',
70287 'c' => 'C',
70288 'd' => 'D',
70289 'e' => 'E',
70290 'f' => 'F',
70291 'g' => 'G',
70292 'h' => 'H',
70293 'i' => 'I',
70294 'j' => 'J',
70295 'k' => 'K',
70296 'l' => 'L',
70297 'm' => 'M',
70298 'n' => 'N',
70299 'o' => 'O',
70300 'p' => 'P',
70301 'q' => 'Q',
70302 'r' => 'R',
70303 's' => 'S',
70304 't' => 'T',
70305 'u' => 'U',
70306 'v' => 'V',
70307 'w' => 'W',
70308 'x' => 'X',
70309 'y' => 'Y',
70310 'z' => 'Z',
70311 'µ' => 'Μ',
70312 'à' => 'À',
70313 'á' => 'Á',
70314 'â' => 'Â',
70315 'ã' => 'Ã',
70316 'ä' => 'Ä',
70317 'å' => 'Å',
70318 'æ' => 'Æ',
70319 'ç' => 'Ç',
70320 'è' => 'È',
70321 'é' => 'É',
70322 'ê' => 'Ê',
70323 'ë' => 'Ë',
70324 'ì' => 'Ì',
70325 'í' => 'Í',
70326 'î' => 'Î',
70327 'ï' => 'Ï',
70328 'ð' => 'Ð',
70329 'ñ' => 'Ñ',
70330 'ò' => 'Ò',
70331 'ó' => 'Ó',
70332 'ô' => 'Ô',
70333 'õ' => 'Õ',
70334 'ö' => 'Ö',
70335 'ø' => 'Ø',
70336 'ù' => 'Ù',
70337 'ú' => 'Ú',
70338 'û' => 'Û',
70339 'ü' => 'Ü',
70340 'ý' => 'Ý',
70341 'þ' => 'Þ',
70342 'ÿ' => 'Ÿ',
70343 'ā' => 'Ā',
70344 'ă' => 'Ă',
70345 'ą' => 'Ą',
70346 'ć' => 'Ć',
70347 'ĉ' => 'Ĉ',
70348 'ċ' => 'Ċ',
70349 'č' => 'Č',
70350 'ď' => 'Ď',
70351 'đ' => 'Đ',
70352 'ē' => 'Ē',
70353 'ĕ' => 'Ĕ',
70354 'ė' => 'Ė',
70355 'ę' => 'Ę',
70356 'ě' => 'Ě',
70357 'ĝ' => 'Ĝ',
70358 'ğ' => 'Ğ',
70359 'ġ' => 'Ġ',
70360 'ģ' => 'Ģ',
70361 'ĥ' => 'Ĥ',
70362 'ħ' => 'Ħ',
70363 'ĩ' => 'Ĩ',
70364 'ī' => 'Ī',
70365 'ĭ' => 'Ĭ',
70366 'į' => 'Į',
70367 'ı' => 'I',
70368 'ij' => 'IJ',
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 'ſ' => 'S',
70406 'ƀ' => 'Ƀ',
70407 'ƃ' => 'Ƃ',
70408 'ƅ' => 'Ƅ',
70409 'ƈ' => 'Ƈ',
70410 'ƌ' => 'Ƌ',
70411 'ƒ' => 'Ƒ',
70412 'ƕ' => 'Ƕ',
70413 'ƙ' => 'Ƙ',
70414 'ƚ' => 'Ƚ',
70415 'ƞ' => 'Ƞ',
70416 'ơ' => 'Ơ',
70417 'ƣ' => 'Ƣ',
70418 'ƥ' => 'Ƥ',
70419 'ƨ' => 'Ƨ',
70420 'ƭ' => 'Ƭ',
70421 'ư' => 'Ư',
70422 'ƴ' => 'Ƴ',
70423 'ƶ' => 'Ƶ',
70424 'ƹ' => 'Ƹ',
70425 'ƽ' => 'Ƽ',
70426 'ƿ' => 'Ƿ',
70427 'Dž' => 'DŽ',
70428 'dž' => 'DŽ',
70429 'Lj' => 'LJ',
70430 'lj' => 'LJ',
70431 'Nj' => 'NJ',
70432 'nj' => 'NJ',
70433 'ǎ' => 'Ǎ',
70434 'ǐ' => 'Ǐ',
70435 'ǒ' => 'Ǒ',
70436 'ǔ' => 'Ǔ',
70437 'ǖ' => 'Ǖ',
70438 'ǘ' => 'Ǘ',
70439 'ǚ' => 'Ǚ',
70440 'ǜ' => 'Ǜ',
70441 'ǝ' => 'Ǝ',
70442 'ǟ' => 'Ǟ',
70443 'ǡ' => 'Ǡ',
70444 'ǣ' => 'Ǣ',
70445 'ǥ' => 'Ǥ',
70446 'ǧ' => 'Ǧ',
70447 'ǩ' => 'Ǩ',
70448 'ǫ' => 'Ǫ',
70449 'ǭ' => 'Ǭ',
70450 'ǯ' => 'Ǯ',
70451 'Dz' => 'DZ',
70452 'dz' => 'DZ',
70453 'ǵ' => 'Ǵ',
70454 'ǹ' => 'Ǹ',
70455 'ǻ' => 'Ǻ',
70456 'ǽ' => 'Ǽ',
70457 'ǿ' => 'Ǿ',
70458 'ȁ' => 'Ȁ',
70459 'ȃ' => 'Ȃ',
70460 'ȅ' => 'Ȅ',
70461 'ȇ' => 'Ȇ',
70462 'ȉ' => 'Ȉ',
70463 'ȋ' => 'Ȋ',
70464 'ȍ' => 'Ȍ',
70465 'ȏ' => 'Ȏ',
70466 'ȑ' => 'Ȑ',
70467 'ȓ' => 'Ȓ',
70468 'ȕ' => 'Ȕ',
70469 'ȗ' => 'Ȗ',
70470 'ș' => 'Ș',
70471 'ț' => 'Ț',
70472 'ȝ' => 'Ȝ',
70473 'ȟ' => 'Ȟ',
70474 'ȣ' => 'Ȣ',
70475 'ȥ' => 'Ȥ',
70476 'ȧ' => 'Ȧ',
70477 'ȩ' => 'Ȩ',
70478 'ȫ' => 'Ȫ',
70479 'ȭ' => 'Ȭ',
70480 'ȯ' => 'Ȯ',
70481 'ȱ' => 'Ȱ',
70482 'ȳ' => 'Ȳ',
70483 'ȼ' => 'Ȼ',
70484 'ȿ' => 'Ȿ',
70485 'ɀ' => 'Ɀ',
70486 'ɂ' => 'Ɂ',
70487 'ɇ' => 'Ɇ',
70488 'ɉ' => 'Ɉ',
70489 'ɋ' => 'Ɋ',
70490 'ɍ' => 'Ɍ',
70491 'ɏ' => 'Ɏ',
70492 'ɐ' => 'Ɐ',
70493 'ɑ' => 'Ɑ',
70494 'ɒ' => 'Ɒ',
70495 'ɓ' => 'Ɓ',
70496 'ɔ' => 'Ɔ',
70497 'ɖ' => 'Ɖ',
70498 'ɗ' => 'Ɗ',
70499 'ə' => 'Ə',
70500 'ɛ' => 'Ɛ',
70501 'ɜ' => 'Ɜ',
70502 'ɠ' => 'Ɠ',
70503 'ɡ' => 'Ɡ',
70504 'ɣ' => 'Ɣ',
70505 'ɥ' => 'Ɥ',
70506 'ɦ' => 'Ɦ',
70507 'ɨ' => 'Ɨ',
70508 'ɩ' => 'Ɩ',
70509 'ɫ' => 'Ɫ',
70510 'ɬ' => 'Ɬ',
70511 'ɯ' => 'Ɯ',
70512 'ɱ' => 'Ɱ',
70513 'ɲ' => 'Ɲ',
70514 'ɵ' => 'Ɵ',
70515 'ɽ' => 'Ɽ',
70516 'ʀ' => 'Ʀ',
70517 'ʃ' => 'Ʃ',
70518 'ʇ' => 'Ʇ',
70519 'ʈ' => 'Ʈ',
70520 'ʉ' => 'Ʉ',
70521 'ʊ' => 'Ʊ',
70522 'ʋ' => 'Ʋ',
70523 'ʌ' => 'Ʌ',
70524 'ʒ' => 'Ʒ',
70525 'ʞ' => 'Ʞ',
70526 'ͅ' => 'Ι',
70527 'ͱ' => 'Ͱ',
70528 'ͳ' => 'Ͳ',
70529 'ͷ' => 'Ͷ',
70530 'ͻ' => 'Ͻ',
70531 'ͼ' => 'Ͼ',
70532 'ͽ' => 'Ͽ',
70533 'ά' => 'Ά',
70534 'έ' => 'Έ',
70535 'ή' => 'Ή',
70536 'ί' => 'Ί',
70537 'α' => 'Α',
70538 'β' => 'Β',
70539 'γ' => 'Γ',
70540 'δ' => 'Δ',
70541 'ε' => 'Ε',
70542 'ζ' => 'Ζ',
70543 'η' => 'Η',
70544 'θ' => 'Θ',
70545 'ι' => 'Ι',
70546 'κ' => 'Κ',
70547 'λ' => 'Λ',
70548 'μ' => 'Μ',
70549 'ν' => 'Ν',
70550 'ξ' => 'Ξ',
70551 'ο' => 'Ο',
70552 'π' => 'Π',
70553 'ρ' => 'Ρ',
70554 'ς' => 'Σ',
70555 'σ' => 'Σ',
70556 'τ' => 'Τ',
70557 'υ' => 'Υ',
70558 'φ' => 'Φ',
70559 'χ' => 'Χ',
70560 'ψ' => 'Ψ',
70561 'ω' => 'Ω',
70562 'ϊ' => 'Ϊ',
70563 'ϋ' => 'Ϋ',
70564 'ό' => 'Ό',
70565 'ύ' => 'Ύ',
70566 'ώ' => 'Ώ',
70567 'ϐ' => 'Β',
70568 'ϑ' => 'Θ',
70569 'ϕ' => 'Φ',
70570 'ϖ' => 'Π',
70571 'ϗ' => 'Ϗ',
70572 'ϙ' => 'Ϙ',
70573 'ϛ' => 'Ϛ',
70574 'ϝ' => 'Ϝ',
70575 'ϟ' => 'Ϟ',
70576 'ϡ' => 'Ϡ',
70577 'ϣ' => 'Ϣ',
70578 'ϥ' => 'Ϥ',
70579 'ϧ' => 'Ϧ',
70580 'ϩ' => 'Ϩ',
70581 'ϫ' => 'Ϫ',
70582 'ϭ' => 'Ϭ',
70583 'ϯ' => 'Ϯ',
70584 'ϰ' => 'Κ',
70585 'ϱ' => 'Ρ',
70586 'ϲ' => 'Ϲ',
70587 'ϳ' => 'Ϳ',
70588 'ϵ' => 'Ε',
70589 'ϸ' => 'Ϸ',
70590 'ϻ' => 'Ϻ',
70591 'а' => 'А',
70592 'б' => 'Б',
70593 'в' => 'В',
70594 'г' => 'Г',
70595 'д' => 'Д',
70596 'е' => 'Е',
70597 'ж' => 'Ж',
70598 'з' => 'З',
70599 'и' => 'И',
70600 'й' => 'Й',
70601 'к' => 'К',
70602 'л' => 'Л',
70603 'м' => 'М',
70604 'н' => 'Н',
70605 'о' => 'О',
70606 'п' => 'П',
70607 'р' => 'Р',
70608 'с' => 'С',
70609 'т' => 'Т',
70610 'у' => 'У',
70611 'ф' => 'Ф',
70612 'х' => 'Х',
70613 'ц' => 'Ц',
70614 'ч' => 'Ч',
70615 'ш' => 'Ш',
70616 'щ' => 'Щ',
70617 'ъ' => 'Ъ',
70618 'ы' => 'Ы',
70619 'ь' => 'Ь',
70620 'э' => 'Э',
70621 'ю' => 'Ю',
70622 'я' => 'Я',
70623 'ѐ' => 'Ѐ',
70624 'ё' => 'Ё',
70625 'ђ' => 'Ђ',
70626 'ѓ' => 'Ѓ',
70627 'є' => 'Є',
70628 'ѕ' => 'Ѕ',
70629 'і' => 'І',
70630 'ї' => 'Ї',
70631 'ј' => 'Ј',
70632 'љ' => 'Љ',
70633 'њ' => 'Њ',
70634 'ћ' => 'Ћ',
70635 'ќ' => 'Ќ',
70636 'ѝ' => 'Ѝ',
70637 'ў' => 'Ў',
70638 'џ' => 'Џ',
70639 'ѡ' => 'Ѡ',
70640 'ѣ' => 'Ѣ',
70641 'ѥ' => 'Ѥ',
70642 'ѧ' => 'Ѧ',
70643 'ѩ' => 'Ѩ',
70644 'ѫ' => 'Ѫ',
70645 'ѭ' => 'Ѭ',
70646 'ѯ' => 'Ѯ',
70647 'ѱ' => 'Ѱ',
70648 'ѳ' => 'Ѳ',
70649 'ѵ' => 'Ѵ',
70650 'ѷ' => 'Ѷ',
70651 'ѹ' => 'Ѹ',
70652 'ѻ' => 'Ѻ',
70653 'ѽ' => 'Ѽ',
70654 'ѿ' => 'Ѿ',
70655 'ҁ' => 'Ҁ',
70656 'ҋ' => 'Ҋ',
70657 'ҍ' => 'Ҍ',
70658 'ҏ' => 'Ҏ',
70659 'ґ' => 'Ґ',
70660 'ғ' => 'Ғ',
70661 'ҕ' => 'Ҕ',
70662 'җ' => 'Җ',
70663 'ҙ' => 'Ҙ',
70664 'қ' => 'Қ',
70665 'ҝ' => 'Ҝ',
70666 'ҟ' => 'Ҟ',
70667 'ҡ' => 'Ҡ',
70668 'ң' => 'Ң',
70669 'ҥ' => 'Ҥ',
70670 'ҧ' => 'Ҧ',
70671 'ҩ' => 'Ҩ',
70672 'ҫ' => 'Ҫ',
70673 'ҭ' => 'Ҭ',
70674 'ү' => 'Ү',
70675 'ұ' => 'Ұ',
70676 'ҳ' => 'Ҳ',
70677 'ҵ' => 'Ҵ',
70678 'ҷ' => 'Ҷ',
70679 'ҹ' => 'Ҹ',
70680 'һ' => 'Һ',
70681 'ҽ' => 'Ҽ',
70682 'ҿ' => 'Ҿ',
70683 'ӂ' => 'Ӂ',
70684 'ӄ' => 'Ӄ',
70685 'ӆ' => 'Ӆ',
70686 'ӈ' => 'Ӈ',
70687 'ӊ' => 'Ӊ',
70688 'ӌ' => 'Ӌ',
70689 'ӎ' => 'Ӎ',
70690 'ӏ' => 'Ӏ',
70691 'ӑ' => 'Ӑ',
70692 'ӓ' => 'Ӓ',
70693 'ӕ' => 'Ӕ',
70694 'ӗ' => 'Ӗ',
70695 'ә' => 'Ә',
70696 'ӛ' => 'Ӛ',
70697 'ӝ' => 'Ӝ',
70698 'ӟ' => 'Ӟ',
70699 'ӡ' => 'Ӡ',
70700 'ӣ' => 'Ӣ',
70701 'ӥ' => 'Ӥ',
70702 'ӧ' => 'Ӧ',
70703 'ө' => 'Ө',
70704 'ӫ' => 'Ӫ',
70705 'ӭ' => 'Ӭ',
70706 'ӯ' => 'Ӯ',
70707 'ӱ' => 'Ӱ',
70708 'ӳ' => 'Ӳ',
70709 'ӵ' => 'Ӵ',
70710 'ӷ' => 'Ӷ',
70711 'ӹ' => 'Ӹ',
70712 'ӻ' => 'Ӻ',
70713 'ӽ' => 'Ӽ',
70714 'ӿ' => 'Ӿ',
70715 'ԁ' => 'Ԁ',
70716 'ԃ' => 'Ԃ',
70717 'ԅ' => 'Ԅ',
70718 'ԇ' => 'Ԇ',
70719 'ԉ' => 'Ԉ',
70720 'ԋ' => 'Ԋ',
70721 'ԍ' => 'Ԍ',
70722 'ԏ' => 'Ԏ',
70723 'ԑ' => 'Ԑ',
70724 'ԓ' => 'Ԓ',
70725 'ԕ' => 'Ԕ',
70726 'ԗ' => 'Ԗ',
70727 'ԙ' => 'Ԙ',
70728 'ԛ' => 'Ԛ',
70729 'ԝ' => 'Ԝ',
70730 'ԟ' => 'Ԟ',
70731 'ԡ' => 'Ԡ',
70732 'ԣ' => 'Ԣ',
70733 'ԥ' => 'Ԥ',
70734 'ԧ' => 'Ԧ',
70735 'ԩ' => 'Ԩ',
70736 'ԫ' => 'Ԫ',
70737 'ԭ' => 'Ԭ',
70738 'ԯ' => 'Ԯ',
70739 'ա' => 'Ա',
70740 'բ' => 'Բ',
70741 'գ' => 'Գ',
70742 'դ' => 'Դ',
70743 'ե' => 'Ե',
70744 'զ' => 'Զ',
70745 'է' => 'Է',
70746 'ը' => 'Ը',
70747 'թ' => 'Թ',
70748 'ժ' => 'Ժ',
70749 'ի' => 'Ի',
70750 'լ' => 'Լ',
70751 'խ' => 'Խ',
70752 'ծ' => 'Ծ',
70753 'կ' => 'Կ',
70754 'հ' => 'Հ',
70755 'ձ' => 'Ձ',
70756 'ղ' => 'Ղ',
70757 'ճ' => 'Ճ',
70758 'մ' => 'Մ',
70759 'յ' => 'Յ',
70760 'ն' => 'Ն',
70761 'շ' => 'Շ',
70762 'ո' => 'Ո',
70763 'չ' => 'Չ',
70764 'պ' => 'Պ',
70765 'ջ' => 'Ջ',
70766 'ռ' => 'Ռ',
70767 'ս' => 'Ս',
70768 'վ' => 'Վ',
70769 'տ' => 'Տ',
70770 'ր' => 'Ր',
70771 'ց' => 'Ց',
70772 'ւ' => 'Ւ',
70773 'փ' => 'Փ',
70774 'ք' => 'Ք',
70775 'օ' => 'Օ',
70776 'ֆ' => 'Ֆ',
70777 'ᵹ' => 'Ᵹ',
70778 'ᵽ' => 'Ᵽ',
70779 'ḁ' => 'Ḁ',
70780 'ḃ' => 'Ḃ',
70781 'ḅ' => 'Ḅ',
70782 'ḇ' => 'Ḇ',
70783 'ḉ' => 'Ḉ',
70784 'ḋ' => 'Ḋ',
70785 'ḍ' => 'Ḍ',
70786 'ḏ' => 'Ḏ',
70787 'ḑ' => 'Ḑ',
70788 'ḓ' => 'Ḓ',
70789 'ḕ' => 'Ḕ',
70790 'ḗ' => 'Ḗ',
70791 'ḙ' => 'Ḙ',
70792 'ḛ' => 'Ḛ',
70793 'ḝ' => 'Ḝ',
70794 'ḟ' => 'Ḟ',
70795 'ḡ' => 'Ḡ',
70796 'ḣ' => 'Ḣ',
70797 'ḥ' => 'Ḥ',
70798 'ḧ' => 'Ḧ',
70799 'ḩ' => 'Ḩ',
70800 'ḫ' => 'Ḫ',
70801 'ḭ' => 'Ḭ',
70802 'ḯ' => 'Ḯ',
70803 'ḱ' => 'Ḱ',
70804 'ḳ' => 'Ḳ',
70805 'ḵ' => 'Ḵ',
70806 'ḷ' => 'Ḷ',
70807 'ḹ' => 'Ḹ',
70808 'ḻ' => 'Ḻ',
70809 'ḽ' => 'Ḽ',
70810 'ḿ' => 'Ḿ',
70811 'ṁ' => 'Ṁ',
70812 'ṃ' => 'Ṃ',
70813 'ṅ' => 'Ṅ',
70814 'ṇ' => 'Ṇ',
70815 'ṉ' => 'Ṉ',
70816 'ṋ' => 'Ṋ',
70817 'ṍ' => 'Ṍ',
70818 'ṏ' => 'Ṏ',
70819 'ṑ' => 'Ṑ',
70820 'ṓ' => 'Ṓ',
70821 'ṕ' => 'Ṕ',
70822 'ṗ' => 'Ṗ',
70823 'ṙ' => 'Ṙ',
70824 'ṛ' => 'Ṛ',
70825 'ṝ' => 'Ṝ',
70826 'ṟ' => 'Ṟ',
70827 'ṡ' => 'Ṡ',
70828 'ṣ' => 'Ṣ',
70829 'ṥ' => 'Ṥ',
70830 'ṧ' => 'Ṧ',
70831 'ṩ' => 'Ṩ',
70832 'ṫ' => 'Ṫ',
70833 'ṭ' => 'Ṭ',
70834 'ṯ' => 'Ṯ',
70835 'ṱ' => 'Ṱ',
70836 'ṳ' => 'Ṳ',
70837 'ṵ' => 'Ṵ',
70838 'ṷ' => 'Ṷ',
70839 'ṹ' => 'Ṹ',
70840 'ṻ' => 'Ṻ',
70841 'ṽ' => 'Ṽ',
70842 'ṿ' => 'Ṿ',
70843 'ẁ' => 'Ẁ',
70844 'ẃ' => 'Ẃ',
70845 'ẅ' => 'Ẅ',
70846 'ẇ' => 'Ẇ',
70847 'ẉ' => 'Ẉ',
70848 'ẋ' => 'Ẋ',
70849 'ẍ' => 'Ẍ',
70850 'ẏ' => 'Ẏ',
70851 'ẑ' => 'Ẑ',
70852 'ẓ' => 'Ẓ',
70853 'ẕ' => 'Ẕ',
70854 'ẛ' => 'Ṡ',
70855 'ạ' => 'Ạ',
70856 'ả' => 'Ả',
70857 'ấ' => 'Ấ',
70858 'ầ' => 'Ầ',
70859 'ẩ' => 'Ẩ',
70860 'ẫ' => 'Ẫ',
70861 'ậ' => 'Ậ',
70862 'ắ' => 'Ắ',
70863 'ằ' => 'Ằ',
70864 'ẳ' => 'Ẳ',
70865 'ẵ' => 'Ẵ',
70866 'ặ' => 'Ặ',
70867 'ẹ' => 'Ẹ',
70868 'ẻ' => 'Ẻ',
70869 'ẽ' => 'Ẽ',
70870 'ế' => 'Ế',
70871 'ề' => 'Ề',
70872 'ể' => 'Ể',
70873 'ễ' => 'Ễ',
70874 'ệ' => 'Ệ',
70875 'ỉ' => 'Ỉ',
70876 'ị' => 'Ị',
70877 'ọ' => 'Ọ',
70878 'ỏ' => 'Ỏ',
70879 'ố' => 'Ố',
70880 'ồ' => 'Ồ',
70881 'ổ' => 'Ổ',
70882 'ỗ' => 'Ỗ',
70883 'ộ' => 'Ộ',
70884 'ớ' => 'Ớ',
70885 'ờ' => 'Ờ',
70886 'ở' => 'Ở',
70887 'ỡ' => 'Ỡ',
70888 'ợ' => 'Ợ',
70889 'ụ' => 'Ụ',
70890 'ủ' => 'Ủ',
70891 'ứ' => 'Ứ',
70892 'ừ' => 'Ừ',
70893 'ử' => 'Ử',
70894 'ữ' => 'Ữ',
70895 'ự' => 'Ự',
70896 'ỳ' => 'Ỳ',
70897 'ỵ' => 'Ỵ',
70898 'ỷ' => 'Ỷ',
70899 'ỹ' => 'Ỹ',
70900 'ỻ' => 'Ỻ',
70901 'ỽ' => 'Ỽ',
70902 'ỿ' => 'Ỿ',
70903 'ἀ' => 'Ἀ',
70904 'ἁ' => 'Ἁ',
70905 'ἂ' => 'Ἂ',
70906 'ἃ' => 'Ἃ',
70907 'ἄ' => 'Ἄ',
70908 'ἅ' => 'Ἅ',
70909 'ἆ' => 'Ἆ',
70910 'ἇ' => 'Ἇ',
70911 'ἐ' => 'Ἐ',
70912 'ἑ' => 'Ἑ',
70913 'ἒ' => 'Ἒ',
70914 'ἓ' => 'Ἓ',
70915 'ἔ' => 'Ἔ',
70916 'ἕ' => 'Ἕ',
70917 'ἠ' => 'Ἠ',
70918 'ἡ' => 'Ἡ',
70919 'ἢ' => 'Ἢ',
70920 'ἣ' => 'Ἣ',
70921 'ἤ' => 'Ἤ',
70922 'ἥ' => 'Ἥ',
70923 'ἦ' => 'Ἦ',
70924 'ἧ' => 'Ἧ',
70925 'ἰ' => 'Ἰ',
70926 'ἱ' => 'Ἱ',
70927 'ἲ' => 'Ἲ',
70928 'ἳ' => 'Ἳ',
70929 'ἴ' => 'Ἴ',
70930 'ἵ' => 'Ἵ',
70931 'ἶ' => 'Ἶ',
70932 'ἷ' => 'Ἷ',
70933 'ὀ' => 'Ὀ',
70934 'ὁ' => 'Ὁ',
70935 'ὂ' => 'Ὂ',
70936 'ὃ' => 'Ὃ',
70937 'ὄ' => 'Ὄ',
70938 'ὅ' => 'Ὅ',
70939 'ὑ' => 'Ὑ',
70940 'ὓ' => 'Ὓ',
70941 'ὕ' => 'Ὕ',
70942 'ὗ' => 'Ὗ',
70943 'ὠ' => 'Ὠ',
70944 'ὡ' => 'Ὡ',
70945 'ὢ' => 'Ὢ',
70946 'ὣ' => 'Ὣ',
70947 'ὤ' => 'Ὤ',
70948 'ὥ' => 'Ὥ',
70949 'ὦ' => 'Ὦ',
70950 'ὧ' => 'Ὧ',
70951 'ὰ' => 'Ὰ',
70952 'ά' => 'Ά',
70953 'ὲ' => 'Ὲ',
70954 'έ' => 'Έ',
70955 'ὴ' => 'Ὴ',
70956 'ή' => 'Ή',
70957 'ὶ' => 'Ὶ',
70958 'ί' => 'Ί',
70959 'ὸ' => 'Ὸ',
70960 'ό' => 'Ό',
70961 'ὺ' => 'Ὺ',
70962 'ύ' => 'Ύ',
70963 'ὼ' => 'Ὼ',
70964 'ώ' => 'Ώ',
70965 'ᾀ' => 'ᾈ',
70966 'ᾁ' => 'ᾉ',
70967 'ᾂ' => 'ᾊ',
70968 'ᾃ' => 'ᾋ',
70969 'ᾄ' => 'ᾌ',
70970 'ᾅ' => 'ᾍ',
70971 'ᾆ' => 'ᾎ',
70972 'ᾇ' => 'ᾏ',
70973 'ᾐ' => 'ᾘ',
70974 'ᾑ' => 'ᾙ',
70975 'ᾒ' => 'ᾚ',
70976 'ᾓ' => 'ᾛ',
70977 'ᾔ' => 'ᾜ',
70978 'ᾕ' => 'ᾝ',
70979 'ᾖ' => 'ᾞ',
70980 'ᾗ' => 'ᾟ',
70981 'ᾠ' => 'ᾨ',
70982 'ᾡ' => 'ᾩ',
70983 'ᾢ' => 'ᾪ',
70984 'ᾣ' => 'ᾫ',
70985 'ᾤ' => 'ᾬ',
70986 'ᾥ' => 'ᾭ',
70987 'ᾦ' => 'ᾮ',
70988 'ᾧ' => 'ᾯ',
70989 'ᾰ' => 'Ᾰ',
70990 'ᾱ' => 'Ᾱ',
70991 'ᾳ' => 'ᾼ',
70992 'ι' => 'Ι',
70993 'ῃ' => 'ῌ',
70994 'ῐ' => 'Ῐ',
70995 'ῑ' => 'Ῑ',
70996 'ῠ' => 'Ῠ',
70997 'ῡ' => 'Ῡ',
70998 'ῥ' => 'Ῥ',
70999 'ῳ' => 'ῼ',
71000 'ⅎ' => 'Ⅎ',
71001 'ⅰ' => 'Ⅰ',
71002 'ⅱ' => 'Ⅱ',
71003 'ⅲ' => 'Ⅲ',
71004 'ⅳ' => 'Ⅳ',
71005 'ⅴ' => 'Ⅴ',
71006 'ⅵ' => 'Ⅵ',
71007 'ⅶ' => 'Ⅶ',
71008 'ⅷ' => 'Ⅷ',
71009 'ⅸ' => 'Ⅸ',
71010 'ⅹ' => 'Ⅹ',
71011 'ⅺ' => 'Ⅺ',
71012 'ⅻ' => 'Ⅻ',
71013 'ⅼ' => 'Ⅼ',
71014 'ⅽ' => 'Ⅽ',
71015 'ⅾ' => 'Ⅾ',
71016 'ⅿ' => 'Ⅿ',
71017 'ↄ' => 'Ↄ',
71018 'ⓐ' => 'Ⓐ',
71019 'ⓑ' => 'Ⓑ',
71020 'ⓒ' => 'Ⓒ',
71021 'ⓓ' => 'Ⓓ',
71022 'ⓔ' => 'Ⓔ',
71023 'ⓕ' => 'Ⓕ',
71024 'ⓖ' => 'Ⓖ',
71025 'ⓗ' => 'Ⓗ',
71026 'ⓘ' => 'Ⓘ',
71027 'ⓙ' => 'Ⓙ',
71028 'ⓚ' => 'Ⓚ',
71029 'ⓛ' => 'Ⓛ',
71030 'ⓜ' => 'Ⓜ',
71031 'ⓝ' => 'Ⓝ',
71032 'ⓞ' => 'Ⓞ',
71033 'ⓟ' => 'Ⓟ',
71034 'ⓠ' => 'Ⓠ',
71035 'ⓡ' => 'Ⓡ',
71036 'ⓢ' => 'Ⓢ',
71037 'ⓣ' => 'Ⓣ',
71038 'ⓤ' => 'Ⓤ',
71039 'ⓥ' => 'Ⓥ',
71040 'ⓦ' => 'Ⓦ',
71041 'ⓧ' => 'Ⓧ',
71042 'ⓨ' => 'Ⓨ',
71043 'ⓩ' => 'Ⓩ',
71044 'ⰰ' => 'Ⰰ',
71045 'ⰱ' => 'Ⰱ',
71046 'ⰲ' => 'Ⰲ',
71047 'ⰳ' => 'Ⰳ',
71048 'ⰴ' => 'Ⰴ',
71049 'ⰵ' => 'Ⰵ',
71050 'ⰶ' => 'Ⰶ',
71051 'ⰷ' => 'Ⰷ',
71052 'ⰸ' => 'Ⰸ',
71053 'ⰹ' => 'Ⰹ',
71054 'ⰺ' => 'Ⰺ',
71055 'ⰻ' => 'Ⰻ',
71056 'ⰼ' => 'Ⰼ',
71057 'ⰽ' => 'Ⰽ',
71058 'ⰾ' => 'Ⰾ',
71059 'ⰿ' => 'Ⰿ',
71060 'ⱀ' => 'Ⱀ',
71061 'ⱁ' => 'Ⱁ',
71062 'ⱂ' => 'Ⱂ',
71063 'ⱃ' => 'Ⱃ',
71064 'ⱄ' => 'Ⱄ',
71065 'ⱅ' => 'Ⱅ',
71066 'ⱆ' => 'Ⱆ',
71067 'ⱇ' => 'Ⱇ',
71068 'ⱈ' => 'Ⱈ',
71069 'ⱉ' => 'Ⱉ',
71070 'ⱊ' => 'Ⱊ',
71071 'ⱋ' => 'Ⱋ',
71072 'ⱌ' => 'Ⱌ',
71073 'ⱍ' => 'Ⱍ',
71074 'ⱎ' => 'Ⱎ',
71075 'ⱏ' => 'Ⱏ',
71076 'ⱐ' => 'Ⱐ',
71077 'ⱑ' => 'Ⱑ',
71078 'ⱒ' => 'Ⱒ',
71079 'ⱓ' => 'Ⱓ',
71080 'ⱔ' => 'Ⱔ',
71081 'ⱕ' => 'Ⱕ',
71082 'ⱖ' => 'Ⱖ',
71083 'ⱗ' => 'Ⱗ',
71084 'ⱘ' => 'Ⱘ',
71085 'ⱙ' => 'Ⱙ',
71086 'ⱚ' => 'Ⱚ',
71087 'ⱛ' => 'Ⱛ',
71088 'ⱜ' => 'Ⱜ',
71089 'ⱝ' => 'Ⱝ',
71090 'ⱞ' => 'Ⱞ',
71091 'ⱡ' => 'Ⱡ',
71092 'ⱥ' => 'Ⱥ',
71093 'ⱦ' => 'Ⱦ',
71094 'ⱨ' => 'Ⱨ',
71095 'ⱪ' => 'Ⱪ',
71096 'ⱬ' => 'Ⱬ',
71097 'ⱳ' => 'Ⱳ',
71098 'ⱶ' => 'Ⱶ',
71099 'ⲁ' => 'Ⲁ',
71100 'ⲃ' => 'Ⲃ',
71101 'ⲅ' => 'Ⲅ',
71102 'ⲇ' => 'Ⲇ',
71103 'ⲉ' => 'Ⲉ',
71104 'ⲋ' => 'Ⲋ',
71105 'ⲍ' => 'Ⲍ',
71106 'ⲏ' => 'Ⲏ',
71107 'ⲑ' => 'Ⲑ',
71108 'ⲓ' => 'Ⲓ',
71109 'ⲕ' => 'Ⲕ',
71110 'ⲗ' => 'Ⲗ',
71111 'ⲙ' => 'Ⲙ',
71112 'ⲛ' => 'Ⲛ',
71113 'ⲝ' => 'Ⲝ',
71114 'ⲟ' => 'Ⲟ',
71115 'ⲡ' => 'Ⲡ',
71116 'ⲣ' => 'Ⲣ',
71117 'ⲥ' => 'Ⲥ',
71118 'ⲧ' => 'Ⲧ',
71119 'ⲩ' => 'Ⲩ',
71120 'ⲫ' => 'Ⲫ',
71121 'ⲭ' => 'Ⲭ',
71122 'ⲯ' => 'Ⲯ',
71123 'ⲱ' => 'Ⲱ',
71124 'ⲳ' => 'Ⲳ',
71125 'ⲵ' => 'Ⲵ',
71126 'ⲷ' => 'Ⲷ',
71127 'ⲹ' => 'Ⲹ',
71128 'ⲻ' => 'Ⲻ',
71129 'ⲽ' => 'Ⲽ',
71130 'ⲿ' => 'Ⲿ',
71131 'ⳁ' => 'Ⳁ',
71132 'ⳃ' => 'Ⳃ',
71133 'ⳅ' => 'Ⳅ',
71134 'ⳇ' => 'Ⳇ',
71135 'ⳉ' => 'Ⳉ',
71136 'ⳋ' => 'Ⳋ',
71137 'ⳍ' => 'Ⳍ',
71138 'ⳏ' => 'Ⳏ',
71139 'ⳑ' => 'Ⳑ',
71140 'ⳓ' => 'Ⳓ',
71141 'ⳕ' => 'Ⳕ',
71142 'ⳗ' => 'Ⳗ',
71143 'ⳙ' => 'Ⳙ',
71144 'ⳛ' => 'Ⳛ',
71145 'ⳝ' => 'Ⳝ',
71146 'ⳟ' => 'Ⳟ',
71147 'ⳡ' => 'Ⳡ',
71148 'ⳣ' => 'Ⳣ',
71149 'ⳬ' => 'Ⳬ',
71150 'ⳮ' => 'Ⳮ',
71151 'ⳳ' => 'Ⳳ',
71152 'ⴀ' => 'Ⴀ',
71153 'ⴁ' => 'Ⴁ',
71154 'ⴂ' => 'Ⴂ',
71155 'ⴃ' => 'Ⴃ',
71156 'ⴄ' => 'Ⴄ',
71157 'ⴅ' => 'Ⴅ',
71158 'ⴆ' => 'Ⴆ',
71159 'ⴇ' => 'Ⴇ',
71160 'ⴈ' => 'Ⴈ',
71161 'ⴉ' => 'Ⴉ',
71162 'ⴊ' => 'Ⴊ',
71163 'ⴋ' => 'Ⴋ',
71164 'ⴌ' => 'Ⴌ',
71165 'ⴍ' => 'Ⴍ',
71166 'ⴎ' => 'Ⴎ',
71167 'ⴏ' => 'Ⴏ',
71168 'ⴐ' => 'Ⴐ',
71169 'ⴑ' => 'Ⴑ',
71170 'ⴒ' => 'Ⴒ',
71171 'ⴓ' => 'Ⴓ',
71172 'ⴔ' => 'Ⴔ',
71173 'ⴕ' => 'Ⴕ',
71174 'ⴖ' => 'Ⴖ',
71175 'ⴗ' => 'Ⴗ',
71176 'ⴘ' => 'Ⴘ',
71177 'ⴙ' => 'Ⴙ',
71178 'ⴚ' => 'Ⴚ',
71179 'ⴛ' => 'Ⴛ',
71180 'ⴜ' => 'Ⴜ',
71181 'ⴝ' => 'Ⴝ',
71182 'ⴞ' => 'Ⴞ',
71183 'ⴟ' => 'Ⴟ',
71184 'ⴠ' => 'Ⴠ',
71185 'ⴡ' => 'Ⴡ',
71186 'ⴢ' => 'Ⴢ',
71187 'ⴣ' => 'Ⴣ',
71188 'ⴤ' => 'Ⴤ',
71189 'ⴥ' => 'Ⴥ',
71190 'ⴧ' => 'Ⴧ',
71191 'ⴭ' => 'Ⴭ',
71192 'ꙁ' => 'Ꙁ',
71193 'ꙃ' => 'Ꙃ',
71194 'ꙅ' => 'Ꙅ',
71195 'ꙇ' => 'Ꙇ',
71196 'ꙉ' => 'Ꙉ',
71197 'ꙋ' => 'Ꙋ',
71198 'ꙍ' => 'Ꙍ',
71199 'ꙏ' => 'Ꙏ',
71200 'ꙑ' => 'Ꙑ',
71201 'ꙓ' => 'Ꙓ',
71202 'ꙕ' => 'Ꙕ',
71203 'ꙗ' => 'Ꙗ',
71204 'ꙙ' => 'Ꙙ',
71205 'ꙛ' => 'Ꙛ',
71206 'ꙝ' => 'Ꙝ',
71207 'ꙟ' => 'Ꙟ',
71208 'ꙡ' => 'Ꙡ',
71209 'ꙣ' => 'Ꙣ',
71210 'ꙥ' => 'Ꙥ',
71211 'ꙧ' => 'Ꙧ',
71212 'ꙩ' => 'Ꙩ',
71213 'ꙫ' => 'Ꙫ',
71214 'ꙭ' => 'Ꙭ',
71215 'ꚁ' => 'Ꚁ',
71216 'ꚃ' => 'Ꚃ',
71217 'ꚅ' => 'Ꚅ',
71218 'ꚇ' => 'Ꚇ',
71219 'ꚉ' => 'Ꚉ',
71220 'ꚋ' => 'Ꚋ',
71221 'ꚍ' => 'Ꚍ',
71222 'ꚏ' => 'Ꚏ',
71223 'ꚑ' => 'Ꚑ',
71224 'ꚓ' => 'Ꚓ',
71225 'ꚕ' => 'Ꚕ',
71226 'ꚗ' => 'Ꚗ',
71227 'ꚙ' => 'Ꚙ',
71228 'ꚛ' => 'Ꚛ',
71229 'ꜣ' => 'Ꜣ',
71230 'ꜥ' => 'Ꜥ',
71231 'ꜧ' => 'Ꜧ',
71232 'ꜩ' => 'Ꜩ',
71233 'ꜫ' => 'Ꜫ',
71234 'ꜭ' => 'Ꜭ',
71235 'ꜯ' => 'Ꜯ',
71236 'ꜳ' => 'Ꜳ',
71237 'ꜵ' => 'Ꜵ',
71238 'ꜷ' => 'Ꜷ',
71239 'ꜹ' => 'Ꜹ',
71240 'ꜻ' => 'Ꜻ',
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 'a' => 'A',
71288 'b' => 'B',
71289 'c' => 'C',
71290 'd' => 'D',
71291 'e' => 'E',
71292 'f' => 'F',
71293 'g' => 'G',
71294 'h' => 'H',
71295 'i' => 'I',
71296 'j' => 'J',
71297 'k' => 'K',
71298 'l' => 'L',
71299 'm' => 'M',
71300 'n' => 'N',
71301 'o' => 'O',
71302 'p' => 'P',
71303 'q' => 'Q',
71304 'r' => 'R',
71305 's' => 'S',
71306 't' => 'T',
71307 'u' => 'U',
71308 'v' => 'V',
71309 'w' => 'W',
71310 'x' => 'X',
71311 'y' => 'Y',
71312 'z' => 'Z',
71313 '𐐨' => '𐐀',
71314 '𐐩' => '𐐁',
71315 '𐐪' => '𐐂',
71316 '𐐫' => '𐐃',
71317 '𐐬' => '𐐄',
71318 '𐐭' => '𐐅',
71319 '𐐮' => '𐐆',
71320 '𐐯' => '𐐇',
71321 '𐐰' => '𐐈',
71322 '𐐱' => '𐐉',
71323 '𐐲' => '𐐊',
71324 '𐐳' => '𐐋',
71325 '𐐴' => '𐐌',
71326 '𐐵' => '𐐍',
71327 '𐐶' => '𐐎',
71328 '𐐷' => '𐐏',
71329 '𐐸' => '𐐐',
71330 '𐐹' => '𐐑',
71331 '𐐺' => '𐐒',
71332 '𐐻' => '𐐓',
71333 '𐐼' => '𐐔',
71334 '𐐽' => '𐐕',
71335 '𐐾' => '𐐖',
71336 '𐐿' => '𐐗',
71337 '𐑀' => '𐐘',
71338 '𐑁' => '𐐙',
71339 '𐑂' => '𐐚',
71340 '𐑃' => '𐐛',
71341 '𐑄' => '𐐜',
71342 '𐑅' => '𐐝',
71343 '𐑆' => '𐐞',
71344 '𐑇' => '𐐟',
71345 '𐑈' => '𐐠',
71346 '𐑉' => '𐐡',
71347 '𐑊' => '𐐢',
71348 '𐑋' => '𐐣',
71349 '𐑌' => '𐐤',
71350 '𐑍' => '𐐥',
71351 '𐑎' => '𐐦',
71352 '𐑏' => '𐐧',
71353 '𑣀' => '𑢠',
71354 '𑣁' => '𑢡',
71355 '𑣂' => '𑢢',
71356 '𑣃' => '𑢣',
71357 '𑣄' => '𑢤',
71358 '𑣅' => '𑢥',
71359 '𑣆' => '𑢦',
71360 '𑣇' => '𑢧',
71361 '𑣈' => '𑢨',
71362 '𑣉' => '𑢩',
71363 '𑣊' => '𑢪',
71364 '𑣋' => '𑢫',
71365 '𑣌' => '𑢬',
71366 '𑣍' => '𑢭',
71367 '𑣎' => '𑢮',
71368 '𑣏' => '𑢯',
71369 '𑣐' => '𑢰',
71370 '𑣑' => '𑢱',
71371 '𑣒' => '𑢲',
71372 '𑣓' => '𑢳',
71373 '𑣔' => '𑢴',
71374 '𑣕' => '𑢵',
71375 '𑣖' => '𑢶',
71376 '𑣗' => '𑢷',
71377 '𑣘' => '𑢸',
71378 '𑣙' => '𑢹',
71379 '𑣚' => '𑢺',
71380 '𑣛' => '𑢻',
71381 '𑣜' => '𑢼',
71382 '𑣝' => '𑢽',
71383 '𑣞' => '𑢾',
71384 '𑣟' => '𑢿',
71385 );
71386
71387 $result =& $data;
71388 unset($data);
71389
71390 return $result;
71391 <?php
71392
71393
71394
71395
71396
71397
71398
71399
71400
71401
71402 use Symfony\Polyfill\Mbstring as p;
71403
71404 if (!function_exists('mb_strlen')) {
71405 define('MB_CASE_UPPER', 0);
71406 define('MB_CASE_LOWER', 1);
71407 define('MB_CASE_TITLE', 2);
71408
71409 function mb_convert_encoding($s, $to, $from = null) { return p\Mbstring::mb_convert_encoding($s, $to, $from); }
71410 function mb_decode_mimeheader($s) { return p\Mbstring::mb_decode_mimeheader($s); }
71411 function mb_encode_mimeheader($s, $charset = null, $transferEnc = null, $lf = null, $indent = null) { return p\Mbstring::mb_encode_mimeheader($s, $charset, $transferEnc, $lf, $indent); }
71412 function mb_convert_case($s, $mode, $enc = null) { return p\Mbstring::mb_convert_case($s, $mode, $enc); }
71413 function mb_internal_encoding($enc = null) { return p\Mbstring::mb_internal_encoding($enc); }
71414 function mb_language($lang = null) { return p\Mbstring::mb_language($lang); }
71415 function mb_list_encodings() { return p\Mbstring::mb_list_encodings(); }
71416 function mb_encoding_aliases($encoding) { return p\Mbstring::mb_encoding_aliases($encoding); }
71417 function mb_check_encoding($var = null, $encoding = null) { return p\Mbstring::mb_check_encoding($var, $encoding); }
71418 function mb_detect_encoding($str, $encodingList = null, $strict = false) { return p\Mbstring::mb_detect_encoding($str, $encodingList, $strict); }
71419 function mb_detect_order($encodingList = null) { return p\Mbstring::mb_detect_order($encodingList); }
71420 function mb_parse_str($s, &$result = array()) { parse_str($s, $result); }
71421 function mb_strlen($s, $enc = null) { return p\Mbstring::mb_strlen($s, $enc); }
71422 function mb_strpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strpos($s, $needle, $offset, $enc); }
71423 function mb_strtolower($s, $enc = null) { return p\Mbstring::mb_strtolower($s, $enc); }
71424 function mb_strtoupper($s, $enc = null) { return p\Mbstring::mb_strtoupper($s, $enc); }
71425 function mb_substitute_character($char = null) { return p\Mbstring::mb_substitute_character($char); }
71426 function mb_substr($s, $start, $length = 2147483647, $enc = null) { return p\Mbstring::mb_substr($s, $start, $length, $enc); }
71427 function mb_stripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_stripos($s, $needle, $offset, $enc); }
71428 function mb_stristr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_stristr($s, $needle, $part, $enc); }
71429 function mb_strrchr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrchr($s, $needle, $part, $enc); }
71430 function mb_strrichr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strrichr($s, $needle, $part, $enc); }
71431 function mb_strripos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strripos($s, $needle, $offset, $enc); }
71432 function mb_strrpos($s, $needle, $offset = 0, $enc = null) { return p\Mbstring::mb_strrpos($s, $needle, $offset, $enc); }
71433 function mb_strstr($s, $needle, $part = false, $enc = null) { return p\Mbstring::mb_strstr($s, $needle, $part, $enc); }
71434 function mb_get_info($type = 'all') { return p\Mbstring::mb_get_info($type); }
71435 function mb_http_output($enc = null) { return p\Mbstring::mb_http_output($enc); }
71436 function mb_strwidth($s, $enc = null) { return p\Mbstring::mb_strwidth($s, $enc); }
71437 function mb_substr_count($haystack, $needle, $enc = null) { return p\Mbstring::mb_substr_count($haystack, $needle, $enc); }
71438 function mb_output_handler($contents, $status) { return p\Mbstring::mb_output_handler($contents, $status); }
71439 function mb_http_input($type = '') { return p\Mbstring::mb_http_input($type); }
71440 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); }
71441 }
71442 if (!function_exists('mb_chr')) {
71443 function mb_ord($s, $enc = null) { return p\Mbstring::mb_ord($s, $enc); }
71444 function mb_chr($code, $enc = null) { return p\Mbstring::mb_chr($code, $enc); }
71445 function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); }
71446 }
71447 <?php
71448
71449
71450
71451
71452
71453
71454
71455
71456
71457
71458 namespace Symfony\Component\Process\Exception;
71459
71460
71461
71462
71463
71464
71465 interface ExceptionInterface
71466 {
71467 }
71468 <?php
71469
71470
71471
71472
71473
71474
71475
71476
71477
71478
71479 namespace Symfony\Component\Process\Exception;
71480
71481
71482
71483
71484
71485
71486 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
71487 {
71488 }
71489 <?php
71490
71491
71492
71493
71494
71495
71496
71497
71498
71499
71500 namespace Symfony\Component\Process\Exception;
71501
71502
71503
71504
71505
71506
71507 class LogicException extends \LogicException implements ExceptionInterface
71508 {
71509 }
71510 <?php
71511
71512
71513
71514
71515
71516
71517
71518
71519
71520
71521 namespace Symfony\Component\Process\Exception;
71522
71523 use Symfony\Component\Process\Process;
71524
71525
71526
71527
71528
71529
71530 class ProcessFailedException extends RuntimeException
71531 {
71532 private $process;
71533
71534 public function __construct(Process $process)
71535 {
71536 if ($process->isSuccessful()) {
71537 throw new InvalidArgumentException('Expected a failed process, but the given process was successful.');
71538 }
71539
71540 $error = sprintf('The command "%s" failed.'."\n\nExit Code: %s(%s)\n\nWorking directory: %s",
71541 $process->getCommandLine(),
71542 $process->getExitCode(),
71543 $process->getExitCodeText(),
71544 $process->getWorkingDirectory()
71545 );
71546
71547 if (!$process->isOutputDisabled()) {
71548 $error .= sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s",
71549 $process->getOutput(),
71550 $process->getErrorOutput()
71551 );
71552 }
71553
71554 parent::__construct($error);
71555
71556 $this->process = $process;
71557 }
71558
71559 public function getProcess()
71560 {
71561 return $this->process;
71562 }
71563 }
71564 <?php
71565
71566
71567
71568
71569
71570
71571
71572
71573
71574
71575 namespace Symfony\Component\Process\Exception;
71576
71577 use Symfony\Component\Process\Process;
71578
71579
71580
71581
71582
71583
71584 class ProcessTimedOutException extends RuntimeException
71585 {
71586 const TYPE_GENERAL = 1;
71587 const TYPE_IDLE = 2;
71588
71589 private $process;
71590 private $timeoutType;
71591
71592 public function __construct(Process $process, $timeoutType)
71593 {
71594 $this->process = $process;
71595 $this->timeoutType = $timeoutType;
71596
71597 parent::__construct(sprintf(
71598 'The process "%s" exceeded the timeout of %s seconds.',
71599 $process->getCommandLine(),
71600 $this->getExceededTimeout()
71601 ));
71602 }
71603
71604 public function getProcess()
71605 {
71606 return $this->process;
71607 }
71608
71609 public function isGeneralTimeout()
71610 {
71611 return $this->timeoutType === self::TYPE_GENERAL;
71612 }
71613
71614 public function isIdleTimeout()
71615 {
71616 return $this->timeoutType === self::TYPE_IDLE;
71617 }
71618
71619 public function getExceededTimeout()
71620 {
71621 switch ($this->timeoutType) {
71622 case self::TYPE_GENERAL:
71623 return $this->process->getTimeout();
71624
71625 case self::TYPE_IDLE:
71626 return $this->process->getIdleTimeout();
71627
71628 default:
71629 throw new \LogicException(sprintf('Unknown timeout type "%d".', $this->timeoutType));
71630 }
71631 }
71632 }
71633 <?php
71634
71635
71636
71637
71638
71639
71640
71641
71642
71643
71644 namespace Symfony\Component\Process\Exception;
71645
71646
71647
71648
71649
71650
71651 class RuntimeException extends \RuntimeException implements ExceptionInterface
71652 {
71653 }
71654 <?php
71655
71656
71657
71658
71659
71660
71661
71662
71663
71664
71665 namespace Symfony\Component\Process;
71666
71667
71668
71669
71670
71671
71672
71673 class ExecutableFinder
71674 {
71675 private $suffixes = array('.exe', '.bat', '.cmd', '.com');
71676
71677
71678
71679
71680
71681
71682 public function setSuffixes(array $suffixes)
71683 {
71684 $this->suffixes = $suffixes;
71685 }
71686
71687
71688
71689
71690
71691
71692 public function addSuffix($suffix)
71693 {
71694 $this->suffixes[] = $suffix;
71695 }
71696
71697
71698
71699
71700
71701
71702
71703
71704
71705
71706 public function find($name, $default = null, array $extraDirs = array())
71707 {
71708 if (ini_get('open_basedir')) {
71709 $searchPath = explode(PATH_SEPARATOR, ini_get('open_basedir'));
71710 $dirs = array();
71711 foreach ($searchPath as $path) {
71712
71713  if (@is_dir($path)) {
71714 $dirs[] = $path;
71715 } else {
71716 if (basename($path) == $name && @is_executable($path)) {
71717 return $path;
71718 }
71719 }
71720 }
71721 } else {
71722 $dirs = array_merge(
71723 explode(PATH_SEPARATOR, getenv('PATH') ?: getenv('Path')),
71724 $extraDirs
71725 );
71726 }
71727
71728 $suffixes = array('');
71729 if ('\\' === DIRECTORY_SEPARATOR) {
71730 $pathExt = getenv('PATHEXT');
71731 $suffixes = array_merge($suffixes, $pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes);
71732 }
71733 foreach ($suffixes as $suffix) {
71734 foreach ($dirs as $dir) {
71735 if (@is_file($file = $dir.DIRECTORY_SEPARATOR.$name.$suffix) && ('\\' === DIRECTORY_SEPARATOR || is_executable($file))) {
71736 return $file;
71737 }
71738 }
71739 }
71740
71741 return $default;
71742 }
71743 }
71744 Copyright (c) 2004-2017 Fabien Potencier
71745
71746 Permission is hereby granted, free of charge, to any person obtaining a copy
71747 of this software and associated documentation files (the "Software"), to deal
71748 in the Software without restriction, including without limitation the rights
71749 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
71750 copies of the Software, and to permit persons to whom the Software is furnished
71751 to do so, subject to the following conditions:
71752
71753 The above copyright notice and this permission notice shall be included in all
71754 copies or substantial portions of the Software.
71755
71756 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
71757 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
71758 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
71759 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
71760 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
71761 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
71762 THE SOFTWARE.
71763 <?php
71764
71765
71766
71767
71768
71769
71770
71771
71772
71773
71774 namespace Symfony\Component\Process;
71775
71776
71777
71778
71779
71780
71781
71782 class PhpExecutableFinder
71783 {
71784 private $executableFinder;
71785
71786 public function __construct()
71787 {
71788 $this->executableFinder = new ExecutableFinder();
71789 }
71790
71791
71792
71793
71794
71795
71796
71797
71798 public function find($includeArgs = true)
71799 {
71800 $args = $this->findArguments();
71801 $args = $includeArgs && $args ? ' '.implode(' ', $args) : '';
71802
71803
71804  if (defined('HHVM_VERSION')) {
71805 return (getenv('PHP_BINARY') ?: PHP_BINARY).$args;
71806 }
71807
71808
71809  if (defined('PHP_BINARY') && PHP_BINARY && in_array(PHP_SAPI, array('cli', 'cli-server', 'phpdbg')) && is_file(PHP_BINARY)) {
71810 return PHP_BINARY.$args;
71811 }
71812
71813 if ($php = getenv('PHP_PATH')) {
71814 if (!is_executable($php)) {
71815 return false;
71816 }
71817
71818 return $php;
71819 }
71820
71821 if ($php = getenv('PHP_PEAR_PHP_BIN')) {
71822 if (is_executable($php)) {
71823 return $php;
71824 }
71825 }
71826
71827 $dirs = array(PHP_BINDIR);
71828 if ('\\' === DIRECTORY_SEPARATOR) {
71829 $dirs[] = 'C:\xampp\php\\';
71830 }
71831
71832 return $this->executableFinder->find('php', false, $dirs);
71833 }
71834
71835
71836
71837
71838
71839
71840 public function findArguments()
71841 {
71842 $arguments = array();
71843
71844 if (defined('HHVM_VERSION')) {
71845 $arguments[] = '--php';
71846 } elseif ('phpdbg' === PHP_SAPI) {
71847 $arguments[] = '-qrr';
71848 }
71849
71850 return $arguments;
71851 }
71852 }
71853 <?php
71854
71855
71856
71857
71858
71859
71860
71861
71862
71863
71864 namespace Symfony\Component\Process;
71865
71866 use Symfony\Component\Process\Exception\RuntimeException;
71867
71868
71869
71870
71871
71872
71873
71874
71875
71876
71877 class PhpProcess extends Process
71878 {
71879
71880
71881
71882
71883
71884
71885
71886
71887
71888 public function __construct($script, $cwd = null, array $env = null, $timeout = 60, array $options = array())
71889 {
71890 $executableFinder = new PhpExecutableFinder();
71891 if (false === $php = $executableFinder->find()) {
71892 $php = null;
71893 }
71894 if ('phpdbg' === PHP_SAPI) {
71895 $file = tempnam(sys_get_temp_dir(), 'dbg');
71896 file_put_contents($file, $script);
71897 register_shutdown_function('unlink', $file);
71898 $php .= ' '.ProcessUtils::escapeArgument($file);
71899 $script = null;
71900 }
71901 if ('\\' !== DIRECTORY_SEPARATOR && null !== $php) {
71902
71903  
71904  
71905  $php = 'exec '.$php;
71906 }
71907
71908 parent::__construct($php, $cwd, $env, $script, $timeout, $options);
71909 }
71910
71911
71912
71913
71914 public function setPhpBinary($php)
71915 {
71916 $this->setCommandLine($php);
71917 }
71918
71919
71920
71921
71922 public function start($callback = null)
71923 {
71924 if (null === $this->getCommandLine()) {
71925 throw new RuntimeException('Unable to find the PHP executable.');
71926 }
71927
71928 parent::start($callback);
71929 }
71930 }
71931 <?php
71932
71933
71934
71935
71936
71937
71938
71939
71940
71941
71942 namespace Symfony\Component\Process\Pipes;
71943
71944
71945
71946
71947
71948
71949 abstract class AbstractPipes implements PipesInterface
71950 {
71951
71952 public $pipes = array();
71953
71954
71955 private $inputBuffer = '';
71956
71957 private $input;
71958
71959 private $blocked = true;
71960
71961 public function __construct($input)
71962 {
71963 if (is_resource($input)) {
71964 $this->input = $input;
71965 } elseif (is_string($input)) {
71966 $this->inputBuffer = $input;
71967 } else {
71968 $this->inputBuffer = (string) $input;
71969 }
71970 }
71971
71972
71973
71974
71975 public function close()
71976 {
71977 foreach ($this->pipes as $pipe) {
71978 fclose($pipe);
71979 }
71980 $this->pipes = array();
71981 }
71982
71983
71984
71985
71986
71987
71988 protected function hasSystemCallBeenInterrupted()
71989 {
71990 $lastError = error_get_last();
71991
71992
71993  return isset($lastError['message']) && false !== stripos($lastError['message'], 'interrupted system call');
71994 }
71995
71996
71997
71998
71999 protected function unblock()
72000 {
72001 if (!$this->blocked) {
72002 return;
72003 }
72004
72005 foreach ($this->pipes as $pipe) {
72006 stream_set_blocking($pipe, 0);
72007 }
72008 if (null !== $this->input) {
72009 stream_set_blocking($this->input, 0);
72010 }
72011
72012 $this->blocked = false;
72013 }
72014
72015
72016
72017
72018 protected function write()
72019 {
72020 if (!isset($this->pipes[0])) {
72021 return;
72022 }
72023 $input = $this->input;
72024 $r = $e = array();
72025 $w = array($this->pipes[0]);
72026
72027
72028  if (false === $n = @stream_select($r, $w, $e, 0, 0)) {
72029 return;
72030 }
72031
72032 foreach ($w as $stdin) {
72033 if (isset($this->inputBuffer[0])) {
72034 $written = fwrite($stdin, $this->inputBuffer);
72035 $this->inputBuffer = substr($this->inputBuffer, $written);
72036 if (isset($this->inputBuffer[0])) {
72037 return array($this->pipes[0]);
72038 }
72039 }
72040
72041 if ($input) {
72042 for (;;) {
72043 $data = fread($input, self::CHUNK_SIZE);
72044 if (!isset($data[0])) {
72045 break;
72046 }
72047 $written = fwrite($stdin, $data);
72048 $data = substr($data, $written);
72049 if (isset($data[0])) {
72050 $this->inputBuffer = $data;
72051
72052 return array($this->pipes[0]);
72053 }
72054 }
72055 if (feof($input)) {
72056
72057  
72058  $this->input = null;
72059 }
72060 }
72061 }
72062
72063
72064  if (null === $this->input && !isset($this->inputBuffer[0])) {
72065 fclose($this->pipes[0]);
72066 unset($this->pipes[0]);
72067 } elseif (!$w) {
72068 return array($this->pipes[0]);
72069 }
72070 }
72071 }
72072 <?php
72073
72074
72075
72076
72077
72078
72079
72080
72081
72082
72083 namespace Symfony\Component\Process\Pipes;
72084
72085
72086
72087
72088
72089
72090
72091
72092 interface PipesInterface
72093 {
72094 const CHUNK_SIZE = 16384;
72095
72096
72097
72098
72099
72100
72101 public function getDescriptors();
72102
72103
72104
72105
72106
72107
72108 public function getFiles();
72109
72110
72111
72112
72113
72114
72115
72116
72117
72118 public function readAndWrite($blocking, $close = false);
72119
72120
72121
72122
72123
72124
72125 public function areOpen();
72126
72127
72128
72129
72130 public function close();
72131 }
72132 <?php
72133
72134
72135
72136
72137
72138
72139
72140
72141
72142
72143 namespace Symfony\Component\Process\Pipes;
72144
72145 use Symfony\Component\Process\Process;
72146
72147
72148
72149
72150
72151
72152
72153
72154 class UnixPipes extends AbstractPipes
72155 {
72156
72157 private $ttyMode;
72158
72159 private $ptyMode;
72160
72161 private $disableOutput;
72162
72163 public function __construct($ttyMode, $ptyMode, $input, $disableOutput)
72164 {
72165 $this->ttyMode = (bool) $ttyMode;
72166 $this->ptyMode = (bool) $ptyMode;
72167 $this->disableOutput = (bool) $disableOutput;
72168
72169 parent::__construct($input);
72170 }
72171
72172 public function __destruct()
72173 {
72174 $this->close();
72175 }
72176
72177
72178
72179
72180 public function getDescriptors()
72181 {
72182 if ($this->disableOutput) {
72183 $nullstream = fopen('/dev/null', 'c');
72184
72185 return array(
72186 array('pipe', 'r'),
72187 $nullstream,
72188 $nullstream,
72189 );
72190 }
72191
72192 if ($this->ttyMode) {
72193 return array(
72194 array('file', '/dev/tty', 'r'),
72195 array('file', '/dev/tty', 'w'),
72196 array('file', '/dev/tty', 'w'),
72197 );
72198 }
72199
72200 if ($this->ptyMode && Process::isPtySupported()) {
72201 return array(
72202 array('pty'),
72203 array('pty'),
72204 array('pty'),
72205 );
72206 }
72207
72208 return array(
72209 array('pipe', 'r'),
72210 array('pipe', 'w'), 
72211  array('pipe', 'w'), 
72212  );
72213 }
72214
72215
72216
72217
72218 public function getFiles()
72219 {
72220 return array();
72221 }
72222
72223
72224
72225
72226 public function readAndWrite($blocking, $close = false)
72227 {
72228 $this->unblock();
72229 $w = $this->write();
72230
72231 $read = $e = array();
72232 $r = $this->pipes;
72233 unset($r[0]);
72234
72235
72236  if (($r || $w) && false === $n = @stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1E6 : 0)) {
72237
72238  
72239  if (!$this->hasSystemCallBeenInterrupted()) {
72240 $this->pipes = array();
72241 }
72242
72243 return $read;
72244 }
72245
72246 foreach ($r as $pipe) {
72247
72248  
72249  $read[$type = array_search($pipe, $this->pipes, true)] = '';
72250
72251 do {
72252 $data = fread($pipe, self::CHUNK_SIZE);
72253 $read[$type] .= $data;
72254 } while (isset($data[0]) && ($close || isset($data[self::CHUNK_SIZE - 1])));
72255
72256 if (!isset($read[$type][0])) {
72257 unset($read[$type]);
72258 }
72259
72260 if ($close && feof($pipe)) {
72261 fclose($pipe);
72262 unset($this->pipes[$type]);
72263 }
72264 }
72265
72266 return $read;
72267 }
72268
72269
72270
72271
72272 public function areOpen()
72273 {
72274 return (bool) $this->pipes;
72275 }
72276
72277
72278
72279
72280
72281
72282
72283
72284
72285 public static function create(Process $process, $input)
72286 {
72287 return new static($process->isTty(), $process->isPty(), $input, $process->isOutputDisabled());
72288 }
72289 }
72290 <?php
72291
72292
72293
72294
72295
72296
72297
72298
72299
72300
72301 namespace Symfony\Component\Process\Pipes;
72302
72303 use Symfony\Component\Process\Process;
72304 use Symfony\Component\Process\Exception\RuntimeException;
72305
72306
72307
72308
72309
72310
72311
72312
72313
72314
72315
72316 class WindowsPipes extends AbstractPipes
72317 {
72318
72319 private $files = array();
72320
72321 private $fileHandles = array();
72322
72323 private $readBytes = array(
72324 Process::STDOUT => 0,
72325 Process::STDERR => 0,
72326 );
72327
72328 private $disableOutput;
72329
72330 public function __construct($disableOutput, $input)
72331 {
72332 $this->disableOutput = (bool) $disableOutput;
72333
72334 if (!$this->disableOutput) {
72335
72336  
72337  
72338  
72339  $pipes = array(
72340 Process::STDOUT => Process::OUT,
72341 Process::STDERR => Process::ERR,
72342 );
72343 $tmpCheck = false;
72344 $tmpDir = sys_get_temp_dir();
72345 $lastError = 'unknown reason';
72346 set_error_handler(function ($type, $msg) use (&$lastError) { $lastError = $msg; });
72347 for ($i = 0;; ++$i) {
72348 foreach ($pipes as $pipe => $name) {
72349 $file = sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name);
72350 if (file_exists($file) && !unlink($file)) {
72351 continue 2;
72352 }
72353 $h = fopen($file, 'xb');
72354 if (!$h) {
72355 $error = $lastError;
72356 if ($tmpCheck || $tmpCheck = unlink(tempnam(false, 'sf_check_'))) {
72357 continue;
72358 }
72359 restore_error_handler();
72360 throw new RuntimeException(sprintf('A temporary file could not be opened to write the process output: %s', $error));
72361 }
72362 if (!$h || !$this->fileHandles[$pipe] = fopen($file, 'rb')) {
72363 continue 2;
72364 }
72365 if (isset($this->files[$pipe])) {
72366 unlink($this->files[$pipe]);
72367 }
72368 $this->files[$pipe] = $file;
72369 }
72370 break;
72371 }
72372 restore_error_handler();
72373 }
72374
72375 parent::__construct($input);
72376 }
72377
72378 public function __destruct()
72379 {
72380 $this->close();
72381 $this->removeFiles();
72382 }
72383
72384
72385
72386
72387 public function getDescriptors()
72388 {
72389 if ($this->disableOutput) {
72390 $nullstream = fopen('NUL', 'c');
72391
72392 return array(
72393 array('pipe', 'r'),
72394 $nullstream,
72395 $nullstream,
72396 );
72397 }
72398
72399
72400  
72401  
72402  return array(
72403 array('pipe', 'r'),
72404 array('file', 'NUL', 'w'),
72405 array('file', 'NUL', 'w'),
72406 );
72407 }
72408
72409
72410
72411
72412 public function getFiles()
72413 {
72414 return $this->files;
72415 }
72416
72417
72418
72419
72420 public function readAndWrite($blocking, $close = false)
72421 {
72422 $this->unblock();
72423 $w = $this->write();
72424 $read = $r = $e = array();
72425
72426 if ($blocking) {
72427 if ($w) {
72428 @stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1E6);
72429 } elseif ($this->fileHandles) {
72430 usleep(Process::TIMEOUT_PRECISION * 1E6);
72431 }
72432 }
72433 foreach ($this->fileHandles as $type => $fileHandle) {
72434 $data = stream_get_contents($fileHandle, -1, $this->readBytes[$type]);
72435
72436 if (isset($data[0])) {
72437 $this->readBytes[$type] += strlen($data);
72438 $read[$type] = $data;
72439 }
72440 if ($close) {
72441 fclose($fileHandle);
72442 unset($this->fileHandles[$type]);
72443 }
72444 }
72445
72446 return $read;
72447 }
72448
72449
72450
72451
72452 public function areOpen()
72453 {
72454 return $this->pipes && $this->fileHandles;
72455 }
72456
72457
72458
72459
72460 public function close()
72461 {
72462 parent::close();
72463 foreach ($this->fileHandles as $handle) {
72464 fclose($handle);
72465 }
72466 $this->fileHandles = array();
72467 }
72468
72469
72470
72471
72472
72473
72474
72475
72476
72477 public static function create(Process $process, $input)
72478 {
72479 return new static($process->isOutputDisabled(), $input);
72480 }
72481
72482
72483
72484
72485 private function removeFiles()
72486 {
72487 foreach ($this->files as $filename) {
72488 if (file_exists($filename)) {
72489 @unlink($filename);
72490 }
72491 }
72492 $this->files = array();
72493 }
72494 }
72495 <?php
72496
72497
72498
72499
72500
72501
72502
72503
72504
72505
72506 namespace Symfony\Component\Process;
72507
72508 use Symfony\Component\Process\Exception\InvalidArgumentException;
72509 use Symfony\Component\Process\Exception\LogicException;
72510 use Symfony\Component\Process\Exception\ProcessFailedException;
72511 use Symfony\Component\Process\Exception\ProcessTimedOutException;
72512 use Symfony\Component\Process\Exception\RuntimeException;
72513 use Symfony\Component\Process\Pipes\PipesInterface;
72514 use Symfony\Component\Process\Pipes\UnixPipes;
72515 use Symfony\Component\Process\Pipes\WindowsPipes;
72516
72517
72518
72519
72520
72521
72522
72523
72524 class Process
72525 {
72526 const ERR = 'err';
72527 const OUT = 'out';
72528
72529 const STATUS_READY = 'ready';
72530 const STATUS_STARTED = 'started';
72531 const STATUS_TERMINATED = 'terminated';
72532
72533 const STDIN = 0;
72534 const STDOUT = 1;
72535 const STDERR = 2;
72536
72537
72538  const TIMEOUT_PRECISION = 0.2;
72539
72540 private $callback;
72541 private $commandline;
72542 private $cwd;
72543 private $env;
72544 private $input;
72545 private $starttime;
72546 private $lastOutputTime;
72547 private $timeout;
72548 private $idleTimeout;
72549 private $options;
72550 private $exitcode;
72551 private $fallbackStatus = array();
72552 private $processInformation;
72553 private $outputDisabled = false;
72554 private $stdout;
72555 private $stderr;
72556 private $enhanceWindowsCompatibility = true;
72557 private $enhanceSigchildCompatibility;
72558 private $process;
72559 private $status = self::STATUS_READY;
72560 private $incrementalOutputOffset = 0;
72561 private $incrementalErrorOutputOffset = 0;
72562 private $tty;
72563 private $pty;
72564
72565 private $useFileHandles = false;
72566
72567 private $processPipes;
72568
72569 private $latestSignal;
72570
72571 private static $sigchild;
72572
72573
72574
72575
72576
72577
72578
72579
72580 public static $exitCodes = array(
72581 0 => 'OK',
72582 1 => 'General error',
72583 2 => 'Misuse of shell builtins',
72584
72585 126 => 'Invoked command cannot execute',
72586 127 => 'Command not found',
72587 128 => 'Invalid exit argument',
72588
72589
72590  129 => 'Hangup',
72591 130 => 'Interrupt',
72592 131 => 'Quit and dump core',
72593 132 => 'Illegal instruction',
72594 133 => 'Trace/breakpoint trap',
72595 134 => 'Process aborted',
72596 135 => 'Bus error: "access to undefined portion of memory object"',
72597 136 => 'Floating point exception: "erroneous arithmetic operation"',
72598 137 => 'Kill (terminate immediately)',
72599 138 => 'User-defined 1',
72600 139 => 'Segmentation violation',
72601 140 => 'User-defined 2',
72602 141 => 'Write to pipe with no one reading',
72603 142 => 'Signal raised by alarm',
72604 143 => 'Termination (request to terminate)',
72605
72606  145 => 'Child process terminated, stopped (or continued*)',
72607 146 => 'Continue if stopped',
72608 147 => 'Stop executing temporarily',
72609 148 => 'Terminal stop signal',
72610 149 => 'Background process attempting to read from tty ("in")',
72611 150 => 'Background process attempting to write to tty ("out")',
72612 151 => 'Urgent data available on socket',
72613 152 => 'CPU time limit exceeded',
72614 153 => 'File size limit exceeded',
72615 154 => 'Signal raised by timer counting virtual time: "virtual timer expired"',
72616 155 => 'Profiling timer expired',
72617
72618  157 => 'Pollable event',
72619
72620  159 => 'Bad syscall',
72621 );
72622
72623
72624
72625
72626
72627
72628
72629
72630
72631
72632
72633
72634
72635 public function __construct($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = array())
72636 {
72637 if (!function_exists('proc_open')) {
72638 throw new RuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.');
72639 }
72640
72641 $this->commandline = $commandline;
72642 $this->cwd = $cwd;
72643
72644
72645  
72646  
72647  
72648  if (null === $this->cwd && (defined('ZEND_THREAD_SAFE') || '\\' === DIRECTORY_SEPARATOR)) {
72649 $this->cwd = getcwd();
72650 }
72651 if (null !== $env) {
72652 $this->setEnv($env);
72653 }
72654
72655 $this->setInput($input);
72656 $this->setTimeout($timeout);
72657 $this->useFileHandles = '\\' === DIRECTORY_SEPARATOR;
72658 $this->pty = false;
72659 $this->enhanceSigchildCompatibility = '\\' !== DIRECTORY_SEPARATOR && $this->isSigchildEnabled();
72660 $this->options = array_replace(array('suppress_errors' => true, 'binary_pipes' => true), $options);
72661 }
72662
72663 public function __destruct()
72664 {
72665 $this->stop(0);
72666 }
72667
72668 public function __clone()
72669 {
72670 $this->resetProcessData();
72671 }
72672
72673
72674
72675
72676
72677
72678
72679
72680
72681
72682
72683
72684
72685
72686
72687
72688
72689
72690
72691
72692 public function run($callback = null)
72693 {
72694 $this->start($callback);
72695
72696 return $this->wait();
72697 }
72698
72699
72700
72701
72702
72703
72704
72705
72706
72707
72708
72709
72710
72711
72712 public function mustRun($callback = null)
72713 {
72714 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
72715 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
72716 }
72717
72718 if (0 !== $this->run($callback)) {
72719 throw new ProcessFailedException($this);
72720 }
72721
72722 return $this;
72723 }
72724
72725
72726
72727
72728
72729
72730
72731
72732
72733
72734
72735
72736
72737
72738
72739
72740
72741
72742
72743
72744 public function start($callback = null)
72745 {
72746 if ($this->isRunning()) {
72747 throw new RuntimeException('Process is already running');
72748 }
72749 if ($this->outputDisabled && null !== $callback) {
72750 throw new LogicException('Output has been disabled, enable it to allow the use of a callback.');
72751 }
72752
72753 $this->resetProcessData();
72754 $this->starttime = $this->lastOutputTime = microtime(true);
72755 $this->callback = $this->buildCallback($callback);
72756 $descriptors = $this->getDescriptors();
72757
72758 $commandline = $this->commandline;
72759
72760 if ('\\' === DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) {
72761 $commandline = 'cmd /V:ON /E:ON /D /C "('.$commandline.')';
72762 foreach ($this->processPipes->getFiles() as $offset => $filename) {
72763 $commandline .= ' '.$offset.'>'.ProcessUtils::escapeArgument($filename);
72764 }
72765 $commandline .= '"';
72766
72767 if (!isset($this->options['bypass_shell'])) {
72768 $this->options['bypass_shell'] = true;
72769 }
72770 } elseif (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
72771
72772  $descriptors[3] = array('pipe', 'w');
72773
72774
72775  $commandline = '{ ('.$this->commandline.') <&3 3<&- 3>/dev/null & } 3<&0;';
72776 $commandline .= 'pid=$!; echo $pid >&3; wait $pid; code=$?; echo $code >&3; exit $code';
72777
72778
72779  
72780  $ptsWorkaround = fopen(__FILE__, 'r');
72781 }
72782
72783 $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $this->env, $this->options);
72784
72785 if (!is_resource($this->process)) {
72786 throw new RuntimeException('Unable to launch a new process.');
72787 }
72788 $this->status = self::STATUS_STARTED;
72789
72790 if (isset($descriptors[3])) {
72791 $this->fallbackStatus['pid'] = (int) fgets($this->processPipes->pipes[3]);
72792 }
72793
72794 if ($this->tty) {
72795 return;
72796 }
72797
72798 $this->updateStatus(false);
72799 $this->checkTimeout();
72800 }
72801
72802
72803
72804
72805
72806
72807
72808
72809
72810
72811
72812
72813
72814
72815
72816
72817 public function restart($callback = null)
72818 {
72819 if ($this->isRunning()) {
72820 throw new RuntimeException('Process is already running');
72821 }
72822
72823 $process = clone $this;
72824 $process->start($callback);
72825
72826 return $process;
72827 }
72828
72829
72830
72831
72832
72833
72834
72835
72836
72837
72838
72839
72840
72841
72842
72843
72844 public function wait($callback = null)
72845 {
72846 $this->requireProcessIsStarted(__FUNCTION__);
72847
72848 $this->updateStatus(false);
72849 if (null !== $callback) {
72850 $this->callback = $this->buildCallback($callback);
72851 }
72852
72853 do {
72854 $this->checkTimeout();
72855 $running = '\\' === DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen();
72856 $this->readPipes($running, '\\' !== DIRECTORY_SEPARATOR || !$running);
72857 } while ($running);
72858
72859 while ($this->isRunning()) {
72860 usleep(1000);
72861 }
72862
72863 if ($this->processInformation['signaled'] && $this->processInformation['termsig'] !== $this->latestSignal) {
72864 throw new RuntimeException(sprintf('The process has been signaled with signal "%s".', $this->processInformation['termsig']));
72865 }
72866
72867 return $this->exitcode;
72868 }
72869
72870
72871
72872
72873
72874
72875 public function getPid()
72876 {
72877 return $this->isRunning() ? $this->processInformation['pid'] : null;
72878 }
72879
72880
72881
72882
72883
72884
72885
72886
72887
72888
72889
72890
72891 public function signal($signal)
72892 {
72893 $this->doSignal($signal, true);
72894
72895 return $this;
72896 }
72897
72898
72899
72900
72901
72902
72903
72904
72905
72906 public function disableOutput()
72907 {
72908 if ($this->isRunning()) {
72909 throw new RuntimeException('Disabling output while the process is running is not possible.');
72910 }
72911 if (null !== $this->idleTimeout) {
72912 throw new LogicException('Output can not be disabled while an idle timeout is set.');
72913 }
72914
72915 $this->outputDisabled = true;
72916
72917 return $this;
72918 }
72919
72920
72921
72922
72923
72924
72925
72926
72927 public function enableOutput()
72928 {
72929 if ($this->isRunning()) {
72930 throw new RuntimeException('Enabling output while the process is running is not possible.');
72931 }
72932
72933 $this->outputDisabled = false;
72934
72935 return $this;
72936 }
72937
72938
72939
72940
72941
72942
72943 public function isOutputDisabled()
72944 {
72945 return $this->outputDisabled;
72946 }
72947
72948
72949
72950
72951
72952
72953
72954
72955
72956 public function getOutput()
72957 {
72958 $this->readPipesForOutput(__FUNCTION__);
72959
72960 if (false === $ret = stream_get_contents($this->stdout, -1, 0)) {
72961 return '';
72962 }
72963
72964 return $ret;
72965 }
72966
72967
72968
72969
72970
72971
72972
72973
72974
72975
72976
72977
72978 public function getIncrementalOutput()
72979 {
72980 $this->readPipesForOutput(__FUNCTION__);
72981
72982 $latest = stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);
72983 $this->incrementalOutputOffset = ftell($this->stdout);
72984
72985 if (false === $latest) {
72986 return '';
72987 }
72988
72989 return $latest;
72990 }
72991
72992
72993
72994
72995
72996
72997 public function clearOutput()
72998 {
72999 ftruncate($this->stdout, 0);
73000 fseek($this->stdout, 0);
73001 $this->incrementalOutputOffset = 0;
73002
73003 return $this;
73004 }
73005
73006
73007
73008
73009
73010
73011
73012
73013
73014 public function getErrorOutput()
73015 {
73016 $this->readPipesForOutput(__FUNCTION__);
73017
73018 if (false === $ret = stream_get_contents($this->stderr, -1, 0)) {
73019 return '';
73020 }
73021
73022 return $ret;
73023 }
73024
73025
73026
73027
73028
73029
73030
73031
73032
73033
73034
73035
73036
73037 public function getIncrementalErrorOutput()
73038 {
73039 $this->readPipesForOutput(__FUNCTION__);
73040
73041 $latest = stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);
73042 $this->incrementalErrorOutputOffset = ftell($this->stderr);
73043
73044 if (false === $latest) {
73045 return '';
73046 }
73047
73048 return $latest;
73049 }
73050
73051
73052
73053
73054
73055
73056 public function clearErrorOutput()
73057 {
73058 ftruncate($this->stderr, 0);
73059 fseek($this->stderr, 0);
73060 $this->incrementalErrorOutputOffset = 0;
73061
73062 return $this;
73063 }
73064
73065
73066
73067
73068
73069
73070
73071
73072 public function getExitCode()
73073 {
73074 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
73075 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.');
73076 }
73077
73078 $this->updateStatus(false);
73079
73080 return $this->exitcode;
73081 }
73082
73083
73084
73085
73086
73087
73088
73089
73090
73091
73092
73093
73094 public function getExitCodeText()
73095 {
73096 if (null === $exitcode = $this->getExitCode()) {
73097 return;
73098 }
73099
73100 return isset(self::$exitCodes[$exitcode]) ? self::$exitCodes[$exitcode] : 'Unknown error';
73101 }
73102
73103
73104
73105
73106
73107
73108 public function isSuccessful()
73109 {
73110 return 0 === $this->getExitCode();
73111 }
73112
73113
73114
73115
73116
73117
73118
73119
73120
73121
73122
73123 public function hasBeenSignaled()
73124 {
73125 $this->requireProcessIsTerminated(__FUNCTION__);
73126
73127 if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
73128 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
73129 }
73130
73131 return $this->processInformation['signaled'];
73132 }
73133
73134
73135
73136
73137
73138
73139
73140
73141
73142
73143
73144 public function getTermSignal()
73145 {
73146 $this->requireProcessIsTerminated(__FUNCTION__);
73147
73148 if ($this->isSigchildEnabled() && (!$this->enhanceSigchildCompatibility || -1 === $this->processInformation['termsig'])) {
73149 throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.');
73150 }
73151
73152 return $this->processInformation['termsig'];
73153 }
73154
73155
73156
73157
73158
73159
73160
73161
73162
73163
73164 public function hasBeenStopped()
73165 {
73166 $this->requireProcessIsTerminated(__FUNCTION__);
73167
73168 return $this->processInformation['stopped'];
73169 }
73170
73171
73172
73173
73174
73175
73176
73177
73178
73179
73180 public function getStopSignal()
73181 {
73182 $this->requireProcessIsTerminated(__FUNCTION__);
73183
73184 return $this->processInformation['stopsig'];
73185 }
73186
73187
73188
73189
73190
73191
73192 public function isRunning()
73193 {
73194 if (self::STATUS_STARTED !== $this->status) {
73195 return false;
73196 }
73197
73198 $this->updateStatus(false);
73199
73200 return $this->processInformation['running'];
73201 }
73202
73203
73204
73205
73206
73207
73208 public function isStarted()
73209 {
73210 return $this->status != self::STATUS_READY;
73211 }
73212
73213
73214
73215
73216
73217
73218 public function isTerminated()
73219 {
73220 $this->updateStatus(false);
73221
73222 return $this->status == self::STATUS_TERMINATED;
73223 }
73224
73225
73226
73227
73228
73229
73230
73231
73232 public function getStatus()
73233 {
73234 $this->updateStatus(false);
73235
73236 return $this->status;
73237 }
73238
73239
73240
73241
73242
73243
73244
73245
73246
73247 public function stop($timeout = 10, $signal = null)
73248 {
73249 $timeoutMicro = microtime(true) + $timeout;
73250 if ($this->isRunning()) {
73251
73252  $this->doSignal(15, false);
73253 do {
73254 usleep(1000);
73255 } while ($this->isRunning() && microtime(true) < $timeoutMicro);
73256
73257 if ($this->isRunning()) {
73258
73259  
73260  $this->doSignal($signal ?: 9, false);
73261 }
73262 }
73263
73264 if ($this->isRunning()) {
73265 if (isset($this->fallbackStatus['pid'])) {
73266 unset($this->fallbackStatus['pid']);
73267
73268 return $this->stop(0, $signal);
73269 }
73270 $this->close();
73271 }
73272
73273 return $this->exitcode;
73274 }
73275
73276
73277
73278
73279
73280
73281
73282
73283 public function addOutput($line)
73284 {
73285 $this->lastOutputTime = microtime(true);
73286
73287 fseek($this->stdout, 0, SEEK_END);
73288 fwrite($this->stdout, $line);
73289 fseek($this->stdout, $this->incrementalOutputOffset);
73290 }
73291
73292
73293
73294
73295
73296
73297
73298
73299 public function addErrorOutput($line)
73300 {
73301 $this->lastOutputTime = microtime(true);
73302
73303 fseek($this->stderr, 0, SEEK_END);
73304 fwrite($this->stderr, $line);
73305 fseek($this->stderr, $this->incrementalErrorOutputOffset);
73306 }
73307
73308
73309
73310
73311
73312
73313 public function getCommandLine()
73314 {
73315 return $this->commandline;
73316 }
73317
73318
73319
73320
73321
73322
73323
73324
73325 public function setCommandLine($commandline)
73326 {
73327 $this->commandline = $commandline;
73328
73329 return $this;
73330 }
73331
73332
73333
73334
73335
73336
73337 public function getTimeout()
73338 {
73339 return $this->timeout;
73340 }
73341
73342
73343
73344
73345
73346
73347 public function getIdleTimeout()
73348 {
73349 return $this->idleTimeout;
73350 }
73351
73352
73353
73354
73355
73356
73357
73358
73359
73360
73361
73362
73363 public function setTimeout($timeout)
73364 {
73365 $this->timeout = $this->validateTimeout($timeout);
73366
73367 return $this;
73368 }
73369
73370
73371
73372
73373
73374
73375
73376
73377
73378
73379
73380
73381
73382 public function setIdleTimeout($timeout)
73383 {
73384 if (null !== $timeout && $this->outputDisabled) {
73385 throw new LogicException('Idle timeout can not be set while the output is disabled.');
73386 }
73387
73388 $this->idleTimeout = $this->validateTimeout($timeout);
73389
73390 return $this;
73391 }
73392
73393
73394
73395
73396
73397
73398
73399
73400
73401
73402 public function setTty($tty)
73403 {
73404 if ('\\' === DIRECTORY_SEPARATOR && $tty) {
73405 throw new RuntimeException('TTY mode is not supported on Windows platform.');
73406 }
73407 if ($tty) {
73408 static $isTtySupported;
73409
73410 if (null === $isTtySupported) {
73411 $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);
73412 }
73413
73414 if (!$isTtySupported) {
73415 throw new RuntimeException('TTY mode requires /dev/tty to be read/writable.');
73416 }
73417 }
73418
73419 $this->tty = (bool) $tty;
73420
73421 return $this;
73422 }
73423
73424
73425
73426
73427
73428
73429 public function isTty()
73430 {
73431 return $this->tty;
73432 }
73433
73434
73435
73436
73437
73438
73439
73440
73441 public function setPty($bool)
73442 {
73443 $this->pty = (bool) $bool;
73444
73445 return $this;
73446 }
73447
73448
73449
73450
73451
73452
73453 public function isPty()
73454 {
73455 return $this->pty;
73456 }
73457
73458
73459
73460
73461
73462
73463 public function getWorkingDirectory()
73464 {
73465 if (null === $this->cwd) {
73466
73467  
73468  return getcwd() ?: null;
73469 }
73470
73471 return $this->cwd;
73472 }
73473
73474
73475
73476
73477
73478
73479
73480
73481 public function setWorkingDirectory($cwd)
73482 {
73483 $this->cwd = $cwd;
73484
73485 return $this;
73486 }
73487
73488
73489
73490
73491
73492
73493 public function getEnv()
73494 {
73495 return $this->env;
73496 }
73497
73498
73499
73500
73501
73502
73503
73504
73505
73506
73507
73508
73509
73510
73511 public function setEnv(array $env)
73512 {
73513
73514  $env = array_filter($env, function ($value) {
73515 return !is_array($value);
73516 });
73517
73518 $this->env = array();
73519 foreach ($env as $key => $value) {
73520 $this->env[$key] = (string) $value;
73521 }
73522
73523 return $this;
73524 }
73525
73526
73527
73528
73529
73530
73531
73532
73533
73534
73535 public function getStdin()
73536 {
73537 @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);
73538
73539 return $this->getInput();
73540 }
73541
73542
73543
73544
73545
73546
73547 public function getInput()
73548 {
73549 return $this->input;
73550 }
73551
73552
73553
73554
73555
73556
73557
73558
73559
73560
73561
73562
73563
73564
73565 public function setStdin($stdin)
73566 {
73567 @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);
73568
73569 return $this->setInput($stdin);
73570 }
73571
73572
73573
73574
73575
73576
73577
73578
73579
73580
73581
73582
73583
73584
73585 public function setInput($input)
73586 {
73587 if ($this->isRunning()) {
73588 throw new LogicException('Input can not be set while the process is running.');
73589 }
73590
73591 $this->input = ProcessUtils::validateInput(__METHOD__, $input);
73592
73593 return $this;
73594 }
73595
73596
73597
73598
73599
73600
73601 public function getOptions()
73602 {
73603 return $this->options;
73604 }
73605
73606
73607
73608
73609
73610
73611
73612
73613 public function setOptions(array $options)
73614 {
73615 $this->options = $options;
73616
73617 return $this;
73618 }
73619
73620
73621
73622
73623
73624
73625
73626
73627 public function getEnhanceWindowsCompatibility()
73628 {
73629 return $this->enhanceWindowsCompatibility;
73630 }
73631
73632
73633
73634
73635
73636
73637
73638
73639 public function setEnhanceWindowsCompatibility($enhance)
73640 {
73641 $this->enhanceWindowsCompatibility = (bool) $enhance;
73642
73643 return $this;
73644 }
73645
73646
73647
73648
73649
73650
73651 public function getEnhanceSigchildCompatibility()
73652 {
73653 return $this->enhanceSigchildCompatibility;
73654 }
73655
73656
73657
73658
73659
73660
73661
73662
73663
73664
73665
73666
73667 public function setEnhanceSigchildCompatibility($enhance)
73668 {
73669 $this->enhanceSigchildCompatibility = (bool) $enhance;
73670
73671 return $this;
73672 }
73673
73674
73675
73676
73677
73678
73679
73680
73681
73682 public function checkTimeout()
73683 {
73684 if ($this->status !== self::STATUS_STARTED) {
73685 return;
73686 }
73687
73688 if (null !== $this->timeout && $this->timeout < microtime(true) - $this->starttime) {
73689 $this->stop(0);
73690
73691 throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL);
73692 }
73693
73694 if (null !== $this->idleTimeout && $this->idleTimeout < microtime(true) - $this->lastOutputTime) {
73695 $this->stop(0);
73696
73697 throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE);
73698 }
73699 }
73700
73701
73702
73703
73704
73705
73706 public static function isPtySupported()
73707 {
73708 static $result;
73709
73710 if (null !== $result) {
73711 return $result;
73712 }
73713
73714 if ('\\' === DIRECTORY_SEPARATOR) {
73715 return $result = false;
73716 }
73717
73718 return $result = (bool) @proc_open('echo 1 >/dev/null', array(array('pty'), array('pty'), array('pty')), $pipes);
73719 }
73720
73721
73722
73723
73724
73725
73726 private function getDescriptors()
73727 {
73728 if ('\\' === DIRECTORY_SEPARATOR) {
73729 $this->processPipes = WindowsPipes::create($this, $this->input);
73730 } else {
73731 $this->processPipes = UnixPipes::create($this, $this->input);
73732 }
73733
73734 return $this->processPipes->getDescriptors();
73735 }
73736
73737
73738
73739
73740
73741
73742
73743
73744
73745
73746
73747 protected function buildCallback($callback)
73748 {
73749 $that = $this;
73750 $out = self::OUT;
73751 $callback = function ($type, $data) use ($that, $callback, $out) {
73752 if ($out == $type) {
73753 $that->addOutput($data);
73754 } else {
73755 $that->addErrorOutput($data);
73756 }
73757
73758 if (null !== $callback) {
73759 call_user_func($callback, $type, $data);
73760 }
73761 };
73762
73763 return $callback;
73764 }
73765
73766
73767
73768
73769
73770
73771 protected function updateStatus($blocking)
73772 {
73773 if (self::STATUS_STARTED !== $this->status) {
73774 return;
73775 }
73776
73777 $this->processInformation = proc_get_status($this->process);
73778 $running = $this->processInformation['running'];
73779
73780 $this->readPipes($running && $blocking, '\\' !== DIRECTORY_SEPARATOR || !$running);
73781
73782 if ($this->fallbackStatus && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
73783 $this->processInformation = $this->fallbackStatus + $this->processInformation;
73784 }
73785
73786 if (!$running) {
73787 $this->close();
73788 }
73789 }
73790
73791
73792
73793
73794
73795
73796 protected function isSigchildEnabled()
73797 {
73798 if (null !== self::$sigchild) {
73799 return self::$sigchild;
73800 }
73801
73802 if (!function_exists('phpinfo') || defined('HHVM_VERSION')) {
73803 return self::$sigchild = false;
73804 }
73805
73806 ob_start();
73807 phpinfo(INFO_GENERAL);
73808
73809 return self::$sigchild = false !== strpos(ob_get_clean(), '--enable-sigchild');
73810 }
73811
73812
73813
73814
73815
73816
73817
73818
73819 private function readPipesForOutput($caller)
73820 {
73821 if ($this->outputDisabled) {
73822 throw new LogicException('Output has been disabled.');
73823 }
73824
73825 $this->requireProcessIsStarted($caller);
73826
73827 $this->updateStatus(false);
73828 }
73829
73830
73831
73832
73833
73834
73835
73836
73837
73838
73839 private function validateTimeout($timeout)
73840 {
73841 $timeout = (float) $timeout;
73842
73843 if (0.0 === $timeout) {
73844 $timeout = null;
73845 } elseif ($timeout < 0) {
73846 throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
73847 }
73848
73849 return $timeout;
73850 }
73851
73852
73853
73854
73855
73856
73857
73858 private function readPipes($blocking, $close)
73859 {
73860 $result = $this->processPipes->readAndWrite($blocking, $close);
73861
73862 $callback = $this->callback;
73863 foreach ($result as $type => $data) {
73864 if (3 !== $type) {
73865 $callback($type === self::STDOUT ? self::OUT : self::ERR, $data);
73866 } elseif (!isset($this->fallbackStatus['signaled'])) {
73867 $this->fallbackStatus['exitcode'] = (int) $data;
73868 }
73869 }
73870 }
73871
73872
73873
73874
73875
73876
73877 private function close()
73878 {
73879 $this->processPipes->close();
73880 if (is_resource($this->process)) {
73881 proc_close($this->process);
73882 }
73883 $this->exitcode = $this->processInformation['exitcode'];
73884 $this->status = self::STATUS_TERMINATED;
73885
73886 if (-1 === $this->exitcode) {
73887 if ($this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) {
73888
73889  $this->exitcode = 128 + $this->processInformation['termsig'];
73890 } elseif ($this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
73891 $this->processInformation['signaled'] = true;
73892 $this->processInformation['termsig'] = -1;
73893 }
73894 }
73895
73896
73897  
73898  
73899  $this->callback = null;
73900
73901 return $this->exitcode;
73902 }
73903
73904
73905
73906
73907 private function resetProcessData()
73908 {
73909 $this->starttime = null;
73910 $this->callback = null;
73911 $this->exitcode = null;
73912 $this->fallbackStatus = array();
73913 $this->processInformation = null;
73914 $this->stdout = fopen('php://temp/maxmemory:'.(1024 * 1024), 'wb+');
73915 $this->stderr = fopen('php://temp/maxmemory:'.(1024 * 1024), 'wb+');
73916 $this->process = null;
73917 $this->latestSignal = null;
73918 $this->status = self::STATUS_READY;
73919 $this->incrementalOutputOffset = 0;
73920 $this->incrementalErrorOutputOffset = 0;
73921 }
73922
73923
73924
73925
73926
73927
73928
73929
73930
73931
73932
73933
73934
73935 private function doSignal($signal, $throwException)
73936 {
73937 if (null === $pid = $this->getPid()) {
73938 if ($throwException) {
73939 throw new LogicException('Can not send signal on a non running process.');
73940 }
73941
73942 return false;
73943 }
73944
73945 if ('\\' === DIRECTORY_SEPARATOR) {
73946 exec(sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode);
73947 if ($exitCode && $this->isRunning()) {
73948 if ($throwException) {
73949 throw new RuntimeException(sprintf('Unable to kill the process (%s).', implode(' ', $output)));
73950 }
73951
73952 return false;
73953 }
73954 } else {
73955 if (!$this->enhanceSigchildCompatibility || !$this->isSigchildEnabled()) {
73956 $ok = @proc_terminate($this->process, $signal);
73957 } elseif (function_exists('posix_kill')) {
73958 $ok = @posix_kill($pid, $signal);
73959 } elseif ($ok = proc_open(sprintf('kill -%d %d', $signal, $pid), array(2 => array('pipe', 'w')), $pipes)) {
73960 $ok = false === fgets($pipes[2]);
73961 }
73962 if (!$ok) {
73963 if ($throwException) {
73964 throw new RuntimeException(sprintf('Error while sending signal `%s`.', $signal));
73965 }
73966
73967 return false;
73968 }
73969 }
73970
73971 $this->latestSignal = (int) $signal;
73972 $this->fallbackStatus['signaled'] = true;
73973 $this->fallbackStatus['exitcode'] = -1;
73974 $this->fallbackStatus['termsig'] = $this->latestSignal;
73975
73976 return true;
73977 }
73978
73979
73980
73981
73982
73983
73984
73985
73986 private function requireProcessIsStarted($functionName)
73987 {
73988 if (!$this->isStarted()) {
73989 throw new LogicException(sprintf('Process must be started before calling %s.', $functionName));
73990 }
73991 }
73992
73993
73994
73995
73996
73997
73998
73999
74000 private function requireProcessIsTerminated($functionName)
74001 {
74002 if (!$this->isTerminated()) {
74003 throw new LogicException(sprintf('Process must be terminated before calling %s.', $functionName));
74004 }
74005 }
74006 }
74007 <?php
74008
74009
74010
74011
74012
74013
74014
74015
74016
74017
74018 namespace Symfony\Component\Process;
74019
74020 use Symfony\Component\Process\Exception\InvalidArgumentException;
74021 use Symfony\Component\Process\Exception\LogicException;
74022
74023
74024
74025
74026
74027
74028 class ProcessBuilder
74029 {
74030 private $arguments;
74031 private $cwd;
74032 private $env = array();
74033 private $input;
74034 private $timeout = 60;
74035 private $options = array();
74036 private $inheritEnv = true;
74037 private $prefix = array();
74038 private $outputDisabled = false;
74039
74040
74041
74042
74043
74044
74045 public function __construct(array $arguments = array())
74046 {
74047 $this->arguments = $arguments;
74048 }
74049
74050
74051
74052
74053
74054
74055
74056
74057 public static function create(array $arguments = array())
74058 {
74059 return new static($arguments);
74060 }
74061
74062
74063
74064
74065
74066
74067
74068
74069 public function add($argument)
74070 {
74071 $this->arguments[] = $argument;
74072
74073 return $this;
74074 }
74075
74076
74077
74078
74079
74080
74081
74082
74083
74084
74085 public function setPrefix($prefix)
74086 {
74087 $this->prefix = is_array($prefix) ? $prefix : array($prefix);
74088
74089 return $this;
74090 }
74091
74092
74093
74094
74095
74096
74097
74098
74099
74100
74101
74102 public function setArguments(array $arguments)
74103 {
74104 $this->arguments = $arguments;
74105
74106 return $this;
74107 }
74108
74109
74110
74111
74112
74113
74114
74115
74116 public function setWorkingDirectory($cwd)
74117 {
74118 $this->cwd = $cwd;
74119
74120 return $this;
74121 }
74122
74123
74124
74125
74126
74127
74128
74129
74130 public function inheritEnvironmentVariables($inheritEnv = true)
74131 {
74132 $this->inheritEnv = $inheritEnv;
74133
74134 return $this;
74135 }
74136
74137
74138
74139
74140
74141
74142
74143
74144
74145
74146
74147
74148 public function setEnv($name, $value)
74149 {
74150 $this->env[$name] = $value;
74151
74152 return $this;
74153 }
74154
74155
74156
74157
74158
74159
74160
74161
74162
74163
74164
74165
74166 public function addEnvironmentVariables(array $variables)
74167 {
74168 $this->env = array_replace($this->env, $variables);
74169
74170 return $this;
74171 }
74172
74173
74174
74175
74176
74177
74178
74179
74180
74181
74182
74183
74184 public function setInput($input)
74185 {
74186 $this->input = ProcessUtils::validateInput(__METHOD__, $input);
74187
74188 return $this;
74189 }
74190
74191
74192
74193
74194
74195
74196
74197
74198
74199
74200
74201
74202 public function setTimeout($timeout)
74203 {
74204 if (null === $timeout) {
74205 $this->timeout = null;
74206
74207 return $this;
74208 }
74209
74210 $timeout = (float) $timeout;
74211
74212 if ($timeout < 0) {
74213 throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
74214 }
74215
74216 $this->timeout = $timeout;
74217
74218 return $this;
74219 }
74220
74221
74222
74223
74224
74225
74226
74227
74228
74229 public function setOption($name, $value)
74230 {
74231 $this->options[$name] = $value;
74232
74233 return $this;
74234 }
74235
74236
74237
74238
74239
74240
74241 public function disableOutput()
74242 {
74243 $this->outputDisabled = true;
74244
74245 return $this;
74246 }
74247
74248
74249
74250
74251
74252
74253 public function enableOutput()
74254 {
74255 $this->outputDisabled = false;
74256
74257 return $this;
74258 }
74259
74260
74261
74262
74263
74264
74265
74266
74267 public function getProcess()
74268 {
74269 if (0 === count($this->prefix) && 0 === count($this->arguments)) {
74270 throw new LogicException('You must add() command arguments before calling getProcess().');
74271 }
74272
74273 $options = $this->options;
74274
74275 $arguments = array_merge($this->prefix, $this->arguments);
74276 $script = implode(' ', array_map(array(__NAMESPACE__.'\\ProcessUtils', 'escapeArgument'), $arguments));
74277
74278 if ($this->inheritEnv) {
74279
74280  $env = array_replace($_ENV, $_SERVER, $this->env);
74281 } else {
74282 $env = $this->env;
74283 }
74284
74285 $process = new Process($script, $this->cwd, $env, $this->input, $this->timeout, $options);
74286
74287 if ($this->outputDisabled) {
74288 $process->disableOutput();
74289 }
74290
74291 return $process;
74292 }
74293 }
74294 <?php
74295
74296
74297
74298
74299
74300
74301
74302
74303
74304
74305 namespace Symfony\Component\Process;
74306
74307 use Symfony\Component\Process\Exception\InvalidArgumentException;
74308
74309
74310
74311
74312
74313
74314
74315
74316 class ProcessUtils
74317 {
74318
74319
74320
74321 private function __construct()
74322 {
74323 }
74324
74325
74326
74327
74328
74329
74330
74331
74332 public static function escapeArgument($argument)
74333 {
74334
74335  
74336  
74337  
74338  if ('\\' === DIRECTORY_SEPARATOR) {
74339 if ('' === $argument) {
74340 return escapeshellarg($argument);
74341 }
74342
74343 $escapedArgument = '';
74344 $quote = false;
74345 foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) {
74346 if ('"' === $part) {
74347 $escapedArgument .= '\\"';
74348 } elseif (self::isSurroundedBy($part, '%')) {
74349
74350  $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%';
74351 } else {
74352
74353  if ('\\' === substr($part, -1)) {
74354 $part .= '\\';
74355 }
74356 $quote = true;
74357 $escapedArgument .= $part;
74358 }
74359 }
74360 if ($quote) {
74361 $escapedArgument = '"'.$escapedArgument.'"';
74362 }
74363
74364 return $escapedArgument;
74365 }
74366
74367 return "'".str_replace("'", "'\\''", $argument)."'";
74368 }
74369
74370
74371
74372
74373
74374
74375
74376
74377
74378
74379
74380
74381
74382 public static function validateInput($caller, $input)
74383 {
74384 if (null !== $input) {
74385 if (is_resource($input)) {
74386 return $input;
74387 }
74388 if (is_string($input)) {
74389 return $input;
74390 }
74391 if (is_scalar($input)) {
74392 return (string) $input;
74393 }
74394
74395  if (is_object($input) && method_exists($input, '__toString')) {
74396 @trigger_error('Passing an object as an input is deprecated since version 2.5 and will be removed in 3.0.', E_USER_DEPRECATED);
74397
74398 return (string) $input;
74399 }
74400
74401 throw new InvalidArgumentException(sprintf('%s only accepts strings or stream resources.', $caller));
74402 }
74403
74404 return $input;
74405 }
74406
74407 private static function isSurroundedBy($arg, $char)
74408 {
74409 return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1];
74410 }
74411 }
74412 Copyright (c) 2011 Jordi Boggiano
74413
74414 Permission is hereby granted, free of charge, to any person obtaining a copy
74415 of this software and associated documentation files (the "Software"), to deal
74416 in the Software without restriction, including without limitation the rights
74417 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
74418 copies of the Software, and to permit persons to whom the Software is furnished
74419 to do so, subject to the following conditions:
74420
74421 The above copyright notice and this permission notice shall be included in all
74422 copies or substantial portions of the Software.
74423
74424 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
74425 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
74426 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
74427 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
74428 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
74429 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
74430 THE SOFTWARE.
74431 <?php
74432
74433
74434
74435
74436
74437
74438
74439
74440
74441
74442 namespace Seld\JsonLint;
74443
74444 class DuplicateKeyException extends ParsingException
74445 {
74446 public function __construct($message, $key, array $details = array())
74447 {
74448 $details['key'] = $key;
74449 parent::__construct($message, $details);
74450 }
74451
74452 public function getKey()
74453 {
74454 return $this->details['key'];
74455 }
74456 }
74457 <?php
74458
74459
74460
74461
74462
74463
74464
74465
74466
74467
74468 namespace Seld\JsonLint;
74469 use stdClass;
74470
74471
74472
74473
74474
74475
74476
74477
74478
74479
74480
74481
74482
74483
74484 class JsonParser
74485 {
74486 const DETECT_KEY_CONFLICTS = 1;
74487 const ALLOW_DUPLICATE_KEYS = 2;
74488 const PARSE_TO_ASSOC = 4;
74489
74490 private $lexer;
74491
74492 private $flags;
74493 private $stack;
74494 private $vstack; 
74495  private $lstack; 
74496
74497 private $symbols = array(
74498 'error' => 2,
74499 'JSONString' => 3,
74500 'STRING' => 4,
74501 'JSONNumber' => 5,
74502 'NUMBER' => 6,
74503 'JSONNullLiteral' => 7,
74504 'NULL' => 8,
74505 'JSONBooleanLiteral' => 9,
74506 'TRUE' => 10,
74507 'FALSE' => 11,
74508 'JSONText' => 12,
74509 'JSONValue' => 13,
74510 'EOF' => 14,
74511 'JSONObject' => 15,
74512 'JSONArray' => 16,
74513 '{' => 17,
74514 '}' => 18,
74515 'JSONMemberList' => 19,
74516 'JSONMember' => 20,
74517 ':' => 21,
74518 ',' => 22,
74519 '[' => 23,
74520 ']' => 24,
74521 'JSONElementList' => 25,
74522 '$accept' => 0,
74523 '$end' => 1,
74524 );
74525
74526 private $terminals_ = array(
74527 2 => "error",
74528 4 => "STRING",
74529 6 => "NUMBER",
74530 8 => "NULL",
74531 10 => "TRUE",
74532 11 => "FALSE",
74533 14 => "EOF",
74534 17 => "{",
74535 18 => "}",
74536 21 => ":",
74537 22 => ",",
74538 23 => "[",
74539 24 => "]",
74540 );
74541
74542 private $productions_ = array(
74543 0,
74544 array(3, 1),
74545 array(5, 1),
74546 array(7, 1),
74547 array(9, 1),
74548 array(9, 1),
74549 array(12, 2),
74550 array(13, 1),
74551 array(13, 1),
74552 array(13, 1),
74553 array(13, 1),
74554 array(13, 1),
74555 array(13, 1),
74556 array(15, 2),
74557 array(15, 3),
74558 array(20, 3),
74559 array(19, 1),
74560 array(19, 3),
74561 array(16, 2),
74562 array(16, 3),
74563 array(25, 1),
74564 array(25, 3)
74565 );
74566
74567 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)),
74568 );
74569
74570 private $defaultActions = array(
74571 16 => array(2, 6)
74572 );
74573
74574
74575
74576
74577
74578
74579 public function lint($input, $flags = 0)
74580 {
74581 try {
74582 $this->parse($input, $flags);
74583 } catch (ParsingException $e) {
74584 return $e;
74585 }
74586 }
74587
74588
74589
74590
74591
74592
74593
74594 public function parse($input, $flags = 0)
74595 {
74596 $this->failOnBOM($input);
74597
74598 $this->flags = $flags;
74599
74600 $this->stack = array(0);
74601 $this->vstack = array(null);
74602 $this->lstack = array();
74603
74604 $yytext = '';
74605 $yylineno = 0;
74606 $yyleng = 0;
74607 $recovering = 0;
74608 $TERROR = 2;
74609 $EOF = 1;
74610
74611 $this->lexer = new Lexer();
74612 $this->lexer->setInput($input);
74613
74614 $yyloc = $this->lexer->yylloc;
74615 $this->lstack[] = $yyloc;
74616
74617 $symbol = null;
74618 $preErrorSymbol = null;
74619 $state = null;
74620 $action = null;
74621 $a = null;
74622 $r = null;
74623 $yyval = new stdClass;
74624 $p = null;
74625 $len = null;
74626 $newState = null;
74627 $expected = null;
74628 $errStr = null;
74629
74630 while (true) {
74631
74632  $state = $this->stack[count($this->stack)-1];
74633
74634
74635  if (isset($this->defaultActions[$state])) {
74636 $action = $this->defaultActions[$state];
74637 } else {
74638 if ($symbol == null) {
74639 $symbol = $this->lex();
74640 }
74641
74642  $action = isset($this->table[$state][$symbol]) ? $this->table[$state][$symbol] : false;
74643 }
74644
74645
74646  if (!$action || !$action[0]) {
74647 if (!$recovering) {
74648
74649  $expected = array();
74650 foreach ($this->table[$state] as $p => $ignore) {
74651 if (isset($this->terminals_[$p]) && $p > 2) {
74652 $expected[] = "'" . $this->terminals_[$p] . "'";
74653 }
74654 }
74655
74656 $message = null;
74657 if (in_array("'STRING'", $expected) && in_array(substr($this->lexer->match, 0, 1), array('"', "'"))) {
74658 $message = "Invalid string";
74659 if ("'" === substr($this->lexer->match, 0, 1)) {
74660 $message .= ", it appears you used single quotes instead of double quotes";
74661 } elseif (preg_match('{".+?(\\\\[^"bfnrt/\\\\u])}', $this->lexer->getUpcomingInput(), $match)) {
74662 $message .= ", it appears you have an unescaped backslash at: ".$match[1];
74663 } elseif (preg_match('{"(?:[^"]+|\\\\")*$}m', $this->lexer->getUpcomingInput())) {
74664 $message .= ", it appears you forgot to terminate a string, or attempted to write a multiline string which is invalid";
74665 }
74666 }
74667
74668 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
74669 $errStr .= $this->lexer->showPosition() . "\n";
74670 if ($message) {
74671 $errStr .= $message;
74672 } else {
74673 $errStr .= (count($expected) > 1) ? "Expected one of: " : "Expected: ";
74674 $errStr .= implode(', ', $expected);
74675 }
74676
74677 if (',' === substr(trim($this->lexer->getPastInput()), -1)) {
74678 $errStr .= " - It appears you have an extra trailing comma";
74679 }
74680
74681 $this->parseError($errStr, array(
74682 'text' => $this->lexer->match,
74683 'token' => !empty($this->terminals_[$symbol]) ? $this->terminals_[$symbol] : $symbol,
74684 'line' => $this->lexer->yylineno,
74685 'loc' => $yyloc,
74686 'expected' => $expected,
74687 ));
74688 }
74689
74690
74691  if ($recovering == 3) {
74692 if ($symbol == $EOF) {
74693 throw new ParsingException($errStr ?: 'Parsing halted.');
74694 }
74695
74696
74697  $yyleng = $this->lexer->yyleng;
74698 $yytext = $this->lexer->yytext;
74699 $yylineno = $this->lexer->yylineno;
74700 $yyloc = $this->lexer->yylloc;
74701 $symbol = $this->lex();
74702 }
74703
74704
74705  while (true) {
74706
74707  if (array_key_exists($TERROR, $this->table[$state])) {
74708 break;
74709 }
74710 if ($state == 0) {
74711 throw new ParsingException($errStr ?: 'Parsing halted.');
74712 }
74713 $this->popStack(1);
74714 $state = $this->stack[count($this->stack)-1];
74715 }
74716
74717 $preErrorSymbol = $symbol; 
74718  $symbol = $TERROR; 
74719  $state = $this->stack[count($this->stack)-1];
74720 $action = isset($this->table[$state][$TERROR]) ? $this->table[$state][$TERROR] : false;
74721 $recovering = 3; 
74722  }
74723
74724
74725  if (is_array($action[0]) && count($action) > 1) {
74726 throw new ParsingException('Parse Error: multiple actions possible at state: ' . $state . ', token: ' . $symbol);
74727 }
74728
74729 switch ($action[0]) {
74730 case 1: 
74731  $this->stack[] = $symbol;
74732 $this->vstack[] = $this->lexer->yytext;
74733 $this->lstack[] = $this->lexer->yylloc;
74734 $this->stack[] = $action[1]; 
74735  $symbol = null;
74736 if (!$preErrorSymbol) { 
74737  $yyleng = $this->lexer->yyleng;
74738 $yytext = $this->lexer->yytext;
74739 $yylineno = $this->lexer->yylineno;
74740 $yyloc = $this->lexer->yylloc;
74741 if ($recovering > 0) {
74742 $recovering--;
74743 }
74744 } else { 
74745  $symbol = $preErrorSymbol;
74746 $preErrorSymbol = null;
74747 }
74748 break;
74749
74750 case 2: 
74751  $len = $this->productions_[$action[1]][1];
74752
74753
74754  $yyval->token = $this->vstack[count($this->vstack) - $len]; 
74755  
74756  $yyval->store = array( 
74757  'first_line' => $this->lstack[count($this->lstack) - ($len ?: 1)]['first_line'],
74758 'last_line' => $this->lstack[count($this->lstack) - 1]['last_line'],
74759 'first_column' => $this->lstack[count($this->lstack) - ($len ?: 1)]['first_column'],
74760 'last_column' => $this->lstack[count($this->lstack) - 1]['last_column'],
74761 );
74762 $r = $this->performAction($yyval, $yytext, $yyleng, $yylineno, $action[1], $this->vstack, $this->lstack);
74763
74764 if (!$r instanceof Undefined) {
74765 return $r;
74766 }
74767
74768 if ($len) {
74769 $this->popStack($len);
74770 }
74771
74772 $this->stack[] = $this->productions_[$action[1]][0]; 
74773  $this->vstack[] = $yyval->token;
74774 $this->lstack[] = $yyval->store;
74775 $newState = $this->table[$this->stack[count($this->stack)-2]][$this->stack[count($this->stack)-1]];
74776 $this->stack[] = $newState;
74777 break;
74778
74779 case 3: 
74780
74781 return true;
74782 }
74783 }
74784
74785 return true;
74786 }
74787
74788 protected function parseError($str, $hash)
74789 {
74790 throw new ParsingException($str, $hash);
74791 }
74792
74793
74794  
74795  
74796  private function performAction(stdClass $yyval, $yytext, $yyleng, $yylineno, $yystate, &$tokens)
74797 {
74798
74799  $len = count($tokens) - 1;
74800 switch ($yystate) {
74801 case 1:
74802 $yytext = preg_replace_callback('{(?:\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4})}', array($this, 'stringInterpolation'), $yytext);
74803 $yyval->token = $yytext;
74804 break;
74805 case 2:
74806 if (strpos($yytext, 'e') !== false || strpos($yytext, 'E') !== false) {
74807 $yyval->token = floatval($yytext);
74808 } else {
74809 $yyval->token = strpos($yytext, '.') === false ? intval($yytext) : floatval($yytext);
74810 }
74811 break;
74812 case 3:
74813 $yyval->token = null;
74814 break;
74815 case 4:
74816 $yyval->token = true;
74817 break;
74818 case 5:
74819 $yyval->token = false;
74820 break;
74821 case 6:
74822 return $yyval->token = $tokens[$len-1];
74823 case 13:
74824 if ($this->flags & self::PARSE_TO_ASSOC) {
74825 $yyval->token = array();
74826 } else {
74827 $yyval->token = new stdClass;
74828 }
74829 break;
74830 case 14:
74831 $yyval->token = $tokens[$len-1];
74832 break;
74833 case 15:
74834 $yyval->token = array($tokens[$len-2], $tokens[$len]);
74835 break;
74836 case 16:
74837 if (PHP_VERSION_ID < 70100) {
74838 $property = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
74839 } else {
74840 $property = $tokens[$len][0];
74841 }
74842 if ($this->flags & self::PARSE_TO_ASSOC) {
74843 $yyval->token = array();
74844 $yyval->token[$property] = $tokens[$len][1];
74845 } else {
74846 $yyval->token = new stdClass;
74847 $yyval->token->$property = $tokens[$len][1];
74848 }
74849 break;
74850 case 17:
74851 if ($this->flags & self::PARSE_TO_ASSOC) {
74852 $yyval->token =& $tokens[$len-2];
74853 $key = $tokens[$len][0];
74854 if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2][$key])) {
74855 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
74856 $errStr .= $this->lexer->showPosition() . "\n";
74857 $errStr .= "Duplicate key: ".$tokens[$len][0];
74858 throw new DuplicateKeyException($errStr, $tokens[$len][0], array('line' => $yylineno+1));
74859 } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2][$key])) {
74860 $duplicateCount = 1;
74861 do {
74862 $duplicateKey = $key . '.' . $duplicateCount++;
74863 } while (isset($tokens[$len-2][$duplicateKey]));
74864 $key = $duplicateKey;
74865 }
74866 $tokens[$len-2][$key] = $tokens[$len][1];
74867 } else {
74868 $yyval->token = $tokens[$len-2];
74869 if (PHP_VERSION_ID < 70100) {
74870 $key = $tokens[$len][0] === '' ? '_empty_' : $tokens[$len][0];
74871 } else {
74872 $key = $tokens[$len][0];
74873 }
74874 if (($this->flags & self::DETECT_KEY_CONFLICTS) && isset($tokens[$len-2]->{$key})) {
74875 $errStr = 'Parse error on line ' . ($yylineno+1) . ":\n";
74876 $errStr .= $this->lexer->showPosition() . "\n";
74877 $errStr .= "Duplicate key: ".$tokens[$len][0];
74878 throw new DuplicateKeyException($errStr, $tokens[$len][0], array('line' => $yylineno+1));
74879 } elseif (($this->flags & self::ALLOW_DUPLICATE_KEYS) && isset($tokens[$len-2]->{$key})) {
74880 $duplicateCount = 1;
74881 do {
74882 $duplicateKey = $key . '.' . $duplicateCount++;
74883 } while (isset($tokens[$len-2]->$duplicateKey));
74884 $key = $duplicateKey;
74885 }
74886 $tokens[$len-2]->$key = $tokens[$len][1];
74887 }
74888 break;
74889 case 18:
74890 $yyval->token = array();
74891 break;
74892 case 19:
74893 $yyval->token = $tokens[$len-1];
74894 break;
74895 case 20:
74896 $yyval->token = array($tokens[$len]);
74897 break;
74898 case 21:
74899 $tokens[$len-2][] = $tokens[$len];
74900 $yyval->token = $tokens[$len-2];
74901 break;
74902 }
74903
74904 return new Undefined();
74905 }
74906
74907 private function stringInterpolation($match)
74908 {
74909 switch ($match[0]) {
74910 case '\\\\':
74911 return '\\';
74912 case '\"':
74913 return '"';
74914 case '\b':
74915 return chr(8);
74916 case '\f':
74917 return chr(12);
74918 case '\n':
74919 return "\n";
74920 case '\r':
74921 return "\r";
74922 case '\t':
74923 return "\t";
74924 case '\/':
74925 return "/";
74926 default:
74927 return html_entity_decode('&#x'.ltrim(substr($match[0], 2), '0').';', 0, 'UTF-8');
74928 }
74929 }
74930
74931 private function popStack($n)
74932 {
74933 $this->stack = array_slice($this->stack, 0, - (2 * $n));
74934 $this->vstack = array_slice($this->vstack, 0, - $n);
74935 $this->lstack = array_slice($this->lstack, 0, - $n);
74936 }
74937
74938 private function lex()
74939 {
74940 $token = $this->lexer->lex() ?: 1; 
74941  
74942  if (!is_numeric($token)) {
74943 $token = isset($this->symbols[$token]) ? $this->symbols[$token] : $token;
74944 }
74945
74946 return $token;
74947 }
74948
74949 private function failOnBOM($input)
74950 {
74951
74952  $bom = "\xEF\xBB\xBF";
74953
74954 if (substr($input, 0, 3) === $bom) {
74955 $this->parseError("BOM detected, make sure your input does not include a Unicode Byte-Order-Mark", array());
74956 }
74957 }
74958 }
74959 <?php
74960
74961
74962
74963
74964
74965
74966
74967
74968
74969
74970 namespace Seld\JsonLint;
74971
74972
74973
74974
74975
74976
74977 class Lexer
74978 {
74979 private $EOF = 1;
74980 private $rules = array(
74981 0 => '/^\s+/',
74982 1 => '/^-?([0-9]|[1-9][0-9]+)(\.[0-9]+)?([eE][+-]?[0-9]+)?\b/',
74983 2 => '{^"(?>\\\\["bfnrt/\\\\]|\\\\u[a-fA-F0-9]{4}|[^\0-\x1f\\\\"]++)*+"}',
74984 3 => '/^\{/',
74985 4 => '/^\}/',
74986 5 => '/^\[/',
74987 6 => '/^\]/',
74988 7 => '/^,/',
74989 8 => '/^:/',
74990 9 => '/^true\b/',
74991 10 => '/^false\b/',
74992 11 => '/^null\b/',
74993 12 => '/^$/',
74994 13 => '/^./',
74995 );
74996
74997 private $conditions = array(
74998 "INITIAL" => array(
74999 "rules" => array(0,1,2,3,4,5,6,7,8,9,10,11,12,13),
75000 "inclusive" => true,
75001 ),
75002 );
75003
75004 private $conditionStack;
75005 private $input;
75006 private $more;
75007 private $done;
75008 private $matched;
75009
75010 public $match;
75011 public $yylineno;
75012 public $yyleng;
75013 public $yytext;
75014 public $yylloc;
75015
75016 public function lex()
75017 {
75018 $r = $this->next();
75019 if (!$r instanceof Undefined) {
75020 return $r;
75021 }
75022
75023 return $this->lex();
75024 }
75025
75026 public function setInput($input)
75027 {
75028 $this->input = $input;
75029 $this->more = false;
75030 $this->done = false;
75031 $this->yylineno = $this->yyleng = 0;
75032 $this->yytext = $this->matched = $this->match = '';
75033 $this->conditionStack = array('INITIAL');
75034 $this->yylloc = array('first_line' => 1, 'first_column' => 0, 'last_line' => 1, 'last_column' => 0);
75035
75036 return $this;
75037 }
75038
75039 public function showPosition()
75040 {
75041 $pre = str_replace("\n", '', $this->getPastInput());
75042 $c = str_repeat('-', max(0, strlen($pre) - 1)); 
75043
75044 return $pre . str_replace("\n", '', $this->getUpcomingInput()) . "\n" . $c . "^";
75045 }
75046
75047 public function getPastInput()
75048 {
75049 $past = substr($this->matched, 0, strlen($this->matched) - strlen($this->match));
75050
75051 return (strlen($past) > 20 ? '...' : '') . substr($past, -20);
75052 }
75053
75054 public function getUpcomingInput()
75055 {
75056 $next = $this->match;
75057 if (strlen($next) < 20) {
75058 $next .= substr($this->input, 0, 20 - strlen($next));
75059 }
75060
75061 return substr($next, 0, 20) . (strlen($next) > 20 ? '...' : '');
75062 }
75063
75064 protected function parseError($str, $hash)
75065 {
75066 throw new \Exception($str);
75067 }
75068
75069 private function next()
75070 {
75071 if ($this->done) {
75072 return $this->EOF;
75073 }
75074 if ($this->input === '') {
75075 $this->done = true;
75076 }
75077
75078 $token = null;
75079 $match = null;
75080 $col = null;
75081 $lines = null;
75082
75083 if (!$this->more) {
75084 $this->yytext = '';
75085 $this->match = '';
75086 }
75087
75088 $rules = $this->getCurrentRules();
75089 $rulesLen = count($rules);
75090
75091 for ($i=0; $i < $rulesLen; $i++) {
75092 if (preg_match($this->rules[$rules[$i]], $this->input, $match)) {
75093 preg_match_all('/\n.*/', $match[0], $lines);
75094 $lines = $lines[0];
75095 if ($lines) {
75096 $this->yylineno += count($lines);
75097 }
75098
75099 $this->yylloc = array(
75100 'first_line' => $this->yylloc['last_line'],
75101 'last_line' => $this->yylineno+1,
75102 'first_column' => $this->yylloc['last_column'],
75103 'last_column' => $lines ? strlen($lines[count($lines) - 1]) - 1 : $this->yylloc['last_column'] + strlen($match[0]),
75104 );
75105 $this->yytext .= $match[0];
75106 $this->match .= $match[0];
75107 $this->yyleng = strlen($this->yytext);
75108 $this->more = false;
75109 $this->input = substr($this->input, strlen($match[0]));
75110 $this->matched .= $match[0];
75111 $token = $this->performAction($rules[$i], $this->conditionStack[count($this->conditionStack)-1]);
75112 if ($token) {
75113 return $token;
75114 }
75115
75116 return new Undefined();
75117 }
75118 }
75119
75120 if ($this->input === "") {
75121 return $this->EOF;
75122 }
75123
75124 $this->parseError(
75125 'Lexical error on line ' . ($this->yylineno+1) . ". Unrecognized text.\n" . $this->showPosition(),
75126 array(
75127 'text' => "",
75128 'token' => null,
75129 'line' => $this->yylineno,
75130 )
75131 );
75132 }
75133
75134 private function getCurrentRules()
75135 {
75136 return $this->conditions[$this->conditionStack[count($this->conditionStack)-1]]['rules'];
75137 }
75138
75139 private function performAction($avoiding_name_collisions, $YY_START)
75140 {
75141 switch ($avoiding_name_collisions) {
75142 case 0:
75143 break;
75144 case 1:
75145 return 6;
75146 break;
75147 case 2:
75148 $this->yytext = substr($this->yytext, 1, $this->yyleng-2);
75149
75150 return 4;
75151 case 3:
75152 return 17;
75153 case 4:
75154 return 18;
75155 case 5:
75156 return 23;
75157 case 6:
75158 return 24;
75159 case 7:
75160 return 22;
75161 case 8:
75162 return 21;
75163 case 9:
75164 return 10;
75165 case 10:
75166 return 11;
75167 case 11:
75168 return 8;
75169 case 12:
75170 return 14;
75171 case 13:
75172 return 'INVALID';
75173 }
75174 }
75175 }
75176 <?php
75177
75178
75179
75180
75181
75182
75183
75184
75185
75186
75187 namespace Seld\JsonLint;
75188
75189 class ParsingException extends \Exception
75190 {
75191 protected $details;
75192
75193 public function __construct($message, $details = array())
75194 {
75195 $this->details = $details;
75196 parent::__construct($message);
75197 }
75198
75199 public function getDetails()
75200 {
75201 return $this->details;
75202 }
75203 }
75204 <?php
75205
75206
75207
75208
75209
75210
75211
75212
75213
75214
75215 namespace Seld\JsonLint;
75216
75217 class Undefined
75218 {
75219 }
75220 Copyright (c) 2015 Jordi Boggiano
75221
75222 Permission is hereby granted, free of charge, to any person obtaining a copy
75223 of this software and associated documentation files (the "Software"), to deal
75224 in the Software without restriction, including without limitation the rights
75225 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
75226 copies of the Software, and to permit persons to whom the Software is furnished
75227 to do so, subject to the following conditions:
75228
75229 The above copyright notice and this permission notice shall be included in all
75230 copies or substantial portions of the Software.
75231
75232 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
75233 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
75234 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
75235 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
75236 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
75237 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
75238 THE SOFTWARE.
75239 <?php
75240
75241 require __DIR__.'/../vendor/autoload.php';
75242
75243 echo 'Say hello (visible): ';
75244
75245 $answer = Seld\CliPrompt\CliPrompt::prompt();
75246
75247 echo 'You answered: '.$answer . PHP_EOL;
75248
75249 echo 'Say hello (hidden): ';
75250
75251 $answer = Seld\CliPrompt\CliPrompt::hiddenPrompt();
75252
75253 echo 'You answered: '.$answer . PHP_EOL;
75254 <?php
75255
75256
75257
75258
75259
75260
75261
75262
75263
75264
75265 namespace Seld\CliPrompt;
75266
75267 class CliPrompt
75268 {
75269
75270
75271
75272
75273
75274 public static function prompt()
75275 {
75276 $stdin = fopen('php://stdin', 'r');
75277 $answer = self::trimAnswer(fgets($stdin, 4096));
75278 fclose($stdin);
75279
75280 return $answer;
75281 }
75282
75283
75284
75285
75286
75287
75288
75289
75290
75291
75292 public static function hiddenPrompt($allowFallback = false)
75293 {
75294
75295  if (defined('PHP_WINDOWS_VERSION_BUILD')) {
75296
75297  $exe = __DIR__.'\\..\\res\\hiddeninput.exe';
75298
75299
75300  if ('phar:' === substr(__FILE__, 0, 5)) {
75301 $tmpExe = sys_get_temp_dir().'/hiddeninput.exe';
75302
75303
75304  
75305  $source = fopen($exe, 'r');
75306 $target = fopen($tmpExe, 'w+');
75307 stream_copy_to_stream($source, $target);
75308 fclose($source);
75309 fclose($target);
75310 unset($source, $target);
75311
75312 $exe = $tmpExe;
75313 }
75314
75315 $output = shell_exec($exe);
75316
75317
75318  if (isset($tmpExe)) {
75319 unlink($tmpExe);
75320 }
75321
75322 if ($output !== null) {
75323
75324  echo PHP_EOL;
75325
75326 return self::trimAnswer($output);
75327 }
75328 }
75329
75330 if (file_exists('/usr/bin/env')) {
75331
75332  $test = "/usr/bin/env %s -c 'echo OK' 2> /dev/null";
75333 foreach (array('bash', 'zsh', 'ksh', 'csh', 'sh') as $sh) {
75334 if ('OK' === rtrim(shell_exec(sprintf($test, $sh)))) {
75335 $shell = $sh;
75336 break;
75337 }
75338 }
75339
75340 if (isset($shell)) {
75341 $readCmd = ($shell === 'csh') ? 'set mypassword = $<' : 'read -r mypassword';
75342 $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd);
75343 $output = shell_exec($command);
75344
75345 if ($output !== null) {
75346
75347  echo PHP_EOL;
75348
75349 return self::trimAnswer($output);
75350 }
75351 }
75352 }
75353
75354
75355  if (!$allowFallback) {
75356 throw new \RuntimeException('Could not prompt for input in a secure fashion, aborting');
75357 }
75358
75359 return self::prompt();
75360 }
75361
75362 private static function trimAnswer($str)
75363 {
75364 return preg_replace('{\r?\n$}D', '', $str);
75365 }
75366 }
75367 MIT License
75368
75369 Copyright (c) 2016
75370
75371 Permission is hereby granted, free of charge, to any person obtaining a copy
75372 of this software and associated documentation files (the "Software"), to deal
75373 in the Software without restriction, including without limitation the rights
75374 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
75375 copies of the Software, and to permit persons to whom the Software is
75376 furnished to do so, subject to the following conditions:
75377
75378 The above copyright notice and this permission notice shall be included in all
75379 copies or substantial portions of the Software.
75380
75381 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
75382 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
75383 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
75384 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
75385 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
75386 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
75387 SOFTWARE.
75388 <?php
75389
75390 require __DIR__ . '/../vendor/autoload.php';
75391
75392 $data = json_decode(file_get_contents('data.json'));
75393
75394
75395 $validator = new JsonSchema\Validator();
75396 $validator->check($data, (object) array('$ref' => 'file://' . realpath('schema.json')));
75397
75398 if ($validator->isValid()) {
75399 echo "The supplied JSON validates against the schema.\n";
75400 } else {
75401 echo "JSON does not validate. Violations:\n";
75402 foreach ($validator->getErrors() as $error) {
75403 echo sprintf("[%s] %s\n", $error['property'], $error['message']);
75404 }
75405 }
75406 <?php
75407
75408
75409
75410
75411
75412
75413
75414
75415 namespace JsonSchema\Constraints;
75416
75417 use JsonSchema\Entity\JsonPointer;
75418 use JsonSchema\Exception\InvalidArgumentException;
75419 use JsonSchema\Exception\ValidationException;
75420 use JsonSchema\Validator;
75421
75422
75423
75424
75425
75426 class BaseConstraint
75427 {
75428
75429
75430
75431 protected $errors = array();
75432
75433
75434
75435
75436 protected $errorMask = Validator::ERROR_NONE;
75437
75438
75439
75440
75441 protected $factory;
75442
75443
75444
75445
75446 public function __construct(Factory $factory = null)
75447 {
75448 $this->factory = $factory ?: new Factory();
75449 }
75450
75451 public function addError(JsonPointer $path = null, $message, $constraint = '', array $more = null)
75452 {
75453 $error = array(
75454 'property' => $this->convertJsonPointerIntoPropertyPath($path ?: new JsonPointer('')),
75455 'pointer' => ltrim(strval($path ?: new JsonPointer('')), '#'),
75456 'message' => $message,
75457 'constraint' => $constraint,
75458 'context' => $this->factory->getErrorContext(),
75459 );
75460
75461 if ($this->factory->getConfig(Constraint::CHECK_MODE_EXCEPTIONS)) {
75462 throw new ValidationException(sprintf('Error validating %s: %s', $error['pointer'], $error['message']));
75463 }
75464
75465 if (is_array($more) && count($more) > 0) {
75466 $error += $more;
75467 }
75468
75469 $this->errors[] = $error;
75470 $this->errorMask |= $error['context'];
75471 }
75472
75473 public function addErrors(array $errors)
75474 {
75475 if ($errors) {
75476 $this->errors = array_merge($this->errors, $errors);
75477 $errorMask = &$this->errorMask;
75478 array_walk($errors, function ($error) use (&$errorMask) {
75479 if (isset($error['context'])) {
75480 $errorMask |= $error['context'];
75481 }
75482 });
75483 }
75484 }
75485
75486 public function getErrors($errorContext = Validator::ERROR_ALL)
75487 {
75488 if ($errorContext === Validator::ERROR_ALL) {
75489 return $this->errors;
75490 }
75491
75492 return array_filter($this->errors, function ($error) use ($errorContext) {
75493 if ($errorContext & $error['context']) {
75494 return true;
75495 }
75496 });
75497 }
75498
75499 public function numErrors($errorContext = Validator::ERROR_ALL)
75500 {
75501 if ($errorContext === Validator::ERROR_ALL) {
75502 return count($this->errors);
75503 }
75504
75505 return count($this->getErrors($errorContext));
75506 }
75507
75508 public function isValid()
75509 {
75510 return !$this->getErrors();
75511 }
75512
75513
75514
75515
75516
75517 public function reset()
75518 {
75519 $this->errors = array();
75520 $this->errorMask = Validator::ERROR_NONE;
75521 }
75522
75523
75524
75525
75526
75527
75528 public function getErrorMask()
75529 {
75530 return $this->errorMask;
75531 }
75532
75533
75534
75535
75536
75537
75538
75539
75540 public static function arrayToObjectRecursive($array)
75541 {
75542 $json = json_encode($array);
75543 if (json_last_error() !== \JSON_ERROR_NONE) {
75544 $message = 'Unable to encode schema array as JSON';
75545 if (function_exists('json_last_error_msg')) {
75546 $message .= ': ' . json_last_error_msg();
75547 }
75548 throw new InvalidArgumentException($message);
75549 }
75550
75551 return (object) json_decode($json);
75552 }
75553 }
75554 <?php
75555
75556
75557
75558
75559
75560
75561
75562
75563 namespace JsonSchema\Constraints;
75564
75565 use JsonSchema\Entity\JsonPointer;
75566
75567
75568
75569
75570
75571
75572
75573 class CollectionConstraint extends Constraint
75574 {
75575
75576
75577
75578 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null)
75579 {
75580
75581  if (isset($schema->minItems) && count($value) < $schema->minItems) {
75582 $this->addError($path, 'There must be a minimum of ' . $schema->minItems . ' items in the array', 'minItems', array('minItems' => $schema->minItems));
75583 }
75584
75585
75586  if (isset($schema->maxItems) && count($value) > $schema->maxItems) {
75587 $this->addError($path, 'There must be a maximum of ' . $schema->maxItems . ' items in the array', 'maxItems', array('maxItems' => $schema->maxItems));
75588 }
75589
75590
75591  if (isset($schema->uniqueItems) && $schema->uniqueItems) {
75592 $unique = $value;
75593 if (is_array($value) && count($value)) {
75594 $unique = array_map(function ($e) {
75595 return var_export($e, true);
75596 }, $value);
75597 }
75598 if (count(array_unique($unique)) != count($value)) {
75599 $this->addError($path, 'There are no duplicates allowed in the array', 'uniqueItems');
75600 }
75601 }
75602
75603
75604  if (isset($schema->items)) {
75605 $this->validateItems($value, $schema, $path, $i);
75606 }
75607 }
75608
75609
75610
75611
75612
75613
75614
75615
75616
75617 protected function validateItems(&$value, $schema = null, JsonPointer $path = null, $i = null)
75618 {
75619 if (is_object($schema->items)) {
75620
75621
75622 if (isset($schema->items->type)
75623 && (
75624 $schema->items->type == 'string'
75625 || $schema->items->type == 'number'
75626 || $schema->items->type == 'integer'
75627 )
75628 && !isset($schema->additionalItems)
75629 ) {
75630
75631  $type = $schema->items->type;
75632 $typeValidator = $this->factory->createInstanceFor('type');
75633 $validator = $this->factory->createInstanceFor($type === 'integer' ? 'number' : $type);
75634
75635 foreach ($value as $k => &$v) {
75636 $k_path = $this->incrementPath($path, $k);
75637 $typeValidator->check($v, $schema->items, $k_path, $i);
75638
75639 $validator->check($v, $schema->items, $k_path, $i);
75640 }
75641 unset($v); 
75642  
75643  $this->addErrors($typeValidator->getErrors());
75644 $this->addErrors($validator->getErrors());
75645 } else {
75646 foreach ($value as $k => &$v) {
75647 $initErrors = $this->getErrors();
75648
75649
75650  $this->checkUndefined($v, $schema->items, $path, $k);
75651
75652
75653  if (count($initErrors) < count($this->getErrors()) && (isset($schema->additionalItems) && $schema->additionalItems !== false)) {
75654 $secondErrors = $this->getErrors();
75655 $this->checkUndefined($v, $schema->additionalItems, $path, $k);
75656 }
75657
75658
75659  if (isset($secondErrors) && count($secondErrors) < count($this->getErrors())) {
75660 $this->errors = $secondErrors;
75661 } elseif (isset($secondErrors) && count($secondErrors) === count($this->getErrors())) {
75662 $this->errors = $initErrors;
75663 }
75664 }
75665 unset($v); 
75666  
75667  }
75668 } else {
75669
75670  foreach ($value as $k => &$v) {
75671 if (array_key_exists($k, $schema->items)) {
75672 $this->checkUndefined($v, $schema->items[$k], $path, $k);
75673 } else {
75674
75675  if (property_exists($schema, 'additionalItems')) {
75676 if ($schema->additionalItems !== false) {
75677 $this->checkUndefined($v, $schema->additionalItems, $path, $k);
75678 } else {
75679 $this->addError(
75680 $path, 'The item ' . $i . '[' . $k . '] is not defined and the definition does not allow additional items', 'additionalItems', array('additionalItems' => $schema->additionalItems));
75681 }
75682 } else {
75683
75684  $this->checkUndefined($v, new \stdClass(), $path, $k);
75685 }
75686 }
75687 }
75688 unset($v); 
75689  
75690
75691
75692  if (count($value) > 0) {
75693 for ($k = count($value); $k < count($schema->items); $k++) {
75694 $undefinedInstance = $this->factory->createInstanceFor('undefined');
75695 $this->checkUndefined($undefinedInstance, $schema->items[$k], $path, $k);
75696 }
75697 }
75698 }
75699 }
75700 }
75701 <?php
75702
75703
75704
75705
75706
75707
75708
75709
75710 namespace JsonSchema\Constraints;
75711
75712 use JsonSchema\Entity\JsonPointer;
75713 use JsonSchema\SchemaStorage;
75714 use JsonSchema\Uri\UriRetriever;
75715 use JsonSchema\UriRetrieverInterface;
75716
75717
75718
75719
75720
75721
75722
75723 abstract class Constraint extends BaseConstraint implements ConstraintInterface
75724 {
75725 protected $inlineSchemaProperty = '$schema';
75726
75727 const CHECK_MODE_NONE = 0x00000000;
75728 const CHECK_MODE_NORMAL = 0x00000001;
75729 const CHECK_MODE_TYPE_CAST = 0x00000002;
75730 const CHECK_MODE_COERCE_TYPES = 0x00000004;
75731 const CHECK_MODE_APPLY_DEFAULTS = 0x00000008;
75732 const CHECK_MODE_EXCEPTIONS = 0x00000010;
75733 const CHECK_MODE_DISABLE_FORMAT = 0x00000020;
75734 const CHECK_MODE_ONLY_REQUIRED_DEFAULTS = 0x00000080;
75735 const CHECK_MODE_VALIDATE_SCHEMA = 0x00000100;
75736
75737
75738
75739
75740
75741
75742
75743
75744
75745 protected function incrementPath(JsonPointer $path = null, $i)
75746 {
75747 $path = $path ?: new JsonPointer('');
75748 $path = $path->withPropertyPaths(
75749 array_merge(
75750 $path->getPropertyPaths(),
75751 array_filter(array($i), 'strlen')
75752 )
75753 );
75754
75755 return $path;
75756 }
75757
75758
75759
75760
75761
75762
75763
75764
75765
75766 protected function checkArray(&$value, $schema = null, JsonPointer $path = null, $i = null)
75767 {
75768 $validator = $this->factory->createInstanceFor('collection');
75769 $validator->check($value, $schema, $path, $i);
75770
75771 $this->addErrors($validator->getErrors());
75772 }
75773
75774
75775
75776
75777
75778
75779
75780
75781
75782
75783
75784 protected function checkObject(&$value, $schema = null, JsonPointer $path = null, $properties = null,
75785 $additionalProperties = null, $patternProperties = null, $appliedDefaults = array())
75786 {
75787 $validator = $this->factory->createInstanceFor('object');
75788 $validator->check($value, $schema, $path, $properties, $additionalProperties, $patternProperties, $appliedDefaults);
75789
75790 $this->addErrors($validator->getErrors());
75791 }
75792
75793
75794
75795
75796
75797
75798
75799
75800
75801 protected function checkType(&$value, $schema = null, JsonPointer $path = null, $i = null)
75802 {
75803 $validator = $this->factory->createInstanceFor('type');
75804 $validator->check($value, $schema, $path, $i);
75805
75806 $this->addErrors($validator->getErrors());
75807 }
75808
75809
75810
75811
75812
75813
75814
75815
75816
75817 protected function checkUndefined(&$value, $schema = null, JsonPointer $path = null, $i = null, $fromDefault = false)
75818 {
75819 $validator = $this->factory->createInstanceFor('undefined');
75820
75821 $validator->check($value, $this->factory->getSchemaStorage()->resolveRefSchema($schema), $path, $i, $fromDefault);
75822
75823 $this->addErrors($validator->getErrors());
75824 }
75825
75826
75827
75828
75829
75830
75831
75832
75833
75834 protected function checkString($value, $schema = null, JsonPointer $path = null, $i = null)
75835 {
75836 $validator = $this->factory->createInstanceFor('string');
75837 $validator->check($value, $schema, $path, $i);
75838
75839 $this->addErrors($validator->getErrors());
75840 }
75841
75842
75843
75844
75845
75846
75847
75848
75849
75850 protected function checkNumber($value, $schema = null, JsonPointer $path = null, $i = null)
75851 {
75852 $validator = $this->factory->createInstanceFor('number');
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 checkEnum($value, $schema = null, JsonPointer $path = null, $i = null)
75867 {
75868 $validator = $this->factory->createInstanceFor('enum');
75869 $validator->check($value, $schema, $path, $i);
75870
75871 $this->addErrors($validator->getErrors());
75872 }
75873
75874
75875
75876
75877
75878
75879
75880
75881
75882 protected function checkFormat($value, $schema = null, JsonPointer $path = null, $i = null)
75883 {
75884 $validator = $this->factory->createInstanceFor('format');
75885 $validator->check($value, $schema, $path, $i);
75886
75887 $this->addErrors($validator->getErrors());
75888 }
75889
75890
75891
75892
75893
75894
75895 protected function getTypeCheck()
75896 {
75897 return $this->factory->getTypeCheck();
75898 }
75899
75900
75901
75902
75903
75904
75905 protected function convertJsonPointerIntoPropertyPath(JsonPointer $pointer)
75906 {
75907 $result = array_map(
75908 function ($path) {
75909 return sprintf(is_numeric($path) ? '[%d]' : '.%s', $path);
75910 },
75911 $pointer->getPropertyPaths()
75912 );
75913
75914 return trim(implode('', $result), '.');
75915 }
75916 }
75917 <?php
75918
75919
75920
75921
75922
75923
75924
75925
75926 namespace JsonSchema\Constraints;
75927
75928 use JsonSchema\Entity\JsonPointer;
75929
75930
75931
75932
75933
75934
75935 interface ConstraintInterface
75936 {
75937
75938
75939
75940
75941
75942 public function getErrors();
75943
75944
75945
75946
75947
75948
75949 public function addErrors(array $errors);
75950
75951
75952
75953
75954
75955
75956
75957
75958
75959 public function addError(JsonPointer $path = null, $message, $constraint='', array $more = null);
75960
75961
75962
75963
75964
75965
75966 public function isValid();
75967
75968
75969
75970
75971
75972
75973
75974
75975
75976
75977
75978
75979
75980 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null);
75981 }
75982 <?php
75983
75984
75985
75986
75987
75988
75989
75990
75991 namespace JsonSchema\Constraints;
75992
75993 use JsonSchema\Entity\JsonPointer;
75994
75995
75996
75997
75998
75999
76000
76001 class EnumConstraint extends Constraint
76002 {
76003
76004
76005
76006 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
76007 {
76008
76009  if ($element instanceof UndefinedConstraint && (!isset($schema->required) || !$schema->required)) {
76010 return;
76011 }
76012 $type = gettype($element);
76013
76014 foreach ($schema->enum as $enum) {
76015 $enumType = gettype($enum);
76016 if ($this->factory->getConfig(self::CHECK_MODE_TYPE_CAST) && $type == 'array' && $enumType == 'object') {
76017 if ((object) $element == $enum) {
76018 return;
76019 }
76020 }
76021
76022 if ($type === gettype($enum)) {
76023 if ($type == 'object') {
76024 if ($element == $enum) {
76025 return;
76026 }
76027 } elseif ($element === $enum) {
76028 return;
76029 }
76030 }
76031 }
76032
76033 $this->addError($path, 'Does not have a value in the enumeration ' . json_encode($schema->enum), 'enum', array('enum' => $schema->enum));
76034 }
76035 }
76036 <?php
76037
76038
76039
76040
76041
76042
76043
76044
76045 namespace JsonSchema\Constraints;
76046
76047 use JsonSchema\Constraints\Constraint;
76048 use JsonSchema\Exception\InvalidArgumentException;
76049 use JsonSchema\Exception\InvalidConfigException;
76050 use JsonSchema\SchemaStorage;
76051 use JsonSchema\SchemaStorageInterface;
76052 use JsonSchema\Uri\UriRetriever;
76053 use JsonSchema\UriRetrieverInterface;
76054 use JsonSchema\Validator;
76055
76056
76057
76058
76059 class Factory
76060 {
76061
76062
76063
76064 protected $schemaStorage;
76065
76066
76067
76068
76069 protected $uriRetriever;
76070
76071
76072
76073
76074 private $checkMode = Constraint::CHECK_MODE_NORMAL;
76075
76076
76077
76078
76079 private $typeCheck = array();
76080
76081
76082
76083
76084 protected $errorContext = Validator::ERROR_DOCUMENT_VALIDATION;
76085
76086
76087
76088
76089 protected $constraintMap = array(
76090 'array' => 'JsonSchema\Constraints\CollectionConstraint',
76091 'collection' => 'JsonSchema\Constraints\CollectionConstraint',
76092 'object' => 'JsonSchema\Constraints\ObjectConstraint',
76093 'type' => 'JsonSchema\Constraints\TypeConstraint',
76094 'undefined' => 'JsonSchema\Constraints\UndefinedConstraint',
76095 'string' => 'JsonSchema\Constraints\StringConstraint',
76096 'number' => 'JsonSchema\Constraints\NumberConstraint',
76097 'enum' => 'JsonSchema\Constraints\EnumConstraint',
76098 'format' => 'JsonSchema\Constraints\FormatConstraint',
76099 'schema' => 'JsonSchema\Constraints\SchemaConstraint',
76100 'validator' => 'JsonSchema\Validator'
76101 );
76102
76103
76104
76105
76106 private $instanceCache = array();
76107
76108
76109
76110
76111
76112
76113 public function __construct(
76114 SchemaStorageInterface $schemaStorage = null,
76115 UriRetrieverInterface $uriRetriever = null,
76116 $checkMode = Constraint::CHECK_MODE_NORMAL
76117 ) {
76118
76119  $this->setConfig($checkMode);
76120
76121 $this->uriRetriever = $uriRetriever ?: new UriRetriever();
76122 $this->schemaStorage = $schemaStorage ?: new SchemaStorage($this->uriRetriever);
76123 }
76124
76125
76126
76127
76128
76129
76130 public function setConfig($checkMode = Constraint::CHECK_MODE_NORMAL)
76131 {
76132 $this->checkMode = $checkMode;
76133 }
76134
76135
76136
76137
76138
76139
76140 public function addConfig($options)
76141 {
76142 $this->checkMode |= $options;
76143 }
76144
76145
76146
76147
76148
76149
76150 public function removeConfig($options)
76151 {
76152 $this->checkMode &= ~$options;
76153 }
76154
76155
76156
76157
76158
76159
76160
76161
76162 public function getConfig($options = null)
76163 {
76164 if ($options === null) {
76165 return $this->checkMode;
76166 }
76167
76168 return $this->checkMode & $options;
76169 }
76170
76171
76172
76173
76174 public function getUriRetriever()
76175 {
76176 return $this->uriRetriever;
76177 }
76178
76179 public function getSchemaStorage()
76180 {
76181 return $this->schemaStorage;
76182 }
76183
76184 public function getTypeCheck()
76185 {
76186 if (!isset($this->typeCheck[$this->checkMode])) {
76187 $this->typeCheck[$this->checkMode] = ($this->checkMode & Constraint::CHECK_MODE_TYPE_CAST)
76188 ? new TypeCheck\LooseTypeCheck()
76189 : new TypeCheck\StrictTypeCheck();
76190 }
76191
76192 return $this->typeCheck[$this->checkMode];
76193 }
76194
76195
76196
76197
76198
76199
76200
76201 public function setConstraintClass($name, $class)
76202 {
76203
76204  if (!class_exists($class)) {
76205 throw new InvalidArgumentException('Unknown constraint ' . $name);
76206 }
76207
76208  if (!in_array('JsonSchema\Constraints\ConstraintInterface', class_implements($class))) {
76209 throw new InvalidArgumentException('Invalid class ' . $name);
76210 }
76211 $this->constraintMap[$name] = $class;
76212
76213 return $this;
76214 }
76215
76216
76217
76218
76219
76220
76221
76222
76223
76224
76225 public function createInstanceFor($constraintName)
76226 {
76227 if (!isset($this->constraintMap[$constraintName])) {
76228 throw new InvalidArgumentException('Unknown constraint ' . $constraintName);
76229 }
76230
76231 if (!isset($this->instanceCache[$constraintName])) {
76232 $this->instanceCache[$constraintName] = new $this->constraintMap[$constraintName]($this);
76233 }
76234
76235 return clone $this->instanceCache[$constraintName];
76236 }
76237
76238
76239
76240
76241
76242
76243 public function getErrorContext()
76244 {
76245 return $this->errorContext;
76246 }
76247
76248
76249
76250
76251
76252
76253 public function setErrorContext($errorContext)
76254 {
76255 $this->errorContext = $errorContext;
76256 }
76257 }
76258 <?php
76259
76260
76261
76262
76263
76264
76265
76266
76267 namespace JsonSchema\Constraints;
76268
76269 use JsonSchema\Entity\JsonPointer;
76270 use JsonSchema\Rfc3339;
76271
76272
76273
76274
76275
76276
76277
76278
76279 class FormatConstraint extends Constraint
76280 {
76281
76282
76283
76284 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
76285 {
76286 if (!isset($schema->format) || $this->factory->getConfig(self::CHECK_MODE_DISABLE_FORMAT)) {
76287 return;
76288 }
76289
76290 switch ($schema->format) {
76291 case 'date':
76292 if (!$date = $this->validateDateTime($element, 'Y-m-d')) {
76293 $this->addError($path, sprintf('Invalid date %s, expected format YYYY-MM-DD', json_encode($element)), 'format', array('format' => $schema->format));
76294 }
76295 break;
76296
76297 case 'time':
76298 if (!$this->validateDateTime($element, 'H:i:s')) {
76299 $this->addError($path, sprintf('Invalid time %s, expected format hh:mm:ss', json_encode($element)), 'format', array('format' => $schema->format));
76300 }
76301 break;
76302
76303 case 'date-time':
76304 if (null === Rfc3339::createFromString($element)) {
76305 $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));
76306 }
76307 break;
76308
76309 case 'utc-millisec':
76310 if (!$this->validateDateTime($element, 'U')) {
76311 $this->addError($path, sprintf('Invalid time %s, expected integer of milliseconds since Epoch', json_encode($element)), 'format', array('format' => $schema->format));
76312 }
76313 break;
76314
76315 case 'regex':
76316 if (!$this->validateRegex($element)) {
76317 $this->addError($path, 'Invalid regex format ' . $element, 'format', array('format' => $schema->format));
76318 }
76319 break;
76320
76321 case 'color':
76322 if (!$this->validateColor($element)) {
76323 $this->addError($path, 'Invalid color', 'format', array('format' => $schema->format));
76324 }
76325 break;
76326
76327 case 'style':
76328 if (!$this->validateStyle($element)) {
76329 $this->addError($path, 'Invalid style', 'format', array('format' => $schema->format));
76330 }
76331 break;
76332
76333 case 'phone':
76334 if (!$this->validatePhone($element)) {
76335 $this->addError($path, 'Invalid phone number', 'format', array('format' => $schema->format));
76336 }
76337 break;
76338
76339 case 'uri':
76340 if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
76341 $this->addError($path, 'Invalid URL format', 'format', array('format' => $schema->format));
76342 }
76343 break;
76344
76345 case 'uriref':
76346 case 'uri-reference':
76347 if (null === filter_var($element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE)) {
76348
76349  
76350  
76351  if (substr($element, 0, 2) === '//') { 
76352  $validURL = filter_var('scheme:' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
76353 } elseif (substr($element, 0, 1) === '/') { 
76354  $validURL = filter_var('scheme://host' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
76355 } elseif (strlen($element)) { 
76356  $pathParts = explode('/', $element, 2);
76357 if (strpos($pathParts[0], ':') !== false) {
76358 $validURL = null;
76359 } else {
76360 $validURL = filter_var('scheme://host/' . $element, FILTER_VALIDATE_URL, FILTER_NULL_ON_FAILURE);
76361 }
76362 } else {
76363 $validURL = null;
76364 }
76365 if ($validURL === null) {
76366 $this->addError($path, 'Invalid URL format', 'format', array('format' => $schema->format));
76367 }
76368 }
76369 break;
76370
76371 case 'email':
76372 $filterFlags = FILTER_NULL_ON_FAILURE;
76373 if (defined('FILTER_FLAG_EMAIL_UNICODE')) {
76374
76375  $filterFlags |= constant('FILTER_FLAG_EMAIL_UNICODE'); 
76376  }
76377 if (null === filter_var($element, FILTER_VALIDATE_EMAIL, $filterFlags)) {
76378 $this->addError($path, 'Invalid email', 'format', array('format' => $schema->format));
76379 }
76380 break;
76381
76382 case 'ip-address':
76383 case 'ipv4':
76384 if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV4)) {
76385 $this->addError($path, 'Invalid IP address', 'format', array('format' => $schema->format));
76386 }
76387 break;
76388
76389 case 'ipv6':
76390 if (null === filter_var($element, FILTER_VALIDATE_IP, FILTER_NULL_ON_FAILURE | FILTER_FLAG_IPV6)) {
76391 $this->addError($path, 'Invalid IP address', 'format', array('format' => $schema->format));
76392 }
76393 break;
76394
76395 case 'host-name':
76396 case 'hostname':
76397 if (!$this->validateHostname($element)) {
76398 $this->addError($path, 'Invalid hostname', 'format', array('format' => $schema->format));
76399 }
76400 break;
76401
76402 default:
76403
76404  
76405  
76406  
76407  
76408  
76409  break;
76410 }
76411 }
76412
76413 protected function validateDateTime($datetime, $format)
76414 {
76415 $dt = \DateTime::createFromFormat($format, $datetime);
76416
76417 if (!$dt) {
76418 return false;
76419 }
76420
76421 if ($datetime === $dt->format($format)) {
76422 return true;
76423 }
76424
76425
76426  
76427  
76428  
76429  if ((strpos('u', $format) !== -1) && (preg_match('/\.\d+Z$/', $datetime))) {
76430 return true;
76431 }
76432
76433 return false;
76434 }
76435
76436 protected function validateRegex($regex)
76437 {
76438 return false !== @preg_match('/' . $regex . '/u', '');
76439 }
76440
76441 protected function validateColor($color)
76442 {
76443 if (in_array(strtolower($color), array('aqua', 'black', 'blue', 'fuchsia',
76444 'gray', 'green', 'lime', 'maroon', 'navy', 'olive', 'orange', 'purple',
76445 'red', 'silver', 'teal', 'white', 'yellow'))) {
76446 return true;
76447 }
76448
76449 return preg_match('/^#([a-f0-9]{3}|[a-f0-9]{6})$/i', $color);
76450 }
76451
76452 protected function validateStyle($style)
76453 {
76454 $properties = explode(';', rtrim($style, ';'));
76455 $invalidEntries = preg_grep('/^\s*[-a-z]+\s*:\s*.+$/i', $properties, PREG_GREP_INVERT);
76456
76457 return empty($invalidEntries);
76458 }
76459
76460 protected function validatePhone($phone)
76461 {
76462 return preg_match('/^\+?(\(\d{3}\)|\d{3}) \d{3} \d{4}$/', $phone);
76463 }
76464
76465 protected function validateHostname($host)
76466 {
76467 $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';
76468
76469 return preg_match($hostnameRegex, $host);
76470 }
76471 }
76472 <?php
76473
76474
76475
76476
76477
76478
76479
76480
76481 namespace JsonSchema\Constraints;
76482
76483 use JsonSchema\Entity\JsonPointer;
76484
76485
76486
76487
76488
76489
76490
76491 class NumberConstraint extends Constraint
76492 {
76493
76494
76495
76496 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
76497 {
76498
76499  if (isset($schema->exclusiveMinimum)) {
76500 if (isset($schema->minimum)) {
76501 if ($schema->exclusiveMinimum && $element <= $schema->minimum) {
76502 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'exclusiveMinimum', array('minimum' => $schema->minimum));
76503 } elseif ($element < $schema->minimum) {
76504 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'minimum', array('minimum' => $schema->minimum));
76505 }
76506 } else {
76507 $this->addError($path, 'Use of exclusiveMinimum requires presence of minimum', 'missingMinimum');
76508 }
76509 } elseif (isset($schema->minimum) && $element < $schema->minimum) {
76510 $this->addError($path, 'Must have a minimum value of ' . $schema->minimum, 'minimum', array('minimum' => $schema->minimum));
76511 }
76512
76513
76514  if (isset($schema->exclusiveMaximum)) {
76515 if (isset($schema->maximum)) {
76516 if ($schema->exclusiveMaximum && $element >= $schema->maximum) {
76517 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'exclusiveMaximum', array('maximum' => $schema->maximum));
76518 } elseif ($element > $schema->maximum) {
76519 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'maximum', array('maximum' => $schema->maximum));
76520 }
76521 } else {
76522 $this->addError($path, 'Use of exclusiveMaximum requires presence of maximum', 'missingMaximum');
76523 }
76524 } elseif (isset($schema->maximum) && $element > $schema->maximum) {
76525 $this->addError($path, 'Must have a maximum value of ' . $schema->maximum, 'maximum', array('maximum' => $schema->maximum));
76526 }
76527
76528
76529  if (isset($schema->divisibleBy) && $this->fmod($element, $schema->divisibleBy) != 0) {
76530 $this->addError($path, 'Is not divisible by ' . $schema->divisibleBy, 'divisibleBy', array('divisibleBy' => $schema->divisibleBy));
76531 }
76532
76533
76534  if (isset($schema->multipleOf) && $this->fmod($element, $schema->multipleOf) != 0) {
76535 $this->addError($path, 'Must be a multiple of ' . $schema->multipleOf, 'multipleOf', array('multipleOf' => $schema->multipleOf));
76536 }
76537
76538 $this->checkFormat($element, $schema, $path, $i);
76539 }
76540
76541 private function fmod($number1, $number2)
76542 {
76543 $number1 = abs($number1);
76544 $modulus = fmod($number1, $number2);
76545 $precision = abs(0.0000000001);
76546 $diff = (float) ($modulus - $number2);
76547
76548 if (-$precision < $diff && $diff < $precision) {
76549 return 0.0;
76550 }
76551
76552 $decimals1 = mb_strpos($number1, '.') ? mb_strlen($number1) - mb_strpos($number1, '.') - 1 : 0;
76553 $decimals2 = mb_strpos($number2, '.') ? mb_strlen($number2) - mb_strpos($number2, '.') - 1 : 0;
76554
76555 return (float) round($modulus, max($decimals1, $decimals2));
76556 }
76557 }
76558 <?php
76559
76560
76561
76562
76563
76564
76565
76566
76567 namespace JsonSchema\Constraints;
76568
76569 use JsonSchema\Entity\JsonPointer;
76570
76571
76572
76573
76574
76575
76576
76577 class ObjectConstraint extends Constraint
76578 {
76579
76580
76581
76582 protected $appliedDefaults = array();
76583
76584
76585
76586
76587 public function check(&$element, $schema = null, JsonPointer $path = null, $properties = null,
76588 $additionalProp = null, $patternProperties = null, $appliedDefaults = array())
76589 {
76590 if ($element instanceof UndefinedConstraint) {
76591 return;
76592 }
76593
76594 $this->appliedDefaults = $appliedDefaults;
76595
76596 $matches = array();
76597 if ($patternProperties) {
76598
76599  $matches = $this->validatePatternProperties($element, $path, $patternProperties);
76600 }
76601
76602 if ($properties) {
76603
76604  $this->validateProperties($element, $properties, $path);
76605 }
76606
76607
76608  $this->validateElement($element, $matches, $schema, $path, $properties, $additionalProp);
76609 }
76610
76611 public function validatePatternProperties($element, JsonPointer $path = null, $patternProperties)
76612 {
76613 $try = array('/', '#', '+', '~', '%');
76614 $matches = array();
76615 foreach ($patternProperties as $pregex => $schema) {
76616 $delimiter = '/';
76617
76618  foreach ($try as $delimiter) {
76619 if (strpos($pregex, $delimiter) === false) { 
76620  break;
76621 }
76622 }
76623
76624
76625  if (@preg_match($delimiter . $pregex . $delimiter . 'u', '') === false) {
76626 $this->addError($path, 'The pattern "' . $pregex . '" is invalid', 'pregex', array('pregex' => $pregex));
76627 continue;
76628 }
76629 foreach ($element as $i => $value) {
76630 if (preg_match($delimiter . $pregex . $delimiter . 'u', $i)) {
76631 $matches[] = $i;
76632 $this->checkUndefined($value, $schema ?: new \stdClass(), $path, $i, in_array($i, $this->appliedDefaults));
76633 }
76634 }
76635 }
76636
76637 return $matches;
76638 }
76639
76640
76641
76642
76643
76644
76645
76646
76647
76648
76649
76650 public function validateElement($element, $matches, $schema = null, JsonPointer $path = null,
76651 $properties = null, $additionalProp = null)
76652 {
76653 $this->validateMinMaxConstraint($element, $schema, $path);
76654
76655 foreach ($element as $i => $value) {
76656 $definition = $this->getProperty($properties, $i);
76657
76658
76659  if (!in_array($i, $matches) && $additionalProp === false && $this->inlineSchemaProperty !== $i && !$definition) {
76660 $this->addError($path, 'The property ' . $i . ' is not defined and the definition does not allow additional properties', 'additionalProp');
76661 }
76662
76663
76664  if (!in_array($i, $matches) && $additionalProp && !$definition) {
76665 if ($additionalProp === true) {
76666 $this->checkUndefined($value, null, $path, $i, in_array($i, $this->appliedDefaults));
76667 } else {
76668 $this->checkUndefined($value, $additionalProp, $path, $i, in_array($i, $this->appliedDefaults));
76669 }
76670 }
76671
76672
76673  $require = $this->getProperty($definition, 'requires');
76674 if ($require && !$this->getProperty($element, $require)) {
76675 $this->addError($path, 'The presence of the property ' . $i . ' requires that ' . $require . ' also be present', 'requires');
76676 }
76677
76678 $property = $this->getProperty($element, $i, $this->factory->createInstanceFor('undefined'));
76679 if (is_object($property)) {
76680 $this->validateMinMaxConstraint(!($property instanceof UndefinedConstraint) ? $property : $element, $definition, $path);
76681 }
76682 }
76683 }
76684
76685
76686
76687
76688
76689
76690
76691
76692 public function validateProperties(&$element, $properties = null, JsonPointer $path = null)
76693 {
76694 $undefinedConstraint = $this->factory->createInstanceFor('undefined');
76695
76696 foreach ($properties as $i => $value) {
76697 $property = &$this->getProperty($element, $i, $undefinedConstraint);
76698 $definition = $this->getProperty($properties, $i);
76699
76700 if (is_object($definition)) {
76701
76702  $this->checkUndefined($property, $definition, $path, $i, in_array($i, $this->appliedDefaults));
76703 }
76704 }
76705 }
76706
76707
76708
76709
76710
76711
76712
76713
76714
76715
76716 protected function &getProperty(&$element, $property, $fallback = null)
76717 {
76718 if (is_array($element) && (isset($element[$property]) || array_key_exists($property, $element)) ) {
76719 return $element[$property];
76720 } elseif (is_object($element) && property_exists($element, $property)) {
76721 return $element->$property;
76722 }
76723
76724 return $fallback;
76725 }
76726
76727
76728
76729
76730
76731
76732
76733
76734 protected function validateMinMaxConstraint($element, $objectDefinition, JsonPointer $path = null)
76735 {
76736
76737  if (isset($objectDefinition->minProperties) && !is_object($objectDefinition->minProperties)) {
76738 if ($this->getTypeCheck()->propertyCount($element) < $objectDefinition->minProperties) {
76739 $this->addError($path, 'Must contain a minimum of ' . $objectDefinition->minProperties . ' properties', 'minProperties', array('minProperties' => $objectDefinition->minProperties));
76740 }
76741 }
76742
76743  if (isset($objectDefinition->maxProperties) && !is_object($objectDefinition->maxProperties)) {
76744 if ($this->getTypeCheck()->propertyCount($element) > $objectDefinition->maxProperties) {
76745 $this->addError($path, 'Must contain no more than ' . $objectDefinition->maxProperties . ' properties', 'maxProperties', array('maxProperties' => $objectDefinition->maxProperties));
76746 }
76747 }
76748 }
76749 }
76750 <?php
76751
76752
76753
76754
76755
76756
76757
76758
76759 namespace JsonSchema\Constraints;
76760
76761 use JsonSchema\Entity\JsonPointer;
76762 use JsonSchema\Exception\InvalidArgumentException;
76763 use JsonSchema\Exception\InvalidSchemaException;
76764 use JsonSchema\Exception\RuntimeException;
76765 use JsonSchema\SchemaStorage;
76766 use JsonSchema\Validator;
76767
76768
76769
76770
76771
76772
76773
76774 class SchemaConstraint extends Constraint
76775 {
76776 const DEFAULT_SCHEMA_SPEC = 'http://json-schema.org/draft-04/schema#';
76777
76778
76779
76780
76781 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
76782 {
76783 if ($schema !== null) {
76784
76785  $validationSchema = $schema;
76786 } elseif ($this->getTypeCheck()->propertyExists($element, $this->inlineSchemaProperty)) {
76787
76788  $validationSchema = $this->getTypeCheck()->propertyGet($element, $this->inlineSchemaProperty);
76789 } else {
76790 throw new InvalidArgumentException('no schema found to verify against');
76791 }
76792
76793
76794  if (is_array($validationSchema)) {
76795 $validationSchema = BaseConstraint::arrayToObjectRecursive($validationSchema);
76796 }
76797
76798
76799  
76800  if ($this->factory->getConfig(self::CHECK_MODE_VALIDATE_SCHEMA)) {
76801 if (!$this->getTypeCheck()->isObject($validationSchema)) {
76802 throw new RuntimeException('Cannot validate the schema of a non-object');
76803 }
76804 if ($this->getTypeCheck()->propertyExists($validationSchema, '$schema')) {
76805 $schemaSpec = $this->getTypeCheck()->propertyGet($validationSchema, '$schema');
76806 } else {
76807 $schemaSpec = self::DEFAULT_SCHEMA_SPEC;
76808 }
76809
76810
76811  $schemaStorage = $this->factory->getSchemaStorage();
76812 if (!$this->getTypeCheck()->isObject($schemaSpec)) {
76813 $schemaSpec = $schemaStorage->getSchema($schemaSpec);
76814 }
76815
76816
76817  $initialErrorCount = $this->numErrors();
76818 $initialConfig = $this->factory->getConfig();
76819 $initialContext = $this->factory->getErrorContext();
76820 $this->factory->removeConfig(self::CHECK_MODE_VALIDATE_SCHEMA | self::CHECK_MODE_APPLY_DEFAULTS);
76821 $this->factory->addConfig(self::CHECK_MODE_TYPE_CAST);
76822 $this->factory->setErrorContext(Validator::ERROR_SCHEMA_VALIDATION);
76823
76824
76825  try {
76826 $this->check($validationSchema, $schemaSpec);
76827 } catch (\Exception $e) {
76828 if ($this->factory->getConfig(self::CHECK_MODE_EXCEPTIONS)) {
76829 throw new InvalidSchemaException('Schema did not pass validation', 0, $e);
76830 }
76831 }
76832 if ($this->numErrors() > $initialErrorCount) {
76833 $this->addError($path, 'Schema is not valid', 'schema');
76834 }
76835
76836
76837  $this->factory->setConfig($initialConfig);
76838 $this->factory->setErrorContext($initialContext);
76839 }
76840
76841
76842  $this->checkUndefined($element, $validationSchema, $path, $i);
76843 }
76844 }
76845 <?php
76846
76847
76848
76849
76850
76851
76852
76853
76854 namespace JsonSchema\Constraints;
76855
76856 use JsonSchema\Entity\JsonPointer;
76857
76858
76859
76860
76861
76862
76863
76864 class StringConstraint extends Constraint
76865 {
76866
76867
76868
76869 public function check(&$element, $schema = null, JsonPointer $path = null, $i = null)
76870 {
76871
76872  if (isset($schema->maxLength) && $this->strlen($element) > $schema->maxLength) {
76873 $this->addError($path, 'Must be at most ' . $schema->maxLength . ' characters long', 'maxLength', array(
76874 'maxLength' => $schema->maxLength,
76875 ));
76876 }
76877
76878
76879  if (isset($schema->minLength) && $this->strlen($element) < $schema->minLength) {
76880 $this->addError($path, 'Must be at least ' . $schema->minLength . ' characters long', 'minLength', array(
76881 'minLength' => $schema->minLength,
76882 ));
76883 }
76884
76885
76886  if (isset($schema->pattern) && !preg_match('#' . str_replace('#', '\\#', $schema->pattern) . '#u', $element)) {
76887 $this->addError($path, 'Does not match the regex pattern ' . $schema->pattern, 'pattern', array(
76888 'pattern' => $schema->pattern,
76889 ));
76890 }
76891
76892 $this->checkFormat($element, $schema, $path, $i);
76893 }
76894
76895 private function strlen($string)
76896 {
76897 if (extension_loaded('mbstring')) {
76898 return mb_strlen($string, mb_detect_encoding($string));
76899 }
76900
76901
76902  return strlen($string); 
76903  }
76904 }
76905 <?php
76906
76907 namespace JsonSchema\Constraints\TypeCheck;
76908
76909 class LooseTypeCheck implements TypeCheckInterface
76910 {
76911 public static function isObject($value)
76912 {
76913 return
76914 is_object($value) ||
76915 (is_array($value) && (count($value) == 0 || self::isAssociativeArray($value)));
76916 }
76917
76918 public static function isArray($value)
76919 {
76920 return
76921 is_array($value) &&
76922 (count($value) == 0 || !self::isAssociativeArray($value));
76923 }
76924
76925 public static function propertyGet($value, $property)
76926 {
76927 if (is_object($value)) {
76928 return $value->{$property};
76929 }
76930
76931 return $value[$property];
76932 }
76933
76934 public static function propertySet(&$value, $property, $data)
76935 {
76936 if (is_object($value)) {
76937 $value->{$property} = $data;
76938 } else {
76939 $value[$property] = $data;
76940 }
76941 }
76942
76943 public static function propertyExists($value, $property)
76944 {
76945 if (is_object($value)) {
76946 return property_exists($value, $property);
76947 }
76948
76949 return array_key_exists($property, $value);
76950 }
76951
76952 public static function propertyCount($value)
76953 {
76954 if (is_object($value)) {
76955 return count(get_object_vars($value));
76956 }
76957
76958 return count($value);
76959 }
76960
76961
76962
76963
76964
76965
76966
76967
76968 private static function isAssociativeArray($arr)
76969 {
76970 return array_keys($arr) !== range(0, count($arr) - 1);
76971 }
76972 }
76973 <?php
76974
76975 namespace JsonSchema\Constraints\TypeCheck;
76976
76977 class StrictTypeCheck implements TypeCheckInterface
76978 {
76979 public static function isObject($value)
76980 {
76981 return is_object($value);
76982 }
76983
76984 public static function isArray($value)
76985 {
76986 return is_array($value);
76987 }
76988
76989 public static function propertyGet($value, $property)
76990 {
76991 return $value->{$property};
76992 }
76993
76994 public static function propertySet(&$value, $property, $data)
76995 {
76996 $value->{$property} = $data;
76997 }
76998
76999 public static function propertyExists($value, $property)
77000 {
77001 return property_exists($value, $property);
77002 }
77003
77004 public static function propertyCount($value)
77005 {
77006 return count(get_object_vars($value));
77007 }
77008 }
77009 <?php
77010
77011 namespace JsonSchema\Constraints\TypeCheck;
77012
77013 interface TypeCheckInterface
77014 {
77015 public static function isObject($value);
77016
77017 public static function isArray($value);
77018
77019 public static function propertyGet($value, $property);
77020
77021 public static function propertySet(&$value, $property, $data);
77022
77023 public static function propertyExists($value, $property);
77024
77025 public static function propertyCount($value);
77026 }
77027 <?php
77028
77029
77030
77031
77032
77033
77034
77035
77036 namespace JsonSchema\Constraints;
77037
77038 use JsonSchema\Entity\JsonPointer;
77039 use JsonSchema\Exception\InvalidArgumentException;
77040 use UnexpectedValueException as StandardUnexpectedValueException;
77041
77042
77043
77044
77045
77046
77047
77048 class TypeConstraint extends Constraint
77049 {
77050
77051
77052
77053 public static $wording = array(
77054 'integer' => 'an integer',
77055 'number' => 'a number',
77056 'boolean' => 'a boolean',
77057 'object' => 'an object',
77058 'array' => 'an array',
77059 'string' => 'a string',
77060 'null' => 'a null',
77061 'any' => null, 
77062  0 => null, 
77063  );
77064
77065
77066
77067
77068 public function check(&$value = null, $schema = null, JsonPointer $path = null, $i = null)
77069 {
77070 $type = isset($schema->type) ? $schema->type : null;
77071 $isValid = false;
77072 $wording = array();
77073
77074 if (is_array($type)) {
77075 $this->validateTypesArray($value, $type, $wording, $isValid, $path);
77076 } elseif (is_object($type)) {
77077 $this->checkUndefined($value, $type, $path);
77078
77079 return;
77080 } else {
77081 $isValid = $this->validateType($value, $type);
77082 }
77083
77084 if ($isValid === false) {
77085 if (!is_array($type)) {
77086 $this->validateTypeNameWording($type);
77087 $wording[] = self::$wording[$type];
77088 }
77089 $this->addError($path, ucwords(gettype($value)) . ' value found, but ' .
77090 $this->implodeWith($wording, ', ', 'or') . ' is required', 'type');
77091 }
77092 }
77093
77094
77095
77096
77097
77098
77099
77100
77101
77102
77103
77104
77105 protected function validateTypesArray(&$value, array $type, &$validTypesWording, &$isValid, $path)
77106 {
77107 foreach ($type as $tp) {
77108
77109  
77110  if (is_object($tp)) {
77111 if (!$isValid) {
77112 $validator = $this->factory->createInstanceFor('type');
77113 $subSchema = new \stdClass();
77114 $subSchema->type = $tp;
77115 $validator->check($value, $subSchema, $path, null);
77116 $error = $validator->getErrors();
77117 $isValid = !(bool) $error;
77118 $validTypesWording[] = self::$wording['object'];
77119 }
77120 } else {
77121 $this->validateTypeNameWording($tp);
77122 $validTypesWording[] = self::$wording[$tp];
77123 if (!$isValid) {
77124 $isValid = $this->validateType($value, $tp);
77125 }
77126 }
77127 }
77128 }
77129
77130
77131
77132
77133
77134
77135
77136
77137
77138
77139
77140
77141 protected function implodeWith(array $elements, $delimiter = ', ', $listEnd = false)
77142 {
77143 if ($listEnd === false || !isset($elements[1])) {
77144 return implode($delimiter, $elements);
77145 }
77146 $lastElement = array_slice($elements, -1);
77147 $firsElements = join($delimiter, array_slice($elements, 0, -1));
77148 $implodedElements = array_merge(array($firsElements), $lastElement);
77149
77150 return join(" $listEnd ", $implodedElements);
77151 }
77152
77153
77154
77155
77156
77157
77158
77159
77160
77161 protected function validateTypeNameWording($type)
77162 {
77163 if (!isset(self::$wording[$type])) {
77164 throw new StandardUnexpectedValueException(
77165 sprintf(
77166 'No wording for %s available, expected wordings are: [%s]',
77167 var_export($type, true),
77168 implode(', ', array_filter(self::$wording)))
77169 );
77170 }
77171 }
77172
77173
77174
77175
77176
77177
77178
77179
77180
77181
77182
77183 protected function validateType(&$value, $type)
77184 {
77185
77186  if (!$type) {
77187 return true;
77188 }
77189
77190 if ('any' === $type) {
77191 return true;
77192 }
77193
77194 if ('object' === $type) {
77195 return $this->getTypeCheck()->isObject($value);
77196 }
77197
77198 if ('array' === $type) {
77199 return $this->getTypeCheck()->isArray($value);
77200 }
77201
77202 $coerce = $this->factory->getConfig(Constraint::CHECK_MODE_COERCE_TYPES);
77203
77204 if ('integer' === $type) {
77205 if ($coerce) {
77206 $value = $this->toInteger($value);
77207 }
77208
77209 return is_int($value);
77210 }
77211
77212 if ('number' === $type) {
77213 if ($coerce) {
77214 $value = $this->toNumber($value);
77215 }
77216
77217 return is_numeric($value) && !is_string($value);
77218 }
77219
77220 if ('boolean' === $type) {
77221 if ($coerce) {
77222 $value = $this->toBoolean($value);
77223 }
77224
77225 return is_bool($value);
77226 }
77227
77228 if ('string' === $type) {
77229 return is_string($value);
77230 }
77231
77232 if ('email' === $type) {
77233 return is_string($value);
77234 }
77235
77236 if ('null' === $type) {
77237 return is_null($value);
77238 }
77239
77240 throw new InvalidArgumentException((is_object($value) ? 'object' : $value) . ' is an invalid type for ' . $type);
77241 }
77242
77243
77244
77245
77246
77247
77248
77249
77250 protected function toBoolean($value)
77251 {
77252 if ($value === 'true') {
77253 return true;
77254 }
77255
77256 if ($value === 'false') {
77257 return false;
77258 }
77259
77260 return $value;
77261 }
77262
77263
77264
77265
77266
77267
77268
77269
77270 protected function toNumber($value)
77271 {
77272 if (is_numeric($value)) {
77273 return $value + 0; 
77274  }
77275
77276 return $value;
77277 }
77278
77279 protected function toInteger($value)
77280 {
77281 if (is_numeric($value) && (int) $value == $value) {
77282 return (int) $value; 
77283  }
77284
77285 return $value;
77286 }
77287 }
77288 <?php
77289
77290
77291
77292
77293
77294
77295
77296
77297 namespace JsonSchema\Constraints;
77298
77299 use JsonSchema\Constraints\TypeCheck\LooseTypeCheck;
77300 use JsonSchema\Entity\JsonPointer;
77301 use JsonSchema\Exception\ValidationException;
77302 use JsonSchema\Uri\UriResolver;
77303
77304
77305
77306
77307
77308
77309
77310 class UndefinedConstraint extends Constraint
77311 {
77312
77313
77314
77315 protected $appliedDefaults = array();
77316
77317
77318
77319
77320 public function check(&$value, $schema = null, JsonPointer $path = null, $i = null, $fromDefault = false)
77321 {
77322 if (is_null($schema) || !is_object($schema)) {
77323 return;
77324 }
77325
77326 $path = $this->incrementPath($path ?: new JsonPointer(''), $i);
77327 if ($fromDefault) {
77328 $path->setFromDefault();
77329 }
77330
77331
77332  $this->validateCommonProperties($value, $schema, $path, $i);
77333
77334
77335  $this->validateOfProperties($value, $schema, $path, '');
77336
77337
77338  $this->validateTypes($value, $schema, $path, $i);
77339 }
77340
77341
77342
77343
77344
77345
77346
77347
77348
77349 public function validateTypes(&$value, $schema = null, JsonPointer $path, $i = null)
77350 {
77351
77352  if ($this->getTypeCheck()->isArray($value)) {
77353 $this->checkArray($value, $schema, $path, $i);
77354 }
77355
77356
77357  if (LooseTypeCheck::isObject($value)) { 
77358  
77359  
77360  $this->checkObject(
77361 $value,
77362 $schema,
77363 $path,
77364 isset($schema->properties) ? $schema->properties : null,
77365 isset($schema->additionalProperties) ? $schema->additionalProperties : null,
77366 isset($schema->patternProperties) ? $schema->patternProperties : null,
77367 $this->appliedDefaults
77368 );
77369 }
77370
77371
77372  if (is_string($value)) {
77373 $this->checkString($value, $schema, $path, $i);
77374 }
77375
77376
77377  if (is_numeric($value)) {
77378 $this->checkNumber($value, $schema, $path, $i);
77379 }
77380
77381
77382  if (isset($schema->enum)) {
77383 $this->checkEnum($value, $schema, $path, $i);
77384 }
77385 }
77386
77387
77388
77389
77390
77391
77392
77393
77394
77395 protected function validateCommonProperties(&$value, $schema = null, JsonPointer $path, $i = '')
77396 {
77397
77398  if (isset($schema->extends)) {
77399 if (is_string($schema->extends)) {
77400 $schema->extends = $this->validateUri($schema, $schema->extends);
77401 }
77402 if (is_array($schema->extends)) {
77403 foreach ($schema->extends as $extends) {
77404 $this->checkUndefined($value, $extends, $path, $i);
77405 }
77406 } else {
77407 $this->checkUndefined($value, $schema->extends, $path, $i);
77408 }
77409 }
77410
77411
77412  if (!$path->fromDefault()) {
77413 $this->applyDefaultValues($value, $schema, $path);
77414 }
77415
77416
77417  if ($this->getTypeCheck()->isObject($value)) {
77418 if (!($value instanceof self) && isset($schema->required) && is_array($schema->required)) {
77419
77420  foreach ($schema->required as $required) {
77421 if (!$this->getTypeCheck()->propertyExists($value, $required)) {
77422 $this->addError(
77423 $this->incrementPath($path ?: new JsonPointer(''), $required),
77424 'The property ' . $required . ' is required',
77425 'required'
77426 );
77427 }
77428 }
77429 } elseif (isset($schema->required) && !is_array($schema->required)) {
77430
77431  if ($schema->required && $value instanceof self) {
77432 $this->addError($path, 'Is missing and it is required', 'required');
77433 }
77434 }
77435 }
77436
77437
77438  if (!($value instanceof self)) {
77439 $this->checkType($value, $schema, $path, $i);
77440 }
77441
77442
77443  if (isset($schema->disallow)) {
77444 $initErrors = $this->getErrors();
77445
77446 $typeSchema = new \stdClass();
77447 $typeSchema->type = $schema->disallow;
77448 $this->checkType($value, $typeSchema, $path);
77449
77450
77451  if (count($this->getErrors()) == count($initErrors)) {
77452 $this->addError($path, 'Disallowed value was matched', 'disallow');
77453 } else {
77454 $this->errors = $initErrors;
77455 }
77456 }
77457
77458 if (isset($schema->not)) {
77459 $initErrors = $this->getErrors();
77460 $this->checkUndefined($value, $schema->not, $path, $i);
77461
77462
77463  if (count($this->getErrors()) == count($initErrors)) {
77464 $this->addError($path, 'Matched a schema which it should not', 'not');
77465 } else {
77466 $this->errors = $initErrors;
77467 }
77468 }
77469
77470
77471  if (isset($schema->dependencies) && $this->getTypeCheck()->isObject($value)) {
77472 $this->validateDependencies($value, $schema->dependencies, $path);
77473 }
77474 }
77475
77476
77477
77478
77479
77480
77481
77482
77483
77484
77485 private function shouldApplyDefaultValue($requiredOnly, $schema, $name = null, $parentSchema = null)
77486 {
77487
77488  if (!$requiredOnly) {
77489 return true;
77490 }
77491
77492  if (
77493 $name !== null
77494 && isset($parentSchema->required)
77495 && is_array($parentSchema->required)
77496 && in_array($name, $parentSchema->required)
77497 ) {
77498 return true;
77499 }
77500
77501  if (isset($schema->required) && !is_array($schema->required) && $schema->required) {
77502 return true;
77503 }
77504
77505  return false;
77506 }
77507
77508
77509
77510
77511
77512
77513
77514
77515 protected function applyDefaultValues(&$value, $schema, $path)
77516 {
77517
77518  if (!$this->factory->getConfig(self::CHECK_MODE_APPLY_DEFAULTS)) {
77519 return;
77520 }
77521
77522
77523  $requiredOnly = $this->factory->getConfig(self::CHECK_MODE_ONLY_REQUIRED_DEFAULTS);
77524 if (isset($schema->properties) && LooseTypeCheck::isObject($value)) {
77525
77526  foreach ($schema->properties as $currentProperty => $propertyDefinition) {
77527 if (
77528 !LooseTypeCheck::propertyExists($value, $currentProperty)
77529 && property_exists($propertyDefinition, 'default')
77530 && $this->shouldApplyDefaultValue($requiredOnly, $propertyDefinition, $currentProperty, $schema)
77531 ) {
77532
77533  if (is_object($propertyDefinition->default)) {
77534 LooseTypeCheck::propertySet($value, $currentProperty, clone $propertyDefinition->default);
77535 } else {
77536 LooseTypeCheck::propertySet($value, $currentProperty, $propertyDefinition->default);
77537 }
77538 $this->appliedDefaults[] = $currentProperty;
77539 }
77540 }
77541 } elseif (isset($schema->items) && LooseTypeCheck::isArray($value)) {
77542 $items = array();
77543 if (LooseTypeCheck::isArray($schema->items)) {
77544 $items = $schema->items;
77545 } elseif (isset($schema->minItems) && count($value) < $schema->minItems) {
77546 $items = array_fill(count($value), $schema->minItems - count($value), $schema->items);
77547 }
77548
77549  foreach ($items as $currentItem => $itemDefinition) {
77550 if (
77551 !array_key_exists($currentItem, $value)
77552 && property_exists($itemDefinition, 'default')
77553 && $this->shouldApplyDefaultValue($requiredOnly, $itemDefinition)) {
77554 if (is_object($itemDefinition->default)) {
77555 $value[$currentItem] = clone $itemDefinition->default;
77556 } else {
77557 $value[$currentItem] = $itemDefinition->default;
77558 }
77559 }
77560 $path->setFromDefault();
77561 }
77562 } elseif (
77563 $value instanceof self
77564 && property_exists($schema, 'default')
77565 && $this->shouldApplyDefaultValue($requiredOnly, $schema)) {
77566
77567  $value = is_object($schema->default) ? clone $schema->default : $schema->default;
77568 $path->setFromDefault();
77569 }
77570 }
77571
77572
77573
77574
77575
77576
77577
77578
77579
77580 protected function validateOfProperties(&$value, $schema, JsonPointer $path, $i = '')
77581 {
77582
77583  if ($value instanceof self) {
77584 return;
77585 }
77586
77587 if (isset($schema->allOf)) {
77588 $isValid = true;
77589 foreach ($schema->allOf as $allOf) {
77590 $initErrors = $this->getErrors();
77591 $this->checkUndefined($value, $allOf, $path, $i);
77592 $isValid = $isValid && (count($this->getErrors()) == count($initErrors));
77593 }
77594 if (!$isValid) {
77595 $this->addError($path, 'Failed to match all schemas', 'allOf');
77596 }
77597 }
77598
77599 if (isset($schema->anyOf)) {
77600 $isValid = false;
77601 $startErrors = $this->getErrors();
77602 $caughtException = null;
77603 foreach ($schema->anyOf as $anyOf) {
77604 $initErrors = $this->getErrors();
77605 try {
77606 $this->checkUndefined($value, $anyOf, $path, $i);
77607 if ($isValid = (count($this->getErrors()) == count($initErrors))) {
77608 break;
77609 }
77610 } catch (ValidationException $e) {
77611 $isValid = false;
77612 }
77613 }
77614 if (!$isValid) {
77615 $this->addError($path, 'Failed to match at least one schema', 'anyOf');
77616 } else {
77617 $this->errors = $startErrors;
77618 }
77619 }
77620
77621 if (isset($schema->oneOf)) {
77622 $allErrors = array();
77623 $matchedSchemas = 0;
77624 $startErrors = $this->getErrors();
77625 foreach ($schema->oneOf as $oneOf) {
77626 try {
77627 $this->errors = array();
77628 $this->checkUndefined($value, $oneOf, $path, $i);
77629 if (count($this->getErrors()) == 0) {
77630 $matchedSchemas++;
77631 }
77632 $allErrors = array_merge($allErrors, array_values($this->getErrors()));
77633 } catch (ValidationException $e) {
77634
77635  
77636  }
77637 }
77638 if ($matchedSchemas !== 1) {
77639 $this->addErrors(array_merge($allErrors, $startErrors));
77640 $this->addError($path, 'Failed to match exactly one schema', 'oneOf');
77641 } else {
77642 $this->errors = $startErrors;
77643 }
77644 }
77645 }
77646
77647
77648
77649
77650
77651
77652
77653
77654
77655 protected function validateDependencies($value, $dependencies, JsonPointer $path, $i = '')
77656 {
77657 foreach ($dependencies as $key => $dependency) {
77658 if ($this->getTypeCheck()->propertyExists($value, $key)) {
77659 if (is_string($dependency)) {
77660
77661  if (!$this->getTypeCheck()->propertyExists($value, $dependency)) {
77662 $this->addError($path, "$key depends on $dependency and $dependency is missing", 'dependencies');
77663 }
77664 } elseif (is_array($dependency)) {
77665
77666  foreach ($dependency as $d) {
77667 if (!$this->getTypeCheck()->propertyExists($value, $d)) {
77668 $this->addError($path, "$key depends on $d and $d is missing", 'dependencies');
77669 }
77670 }
77671 } elseif (is_object($dependency)) {
77672
77673  $this->checkUndefined($value, $dependency, $path, $i);
77674 }
77675 }
77676 }
77677 }
77678
77679 protected function validateUri($schema, $schemaUri = null)
77680 {
77681 $resolver = new UriResolver();
77682 $retriever = $this->factory->getUriRetriever();
77683
77684 $jsonSchema = null;
77685 if ($resolver->isValid($schemaUri)) {
77686 $schemaId = property_exists($schema, 'id') ? $schema->id : null;
77687 $jsonSchema = $retriever->retrieve($schemaId, $schemaUri);
77688 }
77689
77690 return $jsonSchema;
77691 }
77692 }
77693 <?php
77694
77695
77696
77697
77698
77699
77700
77701
77702 namespace JsonSchema\Entity;
77703
77704 use JsonSchema\Exception\InvalidArgumentException;
77705
77706
77707
77708
77709
77710
77711 class JsonPointer
77712 {
77713
77714 private $filename;
77715
77716
77717 private $propertyPaths = array();
77718
77719
77720
77721
77722 private $fromDefault = false;
77723
77724
77725
77726
77727
77728
77729 public function __construct($value)
77730 {
77731 if (!is_string($value)) {
77732 throw new InvalidArgumentException('Ref value must be a string');
77733 }
77734
77735 $splitRef = explode('#', $value, 2);
77736 $this->filename = $splitRef[0];
77737 if (array_key_exists(1, $splitRef)) {
77738 $this->propertyPaths = $this->decodePropertyPaths($splitRef[1]);
77739 }
77740 }
77741
77742
77743
77744
77745
77746
77747 private function decodePropertyPaths($propertyPathString)
77748 {
77749 $paths = array();
77750 foreach (explode('/', trim($propertyPathString, '/')) as $path) {
77751 $path = $this->decodePath($path);
77752 if (is_string($path) && '' !== $path) {
77753 $paths[] = $path;
77754 }
77755 }
77756
77757 return $paths;
77758 }
77759
77760
77761
77762
77763 private function encodePropertyPaths()
77764 {
77765 return array_map(
77766 array($this, 'encodePath'),
77767 $this->getPropertyPaths()
77768 );
77769 }
77770
77771
77772
77773
77774
77775
77776 private function decodePath($path)
77777 {
77778 return strtr($path, array('~1' => '/', '~0' => '~', '%25' => '%'));
77779 }
77780
77781
77782
77783
77784
77785
77786 private function encodePath($path)
77787 {
77788 return strtr($path, array('/' => '~1', '~' => '~0', '%' => '%25'));
77789 }
77790
77791
77792
77793
77794 public function getFilename()
77795 {
77796 return $this->filename;
77797 }
77798
77799
77800
77801
77802 public function getPropertyPaths()
77803 {
77804 return $this->propertyPaths;
77805 }
77806
77807
77808
77809
77810
77811
77812 public function withPropertyPaths(array $propertyPaths)
77813 {
77814 $new = clone $this;
77815 $new->propertyPaths = $propertyPaths;
77816
77817 return $new;
77818 }
77819
77820
77821
77822
77823 public function getPropertyPathAsString()
77824 {
77825 return rtrim('#/' . implode('/', $this->encodePropertyPaths()), '/');
77826 }
77827
77828
77829
77830
77831 public function __toString()
77832 {
77833 return $this->getFilename() . $this->getPropertyPathAsString();
77834 }
77835
77836
77837
77838
77839 public function setFromDefault()
77840 {
77841 $this->fromDefault = true;
77842 }
77843
77844
77845
77846
77847
77848
77849 public function fromDefault()
77850 {
77851 return $this->fromDefault;
77852 }
77853 }
77854 <?php
77855
77856 namespace JsonSchema\Exception;
77857
77858 interface ExceptionInterface
77859 {
77860 }
77861 <?php
77862
77863
77864
77865
77866
77867
77868
77869
77870 namespace JsonSchema\Exception;
77871
77872
77873
77874
77875 class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
77876 {
77877 }
77878 <?php
77879
77880
77881
77882
77883
77884
77885
77886
77887 namespace JsonSchema\Exception;
77888
77889
77890
77891
77892 class InvalidConfigException extends RuntimeException
77893 {
77894 }
77895 <?php
77896
77897
77898
77899
77900
77901
77902
77903
77904 namespace JsonSchema\Exception;
77905
77906
77907
77908
77909 class InvalidSchemaException extends RuntimeException
77910 {
77911 }
77912 <?php
77913
77914
77915
77916
77917
77918
77919
77920
77921 namespace JsonSchema\Exception;
77922
77923
77924
77925
77926 class InvalidSchemaMediaTypeException extends RuntimeException
77927 {
77928 }
77929 <?php
77930
77931
77932
77933
77934
77935
77936
77937
77938 namespace JsonSchema\Exception;
77939
77940
77941
77942
77943 class InvalidSourceUriException extends InvalidArgumentException
77944 {
77945 }
77946 <?php
77947
77948
77949
77950
77951
77952
77953
77954
77955 namespace JsonSchema\Exception;
77956
77957
77958
77959
77960 class JsonDecodingException extends RuntimeException
77961 {
77962 public function __construct($code = JSON_ERROR_NONE, \Exception $previous = null)
77963 {
77964 switch ($code) {
77965 case JSON_ERROR_DEPTH:
77966 $message = 'The maximum stack depth has been exceeded';
77967 break;
77968 case JSON_ERROR_STATE_MISMATCH:
77969 $message = 'Invalid or malformed JSON';
77970 break;
77971 case JSON_ERROR_CTRL_CHAR:
77972 $message = 'Control character error, possibly incorrectly encoded';
77973 break;
77974 case JSON_ERROR_UTF8:
77975 $message = 'Malformed UTF-8 characters, possibly incorrectly encoded';
77976 break;
77977 case JSON_ERROR_SYNTAX:
77978 $message = 'JSON syntax is malformed';
77979 break;
77980 default:
77981 $message = 'Syntax error';
77982 }
77983 parent::__construct($message, $code, $previous);
77984 }
77985 }
77986 <?php
77987
77988
77989
77990
77991
77992
77993
77994
77995 namespace JsonSchema\Exception;
77996
77997
77998
77999
78000 class ResourceNotFoundException extends RuntimeException
78001 {
78002 }
78003 <?php
78004
78005
78006
78007
78008
78009
78010
78011
78012 namespace JsonSchema\Exception;
78013
78014
78015
78016
78017 class RuntimeException extends \RuntimeException implements ExceptionInterface
78018 {
78019 }
78020 <?php
78021
78022
78023
78024
78025
78026
78027
78028
78029 namespace JsonSchema\Exception;
78030
78031
78032
78033
78034
78035
78036 class UnresolvableJsonPointerException extends InvalidArgumentException
78037 {
78038 }
78039 <?php
78040
78041
78042
78043
78044
78045
78046
78047
78048 namespace JsonSchema\Exception;
78049
78050
78051
78052
78053 class UriResolverException extends RuntimeException
78054 {
78055 }
78056 <?php
78057
78058
78059
78060
78061
78062
78063
78064
78065 namespace JsonSchema\Exception;
78066
78067 class ValidationException extends RuntimeException
78068 {
78069 }
78070 <?php
78071
78072
78073
78074
78075
78076
78077
78078
78079 namespace JsonSchema\Iterator;
78080
78081
78082
78083
78084
78085
78086 class ObjectIterator implements \Iterator, \Countable
78087 {
78088
78089 private $object;
78090
78091
78092 private $position = 0;
78093
78094
78095 private $data = array();
78096
78097
78098 private $initialized = false;
78099
78100
78101
78102
78103 public function __construct($object)
78104 {
78105 $this->object = $object;
78106 }
78107
78108
78109
78110
78111 public function current()
78112 {
78113 $this->initialize();
78114
78115 return $this->data[$this->position];
78116 }
78117
78118
78119
78120
78121 public function next()
78122 {
78123 $this->initialize();
78124 $this->position++;
78125 }
78126
78127
78128
78129
78130 public function key()
78131 {
78132 $this->initialize();
78133
78134 return $this->position;
78135 }
78136
78137
78138
78139
78140 public function valid()
78141 {
78142 $this->initialize();
78143
78144 return isset($this->data[$this->position]);
78145 }
78146
78147
78148
78149
78150 public function rewind()
78151 {
78152 $this->initialize();
78153 $this->position = 0;
78154 }
78155
78156
78157
78158
78159 public function count()
78160 {
78161 $this->initialize();
78162
78163 return count($this->data);
78164 }
78165
78166
78167
78168
78169 private function initialize()
78170 {
78171 if (!$this->initialized) {
78172 $this->data = $this->buildDataFromObject($this->object);
78173 $this->initialized = true;
78174 }
78175 }
78176
78177
78178
78179
78180
78181
78182 private function buildDataFromObject($object)
78183 {
78184 $result = array();
78185
78186 $stack = new \SplStack();
78187 $stack->push($object);
78188
78189 while (!$stack->isEmpty()) {
78190 $current = $stack->pop();
78191 if (is_object($current)) {
78192 array_push($result, $current);
78193 }
78194
78195 foreach ($this->getDataFromItem($current) as $propertyName => $propertyValue) {
78196 if (is_object($propertyValue) || is_array($propertyValue)) {
78197 $stack->push($propertyValue);
78198 }
78199 }
78200 }
78201
78202 return $result;
78203 }
78204
78205
78206
78207
78208
78209
78210 private function getDataFromItem($item)
78211 {
78212 if (!is_object($item) && !is_array($item)) {
78213 return array();
78214 }
78215
78216 return is_object($item) ? get_object_vars($item) : $item;
78217 }
78218 }
78219 <?php
78220
78221 namespace JsonSchema;
78222
78223 class Rfc3339
78224 {
78225 const REGEX = '/^(\d{4}-\d{2}-\d{2}[T ]{1}\d{2}:\d{2}:\d{2})(\.\d+)?(Z|([+-]\d{2}):?(\d{2}))$/';
78226
78227
78228
78229
78230
78231
78232
78233
78234 public static function createFromString($string)
78235 {
78236 if (!preg_match(self::REGEX, strtoupper($string), $matches)) {
78237 return null;
78238 }
78239
78240 $dateAndTime = $matches[1];
78241 $microseconds = $matches[2] ?: '.000000';
78242 $timeZone = 'Z' !== $matches[3] ? $matches[4] . ':' . $matches[5] : '+00:00';
78243 $dateFormat = strpos($dateAndTime, 'T') === false ? 'Y-m-d H:i:s.uP' : 'Y-m-d\TH:i:s.uP';
78244 $dateTime = \DateTime::createFromFormat($dateFormat, $dateAndTime . $microseconds . $timeZone, new \DateTimeZone('UTC'));
78245
78246 return $dateTime ?: null;
78247 }
78248 }
78249 <?php
78250
78251 namespace JsonSchema;
78252
78253 use JsonSchema\Constraints\BaseConstraint;
78254 use JsonSchema\Entity\JsonPointer;
78255 use JsonSchema\Exception\UnresolvableJsonPointerException;
78256 use JsonSchema\Iterator\ObjectIterator;
78257 use JsonSchema\Uri\UriResolver;
78258 use JsonSchema\Uri\UriRetriever;
78259
78260 class SchemaStorage implements SchemaStorageInterface
78261 {
78262 const INTERNAL_PROVIDED_SCHEMA_URI = 'internal://provided-schema';
78263
78264 protected $uriRetriever;
78265 protected $uriResolver;
78266 protected $schemas = array();
78267
78268 public function __construct(
78269 UriRetrieverInterface $uriRetriever = null,
78270 UriResolverInterface $uriResolver = null
78271 ) {
78272 $this->uriRetriever = $uriRetriever ?: new UriRetriever();
78273 $this->uriResolver = $uriResolver ?: new UriResolver();
78274 }
78275
78276
78277
78278
78279 public function getUriRetriever()
78280 {
78281 return $this->uriRetriever;
78282 }
78283
78284
78285
78286
78287 public function getUriResolver()
78288 {
78289 return $this->uriResolver;
78290 }
78291
78292
78293
78294
78295 public function addSchema($id, $schema = null)
78296 {
78297 if (is_null($schema) && $id !== self::INTERNAL_PROVIDED_SCHEMA_URI) {
78298
78299  
78300  
78301  $schema = $this->uriRetriever->retrieve($id);
78302 }
78303
78304
78305  if (is_array($schema)) {
78306 $schema = BaseConstraint::arrayToObjectRecursive($schema);
78307 }
78308
78309
78310  
78311  if (is_object($schema) && property_exists($schema, 'id')) {
78312 if ($schema->id == 'http://json-schema.org/draft-04/schema#') {
78313 $schema->properties->id->format = 'uri-reference';
78314 } elseif ($schema->id == 'http://json-schema.org/draft-03/schema#') {
78315 $schema->properties->id->format = 'uri-reference';
78316 $schema->properties->{'$ref'}->format = 'uri-reference';
78317 }
78318 }
78319
78320 $objectIterator = new ObjectIterator($schema);
78321 foreach ($objectIterator as $toResolveSchema) {
78322 if (property_exists($toResolveSchema, '$ref') && is_string($toResolveSchema->{'$ref'})) {
78323 $jsonPointer = new JsonPointer($this->uriResolver->resolve($toResolveSchema->{'$ref'}, $id));
78324 $toResolveSchema->{'$ref'} = (string) $jsonPointer;
78325 }
78326 }
78327 $this->schemas[$id] = $schema;
78328 }
78329
78330
78331
78332
78333 public function getSchema($id)
78334 {
78335 if (!array_key_exists($id, $this->schemas)) {
78336 $this->addSchema($id);
78337 }
78338
78339 return $this->schemas[$id];
78340 }
78341
78342
78343
78344
78345 public function resolveRef($ref)
78346 {
78347 $jsonPointer = new JsonPointer($ref);
78348
78349
78350  $fileName = $jsonPointer->getFilename();
78351 if (!strlen($fileName)) {
78352 throw new UnresolvableJsonPointerException(sprintf(
78353 "Could not resolve fragment '%s': no file is defined",
78354 $jsonPointer->getPropertyPathAsString()
78355 ));
78356 }
78357
78358
78359  $refSchema = $this->getSchema($fileName);
78360 foreach ($jsonPointer->getPropertyPaths() as $path) {
78361 if (is_object($refSchema) && property_exists($refSchema, $path)) {
78362 $refSchema = $this->resolveRefSchema($refSchema->{$path});
78363 } elseif (is_array($refSchema) && array_key_exists($path, $refSchema)) {
78364 $refSchema = $this->resolveRefSchema($refSchema[$path]);
78365 } else {
78366 throw new UnresolvableJsonPointerException(sprintf(
78367 'File: %s is found, but could not resolve fragment: %s',
78368 $jsonPointer->getFilename(),
78369 $jsonPointer->getPropertyPathAsString()
78370 ));
78371 }
78372 }
78373
78374 return $refSchema;
78375 }
78376
78377
78378
78379
78380 public function resolveRefSchema($refSchema)
78381 {
78382 if (is_object($refSchema) && property_exists($refSchema, '$ref') && is_string($refSchema->{'$ref'})) {
78383 $newSchema = $this->resolveRef($refSchema->{'$ref'});
78384 $refSchema = (object) (get_object_vars($refSchema) + get_object_vars($newSchema));
78385 unset($refSchema->{'$ref'});
78386 }
78387
78388 return $refSchema;
78389 }
78390 }
78391 <?php
78392
78393 namespace JsonSchema;
78394
78395 interface SchemaStorageInterface
78396 {
78397
78398
78399
78400
78401
78402
78403 public function addSchema($id, $schema = null);
78404
78405
78406
78407
78408
78409
78410
78411
78412 public function getSchema($id);
78413
78414
78415
78416
78417
78418
78419
78420
78421 public function resolveRef($ref);
78422
78423
78424
78425
78426
78427
78428
78429
78430 public function resolveRefSchema($refSchema);
78431 }
78432 <?php
78433
78434
78435
78436
78437
78438
78439 namespace JsonSchema\Uri\Retrievers;
78440
78441
78442
78443
78444
78445
78446
78447 abstract class AbstractRetriever implements UriRetrieverInterface
78448 {
78449
78450
78451
78452
78453
78454 protected $contentType;
78455
78456
78457
78458
78459
78460
78461 public function getContentType()
78462 {
78463 return $this->contentType;
78464 }
78465 }
78466 <?php
78467
78468
78469
78470
78471
78472
78473
78474
78475 namespace JsonSchema\Uri\Retrievers;
78476
78477 use JsonSchema\Exception\RuntimeException;
78478 use JsonSchema\Validator;
78479
78480
78481
78482
78483
78484
78485 class Curl extends AbstractRetriever
78486 {
78487 protected $messageBody;
78488
78489 public function __construct()
78490 {
78491 if (!function_exists('curl_init')) {
78492
78493  throw new RuntimeException('cURL not installed'); 
78494  }
78495 }
78496
78497
78498
78499
78500
78501
78502 public function retrieve($uri)
78503 {
78504 $ch = curl_init();
78505
78506 curl_setopt($ch, CURLOPT_URL, $uri);
78507 curl_setopt($ch, CURLOPT_HEADER, true);
78508 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
78509 curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept: ' . Validator::SCHEMA_MEDIA_TYPE));
78510
78511 $response = curl_exec($ch);
78512 if (false === $response) {
78513 throw new \JsonSchema\Exception\ResourceNotFoundException('JSON schema not found');
78514 }
78515
78516 $this->fetchMessageBody($response);
78517 $this->fetchContentType($response);
78518
78519 curl_close($ch);
78520
78521 return $this->messageBody;
78522 }
78523
78524
78525
78526
78527 private function fetchMessageBody($response)
78528 {
78529 preg_match("/(?:\r\n){2}(.*)$/ms", $response, $match);
78530 $this->messageBody = $match[1];
78531 }
78532
78533
78534
78535
78536
78537
78538 protected function fetchContentType($response)
78539 {
78540 if (0 < preg_match("/Content-Type:(\V*)/ims", $response, $match)) {
78541 $this->contentType = trim($match[1]);
78542
78543 return true;
78544 }
78545
78546 return false;
78547 }
78548 }
78549 <?php
78550
78551
78552
78553
78554
78555
78556
78557
78558 namespace JsonSchema\Uri\Retrievers;
78559
78560 use JsonSchema\Exception\ResourceNotFoundException;
78561
78562
78563
78564
78565
78566
78567 class FileGetContents extends AbstractRetriever
78568 {
78569 protected $messageBody;
78570
78571
78572
78573
78574
78575
78576 public function retrieve($uri)
78577 {
78578 $errorMessage = null;
78579 set_error_handler(function ($errno, $errstr) use (&$errorMessage) {
78580 $errorMessage = $errstr;
78581 });
78582 $response = file_get_contents($uri);
78583 restore_error_handler();
78584
78585 if ($errorMessage) {
78586 throw new ResourceNotFoundException($errorMessage);
78587 }
78588
78589 if (false === $response) {
78590 throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
78591 }
78592
78593 if ($response == ''
78594 && substr($uri, 0, 7) == 'file://' && substr($uri, -1) == '/'
78595 ) {
78596 throw new ResourceNotFoundException('JSON schema not found at ' . $uri);
78597 }
78598
78599 $this->messageBody = $response;
78600 if (!empty($http_response_header)) {
78601
78602  
78603  $this->fetchContentType($http_response_header); 
78604  } else { 
78605  
78606  $this->contentType = null;
78607 }
78608
78609 return $this->messageBody;
78610 }
78611
78612
78613
78614
78615
78616
78617 private function fetchContentType(array $headers)
78618 {
78619 foreach ($headers as $header) {
78620 if ($this->contentType = self::getContentTypeMatchInHeader($header)) {
78621 return true;
78622 }
78623 }
78624
78625 return false;
78626 }
78627
78628
78629
78630
78631
78632
78633 protected static function getContentTypeMatchInHeader($header)
78634 {
78635 if (0 < preg_match("/Content-Type:(\V*)/ims", $header, $match)) {
78636 return trim($match[1]);
78637 }
78638
78639 return null;
78640 }
78641 }
78642 <?php
78643
78644 namespace JsonSchema\Uri\Retrievers;
78645
78646 use JsonSchema\Validator;
78647
78648
78649
78650
78651
78652
78653
78654
78655
78656
78657
78658
78659
78660 class PredefinedArray extends AbstractRetriever
78661 {
78662
78663
78664
78665
78666
78667 private $schemas;
78668
78669
78670
78671
78672
78673
78674
78675 public function __construct(array $schemas, $contentType = Validator::SCHEMA_MEDIA_TYPE)
78676 {
78677 $this->schemas = $schemas;
78678 $this->contentType = $contentType;
78679 }
78680
78681
78682
78683
78684
78685
78686 public function retrieve($uri)
78687 {
78688 if (!array_key_exists($uri, $this->schemas)) {
78689 throw new \JsonSchema\Exception\ResourceNotFoundException(sprintf(
78690 'The JSON schema "%s" was not found.',
78691 $uri
78692 ));
78693 }
78694
78695 return $this->schemas[$uri];
78696 }
78697 }
78698 <?php
78699
78700
78701
78702
78703
78704
78705
78706
78707 namespace JsonSchema\Uri\Retrievers;
78708
78709
78710
78711
78712
78713
78714 interface UriRetrieverInterface
78715 {
78716
78717
78718
78719
78720
78721
78722
78723
78724
78725 public function retrieve($uri);
78726
78727
78728
78729
78730
78731
78732 public function getContentType();
78733 }
78734 <?php
78735
78736
78737
78738
78739
78740
78741
78742
78743 namespace JsonSchema\Uri;
78744
78745 use JsonSchema\Exception\UriResolverException;
78746 use JsonSchema\UriResolverInterface;
78747
78748
78749
78750
78751
78752
78753 class UriResolver implements UriResolverInterface
78754 {
78755
78756
78757
78758
78759
78760
78761
78762 public function parse($uri)
78763 {
78764 preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
78765
78766 $components = array();
78767 if (5 < count($match)) {
78768 $components = array(
78769 'scheme' => $match[2],
78770 'authority' => $match[4],
78771 'path' => $match[5]
78772 );
78773 }
78774 if (7 < count($match)) {
78775 $components['query'] = $match[7];
78776 }
78777 if (9 < count($match)) {
78778 $components['fragment'] = $match[9];
78779 }
78780
78781 return $components;
78782 }
78783
78784
78785
78786
78787
78788
78789
78790
78791 public function generate(array $components)
78792 {
78793 $uri = $components['scheme'] . '://'
78794 . $components['authority']
78795 . $components['path'];
78796
78797 if (array_key_exists('query', $components)) {
78798 $uri .= $components['query'];
78799 }
78800 if (array_key_exists('fragment', $components)) {
78801 $uri .= '#' . $components['fragment'];
78802 }
78803
78804 return $uri;
78805 }
78806
78807
78808
78809
78810 public function resolve($uri, $baseUri = null)
78811 {
78812 if ($uri == '') {
78813 return $baseUri;
78814 }
78815
78816 $components = $this->parse($uri);
78817 $path = $components['path'];
78818
78819 if (!empty($components['scheme'])) {
78820 return $uri;
78821 }
78822 $baseComponents = $this->parse($baseUri);
78823 $basePath = $baseComponents['path'];
78824
78825 $baseComponents['path'] = self::combineRelativePathWithBasePath($path, $basePath);
78826 if (isset($components['fragment'])) {
78827 $baseComponents['fragment'] = $components['fragment'];
78828 }
78829
78830 return $this->generate($baseComponents);
78831 }
78832
78833
78834
78835
78836
78837
78838
78839
78840
78841
78842
78843 public static function combineRelativePathWithBasePath($relativePath, $basePath)
78844 {
78845 $relativePath = self::normalizePath($relativePath);
78846 if ($relativePath == '') {
78847 return $basePath;
78848 }
78849 if ($relativePath[0] == '/') {
78850 return $relativePath;
78851 }
78852
78853 $basePathSegments = explode('/', $basePath);
78854
78855 preg_match('|^/?(\.\./(?:\./)*)*|', $relativePath, $match);
78856 $numLevelUp = strlen($match[0]) /3 + 1;
78857 if ($numLevelUp >= count($basePathSegments)) {
78858 throw new UriResolverException(sprintf("Unable to resolve URI '%s' from base '%s'", $relativePath, $basePath));
78859 }
78860
78861 $basePathSegments = array_slice($basePathSegments, 0, -$numLevelUp);
78862 $path = preg_replace('|^/?(\.\./(\./)*)*|', '', $relativePath);
78863
78864 return implode('/', $basePathSegments) . '/' . $path;
78865 }
78866
78867
78868
78869
78870
78871
78872
78873
78874 private static function normalizePath($path)
78875 {
78876 $path = preg_replace('|((?<!\.)\./)*|', '', $path);
78877 $path = preg_replace('|//|', '/', $path);
78878
78879 return $path;
78880 }
78881
78882
78883
78884
78885
78886
78887 public function isValid($uri)
78888 {
78889 $components = $this->parse($uri);
78890
78891 return !empty($components);
78892 }
78893 }
78894 <?php
78895
78896
78897
78898
78899
78900
78901
78902
78903 namespace JsonSchema\Uri;
78904
78905 use JsonSchema\Exception\InvalidSchemaMediaTypeException;
78906 use JsonSchema\Exception\JsonDecodingException;
78907 use JsonSchema\Exception\ResourceNotFoundException;
78908 use JsonSchema\Uri\Retrievers\FileGetContents;
78909 use JsonSchema\Uri\Retrievers\UriRetrieverInterface;
78910 use JsonSchema\UriRetrieverInterface as BaseUriRetrieverInterface;
78911 use JsonSchema\Validator;
78912
78913
78914
78915
78916
78917
78918 class UriRetriever implements BaseUriRetrieverInterface
78919 {
78920
78921
78922
78923 protected $translationMap = array(
78924
78925  '|^https?://json-schema.org/draft-(0[34])/schema#?|' => 'package://dist/schema/json-schema-draft-$1.json'
78926 );
78927
78928
78929
78930
78931 protected $uriRetriever = null;
78932
78933
78934
78935
78936
78937
78938 private $schemaCache = array();
78939
78940
78941
78942
78943
78944
78945
78946
78947
78948 public function confirmMediaType($uriRetriever, $uri)
78949 {
78950 $contentType = $uriRetriever->getContentType();
78951
78952 if (is_null($contentType)) {
78953
78954  return;
78955 }
78956
78957 if (in_array($contentType, array(Validator::SCHEMA_MEDIA_TYPE, 'application/json'))) {
78958 return;
78959 }
78960
78961 if (substr($uri, 0, 23) == 'http://json-schema.org/') {
78962
78963  return true;
78964 }
78965
78966 throw new InvalidSchemaMediaTypeException(sprintf('Media type %s expected', Validator::SCHEMA_MEDIA_TYPE));
78967 }
78968
78969
78970
78971
78972
78973
78974
78975
78976
78977 public function getUriRetriever()
78978 {
78979 if (is_null($this->uriRetriever)) {
78980 $this->setUriRetriever(new FileGetContents());
78981 }
78982
78983 return $this->uriRetriever;
78984 }
78985
78986
78987
78988
78989
78990
78991
78992
78993
78994
78995
78996
78997
78998
78999
79000 public function resolvePointer($jsonSchema, $uri)
79001 {
79002 $resolver = new UriResolver();
79003 $parsed = $resolver->parse($uri);
79004 if (empty($parsed['fragment'])) {
79005 return $jsonSchema;
79006 }
79007
79008 $path = explode('/', $parsed['fragment']);
79009 while ($path) {
79010 $pathElement = array_shift($path);
79011 if (!empty($pathElement)) {
79012 $pathElement = str_replace('~1', '/', $pathElement);
79013 $pathElement = str_replace('~0', '~', $pathElement);
79014 if (!empty($jsonSchema->$pathElement)) {
79015 $jsonSchema = $jsonSchema->$pathElement;
79016 } else {
79017 throw new ResourceNotFoundException(
79018 'Fragment "' . $parsed['fragment'] . '" not found'
79019 . ' in ' . $uri
79020 );
79021 }
79022
79023 if (!is_object($jsonSchema)) {
79024 throw new ResourceNotFoundException(
79025 'Fragment part "' . $pathElement . '" is no object '
79026 . ' in ' . $uri
79027 );
79028 }
79029 }
79030 }
79031
79032 return $jsonSchema;
79033 }
79034
79035
79036
79037
79038 public function retrieve($uri, $baseUri = null, $translate = true)
79039 {
79040 $resolver = new UriResolver();
79041 $resolvedUri = $fetchUri = $resolver->resolve($uri, $baseUri);
79042
79043
79044  $arParts = $resolver->parse($resolvedUri);
79045 if (isset($arParts['fragment'])) {
79046 unset($arParts['fragment']);
79047 $fetchUri = $resolver->generate($arParts);
79048 }
79049
79050
79051  if ($translate) {
79052 $fetchUri = $this->translate($fetchUri);
79053 }
79054
79055 $jsonSchema = $this->loadSchema($fetchUri);
79056
79057
79058  $jsonSchema = $this->resolvePointer($jsonSchema, $resolvedUri);
79059
79060 if ($jsonSchema instanceof \stdClass) {
79061 $jsonSchema->id = $resolvedUri;
79062 }
79063
79064 return $jsonSchema;
79065 }
79066
79067
79068
79069
79070
79071
79072
79073
79074
79075 protected function loadSchema($fetchUri)
79076 {
79077 if (isset($this->schemaCache[$fetchUri])) {
79078 return $this->schemaCache[$fetchUri];
79079 }
79080
79081 $uriRetriever = $this->getUriRetriever();
79082 $contents = $this->uriRetriever->retrieve($fetchUri);
79083 $this->confirmMediaType($uriRetriever, $fetchUri);
79084 $jsonSchema = json_decode($contents);
79085
79086 if (JSON_ERROR_NONE < $error = json_last_error()) {
79087 throw new JsonDecodingException($error);
79088 }
79089
79090 $this->schemaCache[$fetchUri] = $jsonSchema;
79091
79092 return $jsonSchema;
79093 }
79094
79095
79096
79097
79098
79099
79100
79101
79102 public function setUriRetriever(UriRetrieverInterface $uriRetriever)
79103 {
79104 $this->uriRetriever = $uriRetriever;
79105
79106 return $this;
79107 }
79108
79109
79110
79111
79112
79113
79114
79115
79116 public function parse($uri)
79117 {
79118 preg_match('|^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?|', $uri, $match);
79119
79120 $components = array();
79121 if (5 < count($match)) {
79122 $components = array(
79123 'scheme' => $match[2],
79124 'authority' => $match[4],
79125 'path' => $match[5]
79126 );
79127 }
79128
79129 if (7 < count($match)) {
79130 $components['query'] = $match[7];
79131 }
79132
79133 if (9 < count($match)) {
79134 $components['fragment'] = $match[9];
79135 }
79136
79137 return $components;
79138 }
79139
79140
79141
79142
79143
79144
79145
79146
79147 public function generate(array $components)
79148 {
79149 $uri = $components['scheme'] . '://'
79150 . $components['authority']
79151 . $components['path'];
79152
79153 if (array_key_exists('query', $components)) {
79154 $uri .= $components['query'];
79155 }
79156
79157 if (array_key_exists('fragment', $components)) {
79158 $uri .= $components['fragment'];
79159 }
79160
79161 return $uri;
79162 }
79163
79164
79165
79166
79167
79168
79169
79170
79171
79172 public function resolve($uri, $baseUri = null)
79173 {
79174 $components = $this->parse($uri);
79175 $path = $components['path'];
79176
79177 if ((array_key_exists('scheme', $components)) && ('http' === $components['scheme'])) {
79178 return $uri;
79179 }
79180
79181 $baseComponents = $this->parse($baseUri);
79182 $basePath = $baseComponents['path'];
79183
79184 $baseComponents['path'] = UriResolver::combineRelativePathWithBasePath($path, $basePath);
79185
79186 return $this->generate($baseComponents);
79187 }
79188
79189
79190
79191
79192
79193
79194 public function isValid($uri)
79195 {
79196 $components = $this->parse($uri);
79197
79198 return !empty($components);
79199 }
79200
79201
79202
79203
79204 public function setTranslation($from, $to)
79205 {
79206 $this->translationMap[$from] = $to;
79207 }
79208
79209
79210
79211
79212 public function translate($uri)
79213 {
79214 foreach ($this->translationMap as $from => $to) {
79215 $uri = preg_replace($from, $to, $uri);
79216 }
79217
79218
79219  $uri = preg_replace('|^package://|', sprintf('file://%s/', realpath(__DIR__ . '/../../..')), $uri);
79220
79221 return $uri;
79222 }
79223 }
79224 <?php
79225
79226
79227
79228
79229
79230
79231
79232
79233 namespace JsonSchema;
79234
79235
79236
79237
79238 interface UriResolverInterface
79239 {
79240
79241
79242
79243
79244
79245
79246
79247
79248 public function resolve($uri, $baseUri = null);
79249 }
79250 <?php
79251
79252
79253
79254
79255
79256
79257
79258
79259 namespace JsonSchema;
79260
79261
79262
79263
79264 interface UriRetrieverInterface
79265 {
79266
79267
79268
79269
79270
79271
79272
79273
79274 public function retrieve($uri, $baseUri = null);
79275 }
79276 <?php
79277
79278
79279
79280
79281
79282
79283
79284
79285 namespace JsonSchema;
79286
79287 use JsonSchema\Constraints\BaseConstraint;
79288 use JsonSchema\Constraints\Constraint;
79289 use JsonSchema\Exception\InvalidConfigException;
79290 use JsonSchema\SchemaStorage;
79291
79292
79293
79294
79295
79296
79297
79298
79299
79300 class Validator extends BaseConstraint
79301 {
79302 const SCHEMA_MEDIA_TYPE = 'application/schema+json';
79303
79304 const ERROR_NONE = 0x00000000;
79305 const ERROR_ALL = 0xFFFFFFFF;
79306 const ERROR_DOCUMENT_VALIDATION = 0x00000001;
79307 const ERROR_SCHEMA_VALIDATION = 0x00000002;
79308
79309
79310
79311
79312
79313
79314
79315
79316
79317
79318 public function validate(&$value, $schema = null, $checkMode = null)
79319 {
79320
79321  if (is_array($schema)) {
79322 $schema = self::arrayToObjectRecursive($schema);
79323 }
79324
79325
79326  $initialCheckMode = $this->factory->getConfig();
79327 if ($checkMode !== null) {
79328 $this->factory->setConfig($checkMode);
79329 }
79330
79331
79332  $this->factory->getSchemaStorage()->addSchema(SchemaStorage::INTERNAL_PROVIDED_SCHEMA_URI, $schema);
79333
79334 $validator = $this->factory->createInstanceFor('schema');
79335 $validator->check(
79336 $value,
79337 $this->factory->getSchemaStorage()->getSchema(SchemaStorage::INTERNAL_PROVIDED_SCHEMA_URI)
79338 );
79339
79340 $this->factory->setConfig($initialCheckMode);
79341
79342 $this->addErrors(array_unique($validator->getErrors(), SORT_REGULAR));
79343
79344 return $validator->getErrorMask();
79345 }
79346
79347
79348
79349
79350 public function check($value, $schema)
79351 {
79352 return $this->validate($value, $schema);
79353 }
79354
79355
79356
79357
79358 public function coerce(&$value, $schema)
79359 {
79360 return $this->validate($value, $schema, Constraint::CHECK_MODE_COERCE_TYPES);
79361 }
79362 }
79363 Copyright (C) 2015 Composer
79364
79365 Permission is hereby granted, free of charge, to any person obtaining a copy of
79366 this software and associated documentation files (the "Software"), to deal in
79367 the Software without restriction, including without limitation the rights to
79368 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
79369 of the Software, and to permit persons to whom the Software is furnished to do
79370 so, subject to the following conditions:
79371
79372 The above copyright notice and this permission notice shall be included in all
79373 copies or substantial portions of the Software.
79374
79375 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
79376 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
79377 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
79378 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
79379 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
79380 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
79381 SOFTWARE.
79382 <?php
79383
79384
79385
79386
79387
79388
79389
79390
79391
79392
79393 namespace Composer\Spdx;
79394
79395 class SpdxLicenses
79396 {
79397
79398 const LICENSES_FILE = 'spdx-licenses.json';
79399
79400
79401 const EXCEPTIONS_FILE = 'spdx-exceptions.json';
79402
79403
79404
79405
79406
79407
79408
79409
79410
79411
79412
79413
79414
79415
79416 private $licenses;
79417
79418
79419
79420
79421 private $licensesExpression;
79422
79423
79424
79425
79426
79427
79428
79429
79430
79431
79432
79433
79434
79435
79436 private $exceptions;
79437
79438
79439
79440
79441 private $exceptionsExpression;
79442
79443 public function __construct()
79444 {
79445 $this->loadLicenses();
79446 $this->loadExceptions();
79447 }
79448
79449
79450
79451
79452
79453
79454
79455
79456
79457
79458
79459
79460
79461 public function getLicenseByIdentifier($identifier)
79462 {
79463 if (!isset($this->licenses[$identifier])) {
79464 return;
79465 }
79466
79467 $license = $this->licenses[$identifier];
79468 $license[] = 'https://spdx.org/licenses/' . $identifier . '.html#licenseText';
79469
79470 return $license;
79471 }
79472
79473
79474
79475
79476
79477
79478
79479
79480
79481
79482
79483
79484
79485 public function getExceptionByIdentifier($identifier)
79486 {
79487 if (!isset($this->exceptions[$identifier])) {
79488 return;
79489 }
79490
79491 $license = $this->exceptions[$identifier];
79492 $license[] = 'https://spdx.org/licenses/' . $identifier . '.html#licenseExceptionText';
79493
79494 return $license;
79495 }
79496
79497
79498
79499
79500
79501
79502
79503
79504 public function getIdentifierByName($name)
79505 {
79506 foreach ($this->licenses as $identifier => $licenseData) {
79507 if ($licenseData[0] === $name) {
79508 return $identifier;
79509 }
79510 }
79511
79512 foreach ($this->exceptions as $identifier => $licenseData) {
79513 if ($licenseData[0] === $name) {
79514 return $identifier;
79515 }
79516 }
79517 }
79518
79519
79520
79521
79522
79523
79524
79525
79526 public function isOsiApprovedByIdentifier($identifier)
79527 {
79528 return $this->licenses[$identifier][1];
79529 }
79530
79531
79532
79533
79534
79535
79536
79537
79538 public function validate($license)
79539 {
79540 if (is_array($license)) {
79541 $count = count($license);
79542 if ($count !== count(array_filter($license, 'is_string'))) {
79543 throw new \InvalidArgumentException('Array of strings expected.');
79544 }
79545 $license = $count > 1 ? '(' . implode(' OR ', $license) . ')' : (string) reset($license);
79546 }
79547
79548 if (!is_string($license)) {
79549 throw new \InvalidArgumentException(sprintf(
79550 'Array or String expected, %s given.',
79551 gettype($license)
79552 ));
79553 }
79554
79555 return $this->isValidLicenseString($license);
79556 }
79557
79558
79559
79560
79561 public static function getResourcesDir()
79562 {
79563 return dirname(__DIR__) . '/res';
79564 }
79565
79566 private function loadLicenses()
79567 {
79568 if (null === $this->licenses) {
79569 $json = file_get_contents(self::getResourcesDir() . '/' . self::LICENSES_FILE);
79570 $this->licenses = json_decode($json, true);
79571 }
79572 }
79573
79574 private function loadExceptions()
79575 {
79576 if (null === $this->exceptions) {
79577 $json = file_get_contents(self::getResourcesDir() . '/' . self::EXCEPTIONS_FILE);
79578 $this->exceptions = json_decode($json, true);
79579 }
79580 }
79581
79582
79583
79584
79585 private function getLicensesExpression()
79586 {
79587 if (null === $this->licensesExpression) {
79588 $licenses = array_map('preg_quote', array_keys($this->licenses));
79589 rsort($licenses);
79590 $licenses = implode('|', $licenses);
79591 $this->licensesExpression = $licenses;
79592 }
79593
79594 return $this->licensesExpression;
79595 }
79596
79597
79598
79599
79600 private function getExceptionsExpression()
79601 {
79602 if (null === $this->exceptionsExpression) {
79603 $exceptions = array_map('preg_quote', array_keys($this->exceptions));
79604 rsort($exceptions);
79605 $exceptions = implode('|', $exceptions);
79606 $this->exceptionsExpression = $exceptions;
79607 }
79608
79609 return $this->exceptionsExpression;
79610 }
79611
79612
79613
79614
79615
79616
79617
79618
79619 private function isValidLicenseString($license)
79620 {
79621 if (isset($this->licenses[$license])) {
79622 return true;
79623 }
79624
79625 $licenses = $this->getLicensesExpression();
79626 $exceptions = $this->getExceptionsExpression();
79627
79628 $regex = <<<REGEX
79629 {
79630 (?(DEFINE)
79631     # idstring: 1*( ALPHA / DIGIT / - / . )
79632     (?<idstring>[\pL\pN.-]{1,})
79633
79634     # license-id: taken from list
79635     (?<licenseid>${licenses})
79636
79637     # license-exception-id: taken from list
79638     (?<licenseexceptionid>${exceptions})
79639
79640     # license-ref: [DocumentRef-1*(idstring):]LicenseRef-1*(idstring)
79641     (?<licenseref>(?:DocumentRef-(?&idstring):)?LicenseRef-(?&idstring))
79642
79643     # simple-expresssion: license-id / license-id+ / license-ref
79644     (?<simple_expression>(?&licenseid)\+? | (?&licenseid) | (?&licenseref))
79645
79646     # compound-expression: 1*(
79647     #   simple-expression /
79648     #   simple-expression WITH license-exception-id /
79649     #   compound-expression AND compound-expression /
79650     #   compound-expression OR compound-expression
79651     # ) / ( compound-expression ) )
79652     (?<compound_head>
79653         (?&simple_expression) ( \s+ (?:with|WITH) \s+ (?&licenseexceptionid))?
79654             | \( \s* (?&compound_expression) \s* \)
79655     )
79656     (?<compound_expression>
79657         (?&compound_head) (?: \s+ (?:and|AND|or|OR) \s+ (?&compound_expression))?
79658     )
79659
79660     # license-expression: 1*1(simple-expression / compound-expression)
79661     (?<license_expression>(?&compound_expression) | (?&simple_expression))
79662 ) # end of define
79663
79664 ^(NONE | NOASSERTION | (?&license_expression))$
79665 }x
79666 REGEX;
79667
79668 $match = preg_match($regex, $license);
79669
79670 if (0 === $match) {
79671 return false;
79672 }
79673
79674 if (false === $match) {
79675 throw new \RuntimeException('Regex failed to compile/run.');
79676 }
79677
79678 return true;
79679 }
79680 }
79681 Copyright (C) 2015 Composer
79682
79683 Permission is hereby granted, free of charge, to any person obtaining a copy of
79684 this software and associated documentation files (the "Software"), to deal in
79685 the Software without restriction, including without limitation the rights to
79686 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
79687 of the Software, and to permit persons to whom the Software is furnished to do
79688 so, subject to the following conditions:
79689
79690 The above copyright notice and this permission notice shall be included in all
79691 copies or substantial portions of the Software.
79692
79693 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
79694 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
79695 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
79696 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
79697 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
79698 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
79699 SOFTWARE.
79700 <?php
79701
79702
79703
79704
79705
79706
79707
79708
79709
79710
79711 namespace Composer\Semver;
79712
79713 use Composer\Semver\Constraint\Constraint;
79714
79715 class Comparator
79716 {
79717
79718
79719
79720
79721
79722
79723
79724
79725 public static function greaterThan($version1, $version2)
79726 {
79727 return self::compare($version1, '>', $version2);
79728 }
79729
79730
79731
79732
79733
79734
79735
79736
79737
79738 public static function greaterThanOrEqualTo($version1, $version2)
79739 {
79740 return self::compare($version1, '>=', $version2);
79741 }
79742
79743
79744
79745
79746
79747
79748
79749
79750
79751 public static function lessThan($version1, $version2)
79752 {
79753 return self::compare($version1, '<', $version2);
79754 }
79755
79756
79757
79758
79759
79760
79761
79762
79763
79764 public static function lessThanOrEqualTo($version1, $version2)
79765 {
79766 return self::compare($version1, '<=', $version2);
79767 }
79768
79769
79770
79771
79772
79773
79774
79775
79776
79777 public static function equalTo($version1, $version2)
79778 {
79779 return self::compare($version1, '==', $version2);
79780 }
79781
79782
79783
79784
79785
79786
79787
79788
79789
79790 public static function notEqualTo($version1, $version2)
79791 {
79792 return self::compare($version1, '!=', $version2);
79793 }
79794
79795
79796
79797
79798
79799
79800
79801
79802
79803
79804 public static function compare($version1, $operator, $version2)
79805 {
79806 $constraint = new Constraint($operator, $version2);
79807
79808 return $constraint->matches(new Constraint('==', $version1));
79809 }
79810 }
79811 <?php
79812
79813
79814
79815
79816
79817
79818
79819
79820
79821
79822 namespace Composer\Semver\Constraint;
79823
79824 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);
79825
79826
79827
79828
79829 abstract class AbstractConstraint implements ConstraintInterface
79830 {
79831
79832 protected $prettyString;
79833
79834
79835
79836
79837
79838
79839 public function matches(ConstraintInterface $provider)
79840 {
79841 if ($provider instanceof $this) {
79842
79843  return $this->matchSpecific($provider);
79844 }
79845
79846
79847  return $provider->matches($this);
79848 }
79849
79850
79851
79852
79853 public function setPrettyString($prettyString)
79854 {
79855 $this->prettyString = $prettyString;
79856 }
79857
79858
79859
79860
79861 public function getPrettyString()
79862 {
79863 if ($this->prettyString) {
79864 return $this->prettyString;
79865 }
79866
79867 return $this->__toString();
79868 }
79869
79870
79871  
79872  
79873 }
79874 <?php
79875
79876
79877
79878
79879
79880
79881
79882
79883
79884
79885 namespace Composer\Semver\Constraint;
79886
79887
79888
79889
79890 class Constraint implements ConstraintInterface
79891 {
79892
79893 const OP_EQ = 0;
79894 const OP_LT = 1;
79895 const OP_LE = 2;
79896 const OP_GT = 3;
79897 const OP_GE = 4;
79898 const OP_NE = 5;
79899
79900
79901
79902
79903
79904
79905 private static $transOpStr = array(
79906 '=' => self::OP_EQ,
79907 '==' => self::OP_EQ,
79908 '<' => self::OP_LT,
79909 '<=' => self::OP_LE,
79910 '>' => self::OP_GT,
79911 '>=' => self::OP_GE,
79912 '<>' => self::OP_NE,
79913 '!=' => self::OP_NE,
79914 );
79915
79916
79917
79918
79919
79920
79921 private static $transOpInt = array(
79922 self::OP_EQ => '==',
79923 self::OP_LT => '<',
79924 self::OP_LE => '<=',
79925 self::OP_GT => '>',
79926 self::OP_GE => '>=',
79927 self::OP_NE => '!=',
79928 );
79929
79930
79931 protected $operator;
79932
79933
79934 protected $version;
79935
79936
79937 protected $prettyString;
79938
79939
79940
79941
79942
79943
79944 public function matches(ConstraintInterface $provider)
79945 {
79946 if ($provider instanceof $this) {
79947 return $this->matchSpecific($provider);
79948 }
79949
79950
79951  return $provider->matches($this);
79952 }
79953
79954
79955
79956
79957 public function setPrettyString($prettyString)
79958 {
79959 $this->prettyString = $prettyString;
79960 }
79961
79962
79963
79964
79965 public function getPrettyString()
79966 {
79967 if ($this->prettyString) {
79968 return $this->prettyString;
79969 }
79970
79971 return $this->__toString();
79972 }
79973
79974
79975
79976
79977
79978
79979 public static function getSupportedOperators()
79980 {
79981 return array_keys(self::$transOpStr);
79982 }
79983
79984
79985
79986
79987
79988
79989
79990
79991
79992 public function __construct($operator, $version)
79993 {
79994 if (!isset(self::$transOpStr[$operator])) {
79995 throw new \InvalidArgumentException(sprintf(
79996 'Invalid operator "%s" given, expected one of: %s',
79997 $operator,
79998 implode(', ', self::getSupportedOperators())
79999 ));
80000 }
80001
80002 $this->operator = self::$transOpStr[$operator];
80003 $this->version = $version;
80004 }
80005
80006
80007
80008
80009
80010
80011
80012
80013
80014
80015
80016 public function versionCompare($a, $b, $operator, $compareBranches = false)
80017 {
80018 if (!isset(self::$transOpStr[$operator])) {
80019 throw new \InvalidArgumentException(sprintf(
80020 'Invalid operator "%s" given, expected one of: %s',
80021 $operator,
80022 implode(', ', self::getSupportedOperators())
80023 ));
80024 }
80025
80026 $aIsBranch = 'dev-' === substr($a, 0, 4);
80027 $bIsBranch = 'dev-' === substr($b, 0, 4);
80028
80029 if ($aIsBranch && $bIsBranch) {
80030 return $operator === '==' && $a === $b;
80031 }
80032
80033
80034  if (!$compareBranches && ($aIsBranch || $bIsBranch)) {
80035 return false;
80036 }
80037
80038 return version_compare($a, $b, $operator);
80039 }
80040
80041
80042
80043
80044
80045
80046
80047 public function matchSpecific(Constraint $provider, $compareBranches = false)
80048 {
80049 $noEqualOp = str_replace('=', '', self::$transOpInt[$this->operator]);
80050 $providerNoEqualOp = str_replace('=', '', self::$transOpInt[$provider->operator]);
80051
80052 $isEqualOp = self::OP_EQ === $this->operator;
80053 $isNonEqualOp = self::OP_NE === $this->operator;
80054 $isProviderEqualOp = self::OP_EQ === $provider->operator;
80055 $isProviderNonEqualOp = self::OP_NE === $provider->operator;
80056
80057
80058  
80059  if ($isNonEqualOp || $isProviderNonEqualOp) {
80060 return !$isEqualOp && !$isProviderEqualOp
80061 || $this->versionCompare($provider->version, $this->version, '!=', $compareBranches);
80062 }
80063
80064
80065  
80066  if ($this->operator !== self::OP_EQ && $noEqualOp === $providerNoEqualOp) {
80067 return true;
80068 }
80069
80070 if ($this->versionCompare($provider->version, $this->version, self::$transOpInt[$this->operator], $compareBranches)) {
80071
80072  
80073  if ($provider->version === $this->version
80074 && self::$transOpInt[$provider->operator] === $providerNoEqualOp
80075 && self::$transOpInt[$this->operator] !== $noEqualOp) {
80076 return false;
80077 }
80078
80079 return true;
80080 }
80081
80082 return false;
80083 }
80084
80085
80086
80087
80088 public function __toString()
80089 {
80090 return self::$transOpInt[$this->operator] . ' ' . $this->version;
80091 }
80092 }
80093 <?php
80094
80095
80096
80097
80098
80099
80100
80101
80102
80103
80104 namespace Composer\Semver\Constraint;
80105
80106 interface ConstraintInterface
80107 {
80108
80109
80110
80111
80112
80113 public function matches(ConstraintInterface $provider);
80114
80115
80116
80117
80118 public function getPrettyString();
80119
80120
80121
80122
80123 public function __toString();
80124 }
80125 <?php
80126
80127
80128
80129
80130
80131
80132
80133
80134
80135
80136 namespace Composer\Semver\Constraint;
80137
80138
80139
80140
80141 class EmptyConstraint implements ConstraintInterface
80142 {
80143
80144 protected $prettyString;
80145
80146
80147
80148
80149
80150
80151 public function matches(ConstraintInterface $provider)
80152 {
80153 return true;
80154 }
80155
80156
80157
80158
80159 public function setPrettyString($prettyString)
80160 {
80161 $this->prettyString = $prettyString;
80162 }
80163
80164
80165
80166
80167 public function getPrettyString()
80168 {
80169 if ($this->prettyString) {
80170 return $this->prettyString;
80171 }
80172
80173 return $this->__toString();
80174 }
80175
80176
80177
80178
80179 public function __toString()
80180 {
80181 return '[]';
80182 }
80183 }
80184 <?php
80185
80186
80187
80188
80189
80190
80191
80192
80193
80194
80195 namespace Composer\Semver\Constraint;
80196
80197
80198
80199
80200 class MultiConstraint implements ConstraintInterface
80201 {
80202
80203 protected $constraints;
80204
80205
80206 protected $prettyString;
80207
80208
80209 protected $conjunctive;
80210
80211
80212
80213
80214
80215 public function __construct(array $constraints, $conjunctive = true)
80216 {
80217 $this->constraints = $constraints;
80218 $this->conjunctive = $conjunctive;
80219 }
80220
80221
80222
80223
80224 public function getConstraints()
80225 {
80226 return $this->constraints;
80227 }
80228
80229
80230
80231
80232 public function isConjunctive()
80233 {
80234 return $this->conjunctive;
80235 }
80236
80237
80238
80239
80240 public function isDisjunctive()
80241 {
80242 return !$this->conjunctive;
80243 }
80244
80245
80246
80247
80248
80249
80250 public function matches(ConstraintInterface $provider)
80251 {
80252 if (false === $this->conjunctive) {
80253 foreach ($this->constraints as $constraint) {
80254 if ($constraint->matches($provider)) {
80255 return true;
80256 }
80257 }
80258
80259 return false;
80260 }
80261
80262 foreach ($this->constraints as $constraint) {
80263 if (!$constraint->matches($provider)) {
80264 return false;
80265 }
80266 }
80267
80268 return true;
80269 }
80270
80271
80272
80273
80274 public function setPrettyString($prettyString)
80275 {
80276 $this->prettyString = $prettyString;
80277 }
80278
80279
80280
80281
80282 public function getPrettyString()
80283 {
80284 if ($this->prettyString) {
80285 return $this->prettyString;
80286 }
80287
80288 return $this->__toString();
80289 }
80290
80291
80292
80293
80294 public function __toString()
80295 {
80296 $constraints = array();
80297 foreach ($this->constraints as $constraint) {
80298 $constraints[] = (string) $constraint;
80299 }
80300
80301 return '[' . implode($this->conjunctive ? ' ' : ' || ', $constraints) . ']';
80302 }
80303 }
80304 <?php
80305
80306
80307
80308
80309
80310
80311
80312
80313
80314
80315 namespace Composer\Semver;
80316
80317 use Composer\Semver\Constraint\Constraint;
80318
80319 class Semver
80320 {
80321 const SORT_ASC = 1;
80322 const SORT_DESC = -1;
80323
80324
80325 private static $versionParser;
80326
80327
80328
80329
80330
80331
80332
80333
80334
80335 public static function satisfies($version, $constraints)
80336 {
80337 if (null === self::$versionParser) {
80338 self::$versionParser = new VersionParser();
80339 }
80340
80341 $versionParser = self::$versionParser;
80342 $provider = new Constraint('==', $versionParser->normalize($version));
80343 $constraints = $versionParser->parseConstraints($constraints);
80344
80345 return $constraints->matches($provider);
80346 }
80347
80348
80349
80350
80351
80352
80353
80354
80355
80356 public static function satisfiedBy(array $versions, $constraints)
80357 {
80358 $versions = array_filter($versions, function ($version) use ($constraints) {
80359 return Semver::satisfies($version, $constraints);
80360 });
80361
80362 return array_values($versions);
80363 }
80364
80365
80366
80367
80368
80369
80370
80371
80372 public static function sort(array $versions)
80373 {
80374 return self::usort($versions, self::SORT_ASC);
80375 }
80376
80377
80378
80379
80380
80381
80382
80383
80384 public static function rsort(array $versions)
80385 {
80386 return self::usort($versions, self::SORT_DESC);
80387 }
80388
80389
80390
80391
80392
80393
80394
80395 private static function usort(array $versions, $direction)
80396 {
80397 if (null === self::$versionParser) {
80398 self::$versionParser = new VersionParser();
80399 }
80400
80401 $versionParser = self::$versionParser;
80402 $normalized = array();
80403
80404
80405  
80406  foreach ($versions as $key => $version) {
80407 $normalized[] = array($versionParser->normalize($version), $key);
80408 }
80409
80410 usort($normalized, function (array $left, array $right) use ($direction) {
80411 if ($left[0] === $right[0]) {
80412 return 0;
80413 }
80414
80415 if (Comparator::lessThan($left[0], $right[0])) {
80416 return -$direction;
80417 }
80418
80419 return $direction;
80420 });
80421
80422
80423  $sorted = array();
80424 foreach ($normalized as $item) {
80425 $sorted[] = $versions[$item[1]];
80426 }
80427
80428 return $sorted;
80429 }
80430 }
80431 <?php
80432
80433
80434
80435
80436
80437
80438
80439
80440
80441
80442 namespace Composer\Semver;
80443
80444 use Composer\Semver\Constraint\ConstraintInterface;
80445 use Composer\Semver\Constraint\EmptyConstraint;
80446 use Composer\Semver\Constraint\MultiConstraint;
80447 use Composer\Semver\Constraint\Constraint;
80448
80449
80450
80451
80452
80453
80454 class VersionParser
80455 {
80456
80457
80458
80459
80460
80461
80462
80463
80464
80465
80466
80467
80468
80469 private static $modifierRegex = '[._-]?(?:(stable|beta|b|RC|alpha|a|patch|pl|p)((?:[.-]?\d+)*+)?)?([.-]?dev)?';
80470
80471
80472 private static $stabilities = array('stable', 'RC', 'beta', 'alpha', 'dev');
80473
80474
80475
80476
80477
80478
80479
80480
80481 public static function parseStability($version)
80482 {
80483 $version = preg_replace('{#.+$}i', '', $version);
80484
80485 if ('dev-' === substr($version, 0, 4) || '-dev' === substr($version, -4)) {
80486 return 'dev';
80487 }
80488
80489 preg_match('{' . self::$modifierRegex . '(?:\+.*)?$}i', strtolower($version), $match);
80490 if (!empty($match[3])) {
80491 return 'dev';
80492 }
80493
80494 if (!empty($match[1])) {
80495 if ('beta' === $match[1] || 'b' === $match[1]) {
80496 return 'beta';
80497 }
80498 if ('alpha' === $match[1] || 'a' === $match[1]) {
80499 return 'alpha';
80500 }
80501 if ('rc' === $match[1]) {
80502 return 'RC';
80503 }
80504 }
80505
80506 return 'stable';
80507 }
80508
80509
80510
80511
80512
80513
80514 public static function normalizeStability($stability)
80515 {
80516 $stability = strtolower($stability);
80517
80518 return $stability === 'rc' ? 'RC' : $stability;
80519 }
80520
80521
80522
80523
80524
80525
80526
80527
80528
80529
80530
80531 public function normalize($version, $fullVersion = null)
80532 {
80533 $version = trim($version);
80534 if (null === $fullVersion) {
80535 $fullVersion = $version;
80536 }
80537
80538
80539  if (preg_match('{^([^,\s]++) ++as ++([^,\s]++)$}', $version, $match)) {
80540 $version = $match[1];
80541 }
80542
80543
80544  if (preg_match('{^(?:dev-)?(?:master|trunk|default)$}i', $version)) {
80545 return '9999999-dev';
80546 }
80547
80548
80549  if ('dev-' === strtolower(substr($version, 0, 4))) {
80550 return 'dev-' . substr($version, 4);
80551 }
80552
80553
80554  if (preg_match('{^([^,\s+]++)\+[^\s]++$}', $version, $match)) {
80555 $version = $match[1];
80556 }
80557
80558
80559  if (preg_match('{^v?(\d{1,5})(\.\d++)?(\.\d++)?(\.\d++)?' . self::$modifierRegex . '$}i', $version, $matches)) {
80560 $version = $matches[1]
80561 . (!empty($matches[2]) ? $matches[2] : '.0')
80562 . (!empty($matches[3]) ? $matches[3] : '.0')
80563 . (!empty($matches[4]) ? $matches[4] : '.0');
80564 $index = 5;
80565
80566  } elseif (preg_match('{^v?(\d{4}(?:[.:-]?\d{2}){1,6}(?:[.:-]?\d{1,3})?)' . self::$modifierRegex . '$}i', $version, $matches)) {
80567 $version = preg_replace('{\D}', '.', $matches[1]);
80568 $index = 2;
80569 }
80570
80571
80572  if (isset($index)) {
80573 if (!empty($matches[$index])) {
80574 if ('stable' === $matches[$index]) {
80575 return $version;
80576 }
80577 $version .= '-' . $this->expandStability($matches[$index]) . (!empty($matches[$index + 1]) ? ltrim($matches[$index + 1], '.-') : '');
80578 }
80579
80580 if (!empty($matches[$index + 2])) {
80581 $version .= '-dev';
80582 }
80583
80584 return $version;
80585 }
80586
80587
80588  if (preg_match('{(.*?)[.-]?dev$}i', $version, $match)) {
80589 try {
80590 return $this->normalizeBranch($match[1]);
80591 } catch (\Exception $e) {
80592 }
80593 }
80594
80595 $extraMessage = '';
80596 if (preg_match('{ +as +' . preg_quote($version) . '$}', $fullVersion)) {
80597 $extraMessage = ' in "' . $fullVersion . '", the alias must be an exact version';
80598 } elseif (preg_match('{^' . preg_quote($version) . ' +as +}', $fullVersion)) {
80599 $extraMessage = ' in "' . $fullVersion . '", the alias source must be an exact version, if it is a branch name you should prefix it with dev-';
80600 }
80601
80602 throw new \UnexpectedValueException('Invalid version string "' . $version . '"' . $extraMessage);
80603 }
80604
80605
80606
80607
80608
80609
80610
80611
80612 public function parseNumericAliasPrefix($branch)
80613 {
80614 if (preg_match('{^(?P<version>(\d++\\.)*\d++)(?:\.x)?-dev$}i', $branch, $matches)) {
80615 return $matches['version'] . '.';
80616 }
80617
80618 return false;
80619 }
80620
80621
80622
80623
80624
80625
80626
80627
80628 public function normalizeBranch($name)
80629 {
80630 $name = trim($name);
80631
80632 if (in_array($name, array('master', 'trunk', 'default'))) {
80633 return $this->normalize($name);
80634 }
80635
80636 if (preg_match('{^v?(\d++)(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?(\.(?:\d++|[xX*]))?$}i', $name, $matches)) {
80637 $version = '';
80638 for ($i = 1; $i < 5; ++$i) {
80639 $version .= isset($matches[$i]) ? str_replace(array('*', 'X'), 'x', $matches[$i]) : '.x';
80640 }
80641
80642 return str_replace('x', '9999999', $version) . '-dev';
80643 }
80644
80645 return 'dev-' . $name;
80646 }
80647
80648
80649
80650
80651
80652
80653
80654
80655 public function parseConstraints($constraints)
80656 {
80657 $prettyConstraint = $constraints;
80658
80659 if (preg_match('{^([^,\s]*?)@(' . implode('|', self::$stabilities) . ')$}i', $constraints, $match)) {
80660 $constraints = empty($match[1]) ? '*' : $match[1];
80661 }
80662
80663 if (preg_match('{^(dev-[^,\s@]+?|[^,\s@]+?\.x-dev)#.+$}i', $constraints, $match)) {
80664 $constraints = $match[1];
80665 }
80666
80667 $orConstraints = preg_split('{\s*\|\|?\s*}', trim($constraints));
80668 $orGroups = array();
80669 foreach ($orConstraints as $constraints) {
80670 $andConstraints = preg_split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $constraints);
80671 if (count($andConstraints) > 1) {
80672 $constraintObjects = array();
80673 foreach ($andConstraints as $constraint) {
80674 foreach ($this->parseConstraint($constraint) as $parsedConstraint) {
80675 $constraintObjects[] = $parsedConstraint;
80676 }
80677 }
80678 } else {
80679 $constraintObjects = $this->parseConstraint($andConstraints[0]);
80680 }
80681
80682 if (1 === count($constraintObjects)) {
80683 $constraint = $constraintObjects[0];
80684 } else {
80685 $constraint = new MultiConstraint($constraintObjects);
80686 }
80687
80688 $orGroups[] = $constraint;
80689 }
80690
80691 if (1 === count($orGroups)) {
80692 $constraint = $orGroups[0];
80693 } elseif (2 === count($orGroups)
80694
80695  
80696  && $orGroups[0] instanceof MultiConstraint
80697 && $orGroups[1] instanceof MultiConstraint
80698 && 2 === count($orGroups[0]->getConstraints())
80699 && 2 === count($orGroups[1]->getConstraints())
80700 && ($a = (string) $orGroups[0])
80701 && substr($a, 0, 3) === '[>=' && (false !== ($posA = strpos($a, '<', 4)))
80702 && ($b = (string) $orGroups[1])
80703 && substr($b, 0, 3) === '[>=' && (false !== ($posB = strpos($b, '<', 4)))
80704 && substr($a, $posA + 2, -1) === substr($b, 4, $posB - 5)
80705 ) {
80706 $constraint = new MultiConstraint(array(
80707 new Constraint('>=', substr($a, 4, $posA - 5)),
80708 new Constraint('<', substr($b, $posB + 2, -1)),
80709 ));
80710 } else {
80711 $constraint = new MultiConstraint($orGroups, false);
80712 }
80713
80714 $constraint->setPrettyString($prettyConstraint);
80715
80716 return $constraint;
80717 }
80718
80719
80720
80721
80722
80723
80724
80725
80726 private function parseConstraint($constraint)
80727 {
80728 if (preg_match('{^([^,\s]+?)@(' . implode('|', self::$stabilities) . ')$}i', $constraint, $match)) {
80729 $constraint = $match[1];
80730 if ($match[2] !== 'stable') {
80731 $stabilityModifier = $match[2];
80732 }
80733 }
80734
80735 if (preg_match('{^v?[xX*](\.[xX*])*$}i', $constraint)) {
80736 return array(new EmptyConstraint());
80737 }
80738
80739 $versionRegex = 'v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.(\d++))?' . self::$modifierRegex . '(?:\+[^\s]+)?';
80740
80741
80742  
80743  
80744  
80745  
80746  if (preg_match('{^~>?' . $versionRegex . '$}i', $constraint, $matches)) {
80747 if (substr($constraint, 0, 2) === '~>') {
80748 throw new \UnexpectedValueException(
80749 'Could not parse version constraint ' . $constraint . ': ' .
80750 'Invalid operator "~>", you probably meant to use the "~" operator'
80751 );
80752 }
80753
80754
80755  if (isset($matches[4]) && '' !== $matches[4]) {
80756 $position = 4;
80757 } elseif (isset($matches[3]) && '' !== $matches[3]) {
80758 $position = 3;
80759 } elseif (isset($matches[2]) && '' !== $matches[2]) {
80760 $position = 2;
80761 } else {
80762 $position = 1;
80763 }
80764
80765
80766  $stabilitySuffix = '';
80767 if (!empty($matches[5])) {
80768 $stabilitySuffix .= '-' . $this->expandStability($matches[5]) . (!empty($matches[6]) ? $matches[6] : '');
80769 }
80770
80771 if (!empty($matches[7])) {
80772 $stabilitySuffix .= '-dev';
80773 }
80774
80775 if (!$stabilitySuffix) {
80776 $stabilitySuffix = '-dev';
80777 }
80778
80779 $lowVersion = $this->manipulateVersionString($matches, $position, 0) . $stabilitySuffix;
80780 $lowerBound = new Constraint('>=', $lowVersion);
80781
80782
80783  
80784  $highPosition = max(1, $position - 1);
80785 $highVersion = $this->manipulateVersionString($matches, $highPosition, 1) . '-dev';
80786 $upperBound = new Constraint('<', $highVersion);
80787
80788 return array(
80789 $lowerBound,
80790 $upperBound,
80791 );
80792 }
80793
80794
80795  
80796  
80797  
80798  
80799  if (preg_match('{^\^' . $versionRegex . '($)}i', $constraint, $matches)) {
80800
80801  if ('0' !== $matches[1] || '' === $matches[2]) {
80802 $position = 1;
80803 } elseif ('0' !== $matches[2] || '' === $matches[3]) {
80804 $position = 2;
80805 } else {
80806 $position = 3;
80807 }
80808
80809
80810  $stabilitySuffix = '';
80811 if (empty($matches[5]) && empty($matches[7])) {
80812 $stabilitySuffix .= '-dev';
80813 }
80814
80815 $lowVersion = $this->normalize(substr($constraint . $stabilitySuffix, 1));
80816 $lowerBound = new Constraint('>=', $lowVersion);
80817
80818
80819  
80820  $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
80821 $upperBound = new Constraint('<', $highVersion);
80822
80823 return array(
80824 $lowerBound,
80825 $upperBound,
80826 );
80827 }
80828
80829
80830  
80831  
80832  
80833  if (preg_match('{^v?(\d++)(?:\.(\d++))?(?:\.(\d++))?(?:\.[xX*])++$}', $constraint, $matches)) {
80834 if (isset($matches[3]) && '' !== $matches[3]) {
80835 $position = 3;
80836 } elseif (isset($matches[2]) && '' !== $matches[2]) {
80837 $position = 2;
80838 } else {
80839 $position = 1;
80840 }
80841
80842 $lowVersion = $this->manipulateVersionString($matches, $position) . '-dev';
80843 $highVersion = $this->manipulateVersionString($matches, $position, 1) . '-dev';
80844
80845 if ($lowVersion === '0.0.0.0-dev') {
80846 return array(new Constraint('<', $highVersion));
80847 }
80848
80849 return array(
80850 new Constraint('>=', $lowVersion),
80851 new Constraint('<', $highVersion),
80852 );
80853 }
80854
80855
80856  
80857  
80858  
80859  
80860  
80861  if (preg_match('{^(?P<from>' . $versionRegex . ') +- +(?P<to>' . $versionRegex . ')($)}i', $constraint, $matches)) {
80862
80863  $lowStabilitySuffix = '';
80864 if (empty($matches[6]) && empty($matches[8])) {
80865 $lowStabilitySuffix = '-dev';
80866 }
80867
80868 $lowVersion = $this->normalize($matches['from']);
80869 $lowerBound = new Constraint('>=', $lowVersion . $lowStabilitySuffix);
80870
80871 $empty = function ($x) {
80872 return ($x === 0 || $x === '0') ? false : empty($x);
80873 };
80874
80875 if ((!$empty($matches[11]) && !$empty($matches[12])) || !empty($matches[14]) || !empty($matches[16])) {
80876 $highVersion = $this->normalize($matches['to']);
80877 $upperBound = new Constraint('<=', $highVersion);
80878 } else {
80879 $highMatch = array('', $matches[10], $matches[11], $matches[12], $matches[13]);
80880 $highVersion = $this->manipulateVersionString($highMatch, $empty($matches[11]) ? 1 : 2, 1) . '-dev';
80881 $upperBound = new Constraint('<', $highVersion);
80882 }
80883
80884 return array(
80885 $lowerBound,
80886 $upperBound,
80887 );
80888 }
80889
80890
80891  if (preg_match('{^(<>|!=|>=?|<=?|==?)?\s*(.*)}', $constraint, $matches)) {
80892 try {
80893 $version = $this->normalize($matches[2]);
80894
80895 if (!empty($stabilityModifier) && $this->parseStability($version) === 'stable') {
80896 $version .= '-' . $stabilityModifier;
80897 } elseif ('<' === $matches[1] || '>=' === $matches[1]) {
80898 if (!preg_match('/-' . self::$modifierRegex . '$/', strtolower($matches[2]))) {
80899 if (substr($matches[2], 0, 4) !== 'dev-') {
80900 $version .= '-dev';
80901 }
80902 }
80903 }
80904
80905 return array(new Constraint($matches[1] ?: '=', $version));
80906 } catch (\Exception $e) {
80907 }
80908 }
80909
80910 $message = 'Could not parse version constraint ' . $constraint;
80911 if (isset($e)) {
80912 $message .= ': ' . $e->getMessage();
80913 }
80914
80915 throw new \UnexpectedValueException($message);
80916 }
80917
80918
80919
80920
80921
80922
80923
80924
80925
80926
80927
80928
80929
80930 private function manipulateVersionString($matches, $position, $increment = 0, $pad = '0')
80931 {
80932 for ($i = 4; $i > 0; --$i) {
80933 if ($i > $position) {
80934 $matches[$i] = $pad;
80935 } elseif ($i === $position && $increment) {
80936 $matches[$i] += $increment;
80937
80938  if ($matches[$i] < 0) {
80939 $matches[$i] = $pad;
80940 --$position;
80941
80942
80943  if ($i === 1) {
80944 return;
80945 }
80946 }
80947 }
80948 }
80949
80950 return $matches[1] . '.' . $matches[2] . '.' . $matches[3] . '.' . $matches[4];
80951 }
80952
80953
80954
80955
80956
80957
80958
80959
80960 private function expandStability($stability)
80961 {
80962 $stability = strtolower($stability);
80963
80964 switch ($stability) {
80965 case 'a':
80966 return 'alpha';
80967 case 'b':
80968 return 'beta';
80969 case 'p':
80970 case 'pl':
80971 return 'patch';
80972 case 'rc':
80973 return 'RC';
80974 default:
80975 return $stability;
80976 }
80977 }
80978 }
80979 Copyright (C) 2016 Composer
80980
80981 Permission is hereby granted, free of charge, to any person obtaining a copy of
80982 this software and associated documentation files (the "Software"), to deal in
80983 the Software without restriction, including without limitation the rights to
80984 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
80985 of the Software, and to permit persons to whom the Software is furnished to do
80986 so, subject to the following conditions:
80987
80988 The above copyright notice and this permission notice shall be included in all
80989 copies or substantial portions of the Software.
80990
80991 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
80992 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
80993 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
80994 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
80995 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
80996 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
80997 SOFTWARE.
80998 <?php
80999
81000
81001
81002
81003
81004
81005
81006
81007
81008
81009 namespace Composer\CaBundle;
81010
81011 use Psr\Log\LoggerInterface;
81012 use Symfony\Component\Process\PhpProcess;
81013
81014
81015
81016
81017
81018 class CaBundle
81019 {
81020 private static $caPath;
81021 private static $caFileValidity = array();
81022 private static $useOpensslParse;
81023
81024
81025
81026
81027
81028
81029
81030
81031
81032
81033
81034
81035
81036
81037
81038
81039
81040
81041
81042
81043
81044
81045
81046
81047
81048
81049
81050
81051
81052
81053
81054
81055
81056
81057
81058
81059
81060
81061 public static function getSystemCaRootBundlePath(LoggerInterface $logger = null)
81062 {
81063 if (self::$caPath !== null) {
81064 return self::$caPath;
81065 }
81066
81067
81068  
81069  $envCertFile = getenv('SSL_CERT_FILE');
81070 if ($envCertFile && is_readable($envCertFile) && static::validateCaFile($envCertFile, $logger)) {
81071 return self::$caPath = $envCertFile;
81072 }
81073
81074
81075  
81076  $envCertDir = getenv('SSL_CERT_DIR');
81077 if ($envCertDir && is_dir($envCertDir) && is_readable($envCertDir)) {
81078 return self::$caPath = $envCertDir;
81079 }
81080
81081 $configured = ini_get('openssl.cafile');
81082 if ($configured && strlen($configured) > 0 && is_readable($configured) && static::validateCaFile($configured, $logger)) {
81083 return self::$caPath = $configured;
81084 }
81085
81086 $configured = ini_get('openssl.capath');
81087 if ($configured && is_dir($configured) && is_readable($configured)) {
81088 return self::$caPath = $configured;
81089 }
81090
81091 $caBundlePaths = array(
81092 '/etc/pki/tls/certs/ca-bundle.crt', 
81093  '/etc/ssl/certs/ca-certificates.crt', 
81094  '/etc/ssl/ca-bundle.pem', 
81095  '/usr/local/share/certs/ca-root-nss.crt', 
81096  '/usr/ssl/certs/ca-bundle.crt', 
81097  '/opt/local/share/curl/curl-ca-bundle.crt', 
81098  '/usr/local/share/curl/curl-ca-bundle.crt', 
81099  '/usr/share/ssl/certs/ca-bundle.crt', 
81100  '/etc/ssl/cert.pem', 
81101  '/usr/local/etc/ssl/cert.pem', 
81102  '/usr/local/etc/openssl/cert.pem', 
81103  );
81104
81105 foreach ($caBundlePaths as $caBundle) {
81106 if (@is_readable($caBundle) && static::validateCaFile($caBundle, $logger)) {
81107 return self::$caPath = $caBundle;
81108 }
81109 }
81110
81111 foreach ($caBundlePaths as $caBundle) {
81112 $caBundle = dirname($caBundle);
81113 if (@is_dir($caBundle) && glob($caBundle.'/*')) {
81114 return self::$caPath = $caBundle;
81115 }
81116 }
81117
81118 return self::$caPath = static::getBundledCaBundlePath(); 
81119  }
81120
81121
81122
81123
81124
81125
81126
81127
81128 public static function getBundledCaBundlePath()
81129 {
81130 return __DIR__.'/../res/cacert.pem';
81131 }
81132
81133
81134
81135
81136
81137
81138
81139
81140
81141 public static function validateCaFile($filename, LoggerInterface $logger = null)
81142 {
81143 static $warned = false;
81144
81145 if (isset(self::$caFileValidity[$filename])) {
81146 return self::$caFileValidity[$filename];
81147 }
81148
81149 $contents = file_get_contents($filename);
81150
81151
81152  
81153  if (!static::isOpensslParseSafe()) {
81154 if (!$warned && $logger) {
81155 $logger->warning(sprintf(
81156 'Your version of PHP, %s, is affected by CVE-2013-6420 and cannot safely perform certificate validation, we strongly suggest you upgrade.',
81157 PHP_VERSION
81158 ));
81159 $warned = true;
81160 }
81161
81162 $isValid = !empty($contents);
81163 } else {
81164 $isValid = (bool) openssl_x509_parse($contents);
81165 }
81166
81167 if ($logger) {
81168 $logger->debug('Checked CA file '.realpath($filename).': '.($isValid ? 'valid' : 'invalid'));
81169 }
81170
81171 return self::$caFileValidity[$filename] = $isValid;
81172 }
81173
81174
81175
81176
81177
81178
81179
81180
81181
81182 public static function isOpensslParseSafe()
81183 {
81184 if (null !== self::$useOpensslParse) {
81185 return self::$useOpensslParse;
81186 }
81187
81188 if (PHP_VERSION_ID >= 50600) {
81189 return self::$useOpensslParse = true;
81190 }
81191
81192
81193  
81194  
81195  
81196  if (
81197 (PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50328)
81198 || (PHP_VERSION_ID < 50500 && PHP_VERSION_ID >= 50423)
81199 || (PHP_VERSION_ID < 50600 && PHP_VERSION_ID >= 50507)
81200 ) {
81201
81202  return self::$useOpensslParse = true;
81203 }
81204
81205 if (defined('PHP_WINDOWS_VERSION_BUILD')) {
81206
81207  return self::$useOpensslParse = false;
81208 }
81209
81210 $compareDistroVersionPrefix = function ($prefix, $fixedVersion) {
81211 $regex = '{^'.preg_quote($prefix).'([0-9]+)$}';
81212
81213 if (preg_match($regex, PHP_VERSION, $m)) {
81214 return ((int) $m[1]) >= $fixedVersion;
81215 }
81216
81217 return false;
81218 };
81219
81220
81221  if (
81222 $compareDistroVersionPrefix('5.3.3-7+squeeze', 18) 
81223  || $compareDistroVersionPrefix('5.4.4-14+deb7u', 7) 
81224  || $compareDistroVersionPrefix('5.3.10-1ubuntu3.', 9) 
81225  ) {
81226 return self::$useOpensslParse = true;
81227 }
81228
81229
81230  if (!class_exists('Symfony\Component\Process\PhpProcess')) {
81231 return self::$useOpensslParse = false;
81232 }
81233
81234
81235  
81236  
81237  
81238  
81239  
81240
81241
81242  
81243  $cert = 'LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVwRENDQTR5Z0F3SUJBZ0lKQUp6dThyNnU2ZUJjTUEwR0NTcUdTSWIzRFFFQkJRVUFNSUhETVFzd0NRWUQKVlFRR0V3SkVSVEVjTUJvR0ExVUVDQXdUVG05eVpISm9aV2x1TFZkbGMzUm1ZV3hsYmpFUU1BNEdBMVVFQnd3SApTOE9Ed3Jac2JqRVVNQklHQTFVRUNnd0xVMlZyZEdsdmJrVnBibk14SHpBZEJnTlZCQXNNRmsxaGJHbGphVzkxCmN5QkRaWEowSUZObFkzUnBiMjR4SVRBZkJnTlZCQU1NR0cxaGJHbGphVzkxY3k1elpXdDBhVzl1WldsdWN5NWsKWlRFcU1DZ0dDU3FHU0liM0RRRUpBUlliYzNSbFptRnVMbVZ6YzJWeVFITmxhM1JwYjI1bGFXNXpMbVJsTUhVWQpaREU1TnpBd01UQXhNREF3TURBd1dnQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBCkFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUEKQUFBQUFBQVhEVEUwTVRFeU9ERXhNemt6TlZvd2djTXhDekFKQmdOVkJBWVRBa1JGTVJ3d0dnWURWUVFJREJOTwpiM0prY21obGFXNHRWMlZ6ZEdaaGJHVnVNUkF3RGdZRFZRUUhEQWRMdzRQQ3RteHVNUlF3RWdZRFZRUUtEQXRUClpXdDBhVzl1UldsdWN6RWZNQjBHQTFVRUN3d1dUV0ZzYVdOcGIzVnpJRU5sY25RZ1UyVmpkR2x2YmpFaE1COEcKQTFVRUF3d1liV0ZzYVdOcGIzVnpMbk5sYTNScGIyNWxhVzV6TG1SbE1Tb3dLQVlKS29aSWh2Y05BUWtCRmh0egpkR1ZtWVc0dVpYTnpaWEpBYzJWcmRHbHZibVZwYm5NdVpHVXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCCkR3QXdnZ0VLQW9JQkFRRERBZjNobDdKWTBYY0ZuaXlFSnBTU0RxbjBPcUJyNlFQNjV1c0pQUnQvOFBhRG9xQnUKd0VZVC9OYSs2ZnNnUGpDMHVLOURaZ1dnMnRIV1dvYW5TYmxBTW96NVBINlorUzRTSFJaN2UyZERJalBqZGhqaAowbUxnMlVNTzV5cDBWNzk3R2dzOWxOdDZKUmZIODFNTjJvYlhXczROdHp0TE11RDZlZ3FwcjhkRGJyMzRhT3M4CnBrZHVpNVVhd1Raa3N5NXBMUEhxNWNNaEZHbTA2djY1Q0xvMFYyUGQ5K0tBb2tQclBjTjVLTEtlYno3bUxwazYKU01lRVhPS1A0aWRFcXh5UTdPN2ZCdUhNZWRzUWh1K3ByWTNzaTNCVXlLZlF0UDVDWm5YMmJwMHdLSHhYMTJEWAoxbmZGSXQ5RGJHdkhUY3lPdU4rblpMUEJtM3ZXeG50eUlJdlZBZ01CQUFHalFqQkFNQWtHQTFVZEV3UUNNQUF3CkVRWUpZSVpJQVliNFFnRUJCQVFEQWdlQU1Bc0dBMVVkRHdRRUF3SUZvREFUQmdOVkhTVUVEREFLQmdnckJnRUYKQlFjREFqQU5CZ2txaGtpRzl3MEJBUVVGQUFPQ0FRRUFHMGZaWVlDVGJkajFYWWMrMVNub2FQUit2SThDOENhRAo4KzBVWWhkbnlVNGdnYTBCQWNEclk5ZTk0ZUVBdTZacXljRjZGakxxWFhkQWJvcHBXb2NyNlQ2R0QxeDMzQ2tsClZBcnpHL0t4UW9oR0QySmVxa2hJTWxEb214SE83a2EzOStPYThpMnZXTFZ5alU4QVp2V01BcnVIYTRFRU55RzcKbFcyQWFnYUZLRkNyOVRuWFRmcmR4R1ZFYnY3S1ZRNmJkaGc1cDVTanBXSDErTXEwM3VSM1pYUEJZZHlWODMxOQpvMGxWajFLRkkyRENML2xpV2lzSlJvb2YrMWNSMzVDdGQwd1lCY3BCNlRac2xNY09QbDc2ZHdLd0pnZUpvMlFnClpzZm1jMnZDMS9xT2xOdU5xLzBUenprVkd2OEVUVDNDZ2FVK1VYZTRYT1Z2a2NjZWJKbjJkZz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K';
81244 $script = <<<'EOT'
81245
81246 error_reporting(-1);
81247 $info = openssl_x509_parse(base64_decode('%s'));
81248 var_dump(PHP_VERSION, $info['issuer']['emailAddress'], $info['validFrom_time_t']);
81249
81250 EOT;
81251 $script = '<'."?php\n".sprintf($script, $cert);
81252
81253 try {
81254 $process = new PhpProcess($script);
81255 $process->mustRun();
81256 } catch (\Exception $e) {
81257
81258  
81259  return self::$useOpensslParse = false;
81260 }
81261
81262 $output = preg_split('{\r?\n}', trim($process->getOutput()));
81263 $errorOutput = trim($process->getErrorOutput());
81264
81265 if (
81266 count($output) === 3
81267 && $output[0] === sprintf('string(%d) "%s"', strlen(PHP_VERSION), PHP_VERSION)
81268 && $output[1] === 'string(27) "stefan.esser@sektioneins.de"'
81269 && $output[2] === 'int(-1)'
81270 && preg_match('{openssl_x509_parse\(\): illegal (?:ASN1 data type for|length in) timestamp in - on line \d+}', $errorOutput)
81271 ) {
81272
81273  return self::$useOpensslParse = true;
81274 }
81275
81276 return self::$useOpensslParse = false;
81277 }
81278
81279
81280
81281
81282 public static function reset()
81283 {
81284 self::$caFileValidity = array();
81285 self::$caPath = null;
81286 self::$useOpensslParse = null;
81287 }
81288 }
81289 Copyright (c) 2012 PHP Framework Interoperability Group
81290
81291 Permission is hereby granted, free of charge, to any person obtaining a copy 
81292 of this software and associated documentation files (the "Software"), to deal
81293 in the Software without restriction, including without limitation the rights 
81294 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
81295 copies of the Software, and to permit persons to whom the Software is 
81296 furnished to do so, subject to the following conditions:
81297
81298 The above copyright notice and this permission notice shall be included in 
81299 all copies or substantial portions of the Software.
81300
81301 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
81302 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
81303 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
81304 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
81305 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
81306 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
81307 THE SOFTWARE.
81308 <?php
81309
81310 namespace Psr\Log;
81311
81312
81313
81314
81315
81316
81317
81318
81319 abstract class AbstractLogger implements LoggerInterface
81320 {
81321
81322
81323
81324
81325
81326
81327
81328
81329 public function emergency($message, array $context = array())
81330 {
81331 $this->log(LogLevel::EMERGENCY, $message, $context);
81332 }
81333
81334
81335
81336
81337
81338
81339
81340
81341
81342
81343
81344
81345 public function alert($message, array $context = array())
81346 {
81347 $this->log(LogLevel::ALERT, $message, $context);
81348 }
81349
81350
81351
81352
81353
81354
81355
81356
81357
81358
81359
81360 public function critical($message, array $context = array())
81361 {
81362 $this->log(LogLevel::CRITICAL, $message, $context);
81363 }
81364
81365
81366
81367
81368
81369
81370
81371
81372
81373
81374 public function error($message, array $context = array())
81375 {
81376 $this->log(LogLevel::ERROR, $message, $context);
81377 }
81378
81379
81380
81381
81382
81383
81384
81385
81386
81387
81388
81389
81390 public function warning($message, array $context = array())
81391 {
81392 $this->log(LogLevel::WARNING, $message, $context);
81393 }
81394
81395
81396
81397
81398
81399
81400
81401
81402
81403 public function notice($message, array $context = array())
81404 {
81405 $this->log(LogLevel::NOTICE, $message, $context);
81406 }
81407
81408
81409
81410
81411
81412
81413
81414
81415
81416
81417
81418 public function info($message, array $context = array())
81419 {
81420 $this->log(LogLevel::INFO, $message, $context);
81421 }
81422
81423
81424
81425
81426
81427
81428
81429
81430
81431 public function debug($message, array $context = array())
81432 {
81433 $this->log(LogLevel::DEBUG, $message, $context);
81434 }
81435 }
81436 <?php
81437
81438 namespace Psr\Log;
81439
81440 class InvalidArgumentException extends \InvalidArgumentException
81441 {
81442 }
81443 <?php
81444
81445 namespace Psr\Log;
81446
81447
81448
81449
81450 class LogLevel
81451 {
81452 const EMERGENCY = 'emergency';
81453 const ALERT = 'alert';
81454 const CRITICAL = 'critical';
81455 const ERROR = 'error';
81456 const WARNING = 'warning';
81457 const NOTICE = 'notice';
81458 const INFO = 'info';
81459 const DEBUG = 'debug';
81460 }
81461 <?php
81462
81463 namespace Psr\Log;
81464
81465
81466
81467
81468 interface LoggerAwareInterface
81469 {
81470
81471
81472
81473
81474
81475
81476
81477 public function setLogger(LoggerInterface $logger);
81478 }
81479 <?php
81480
81481 namespace Psr\Log;
81482
81483
81484
81485
81486 trait LoggerAwareTrait
81487 {
81488
81489
81490
81491
81492
81493 protected $logger;
81494
81495
81496
81497
81498
81499
81500 public function setLogger(LoggerInterface $logger)
81501 {
81502 $this->logger = $logger;
81503 }
81504 }
81505 <?php
81506
81507 namespace Psr\Log;
81508
81509
81510
81511
81512
81513
81514
81515
81516
81517
81518
81519
81520
81521
81522
81523
81524 interface LoggerInterface
81525 {
81526
81527
81528
81529
81530
81531
81532
81533
81534 public function emergency($message, array $context = array());
81535
81536
81537
81538
81539
81540
81541
81542
81543
81544
81545
81546
81547 public function alert($message, array $context = array());
81548
81549
81550
81551
81552
81553
81554
81555
81556
81557
81558
81559 public function critical($message, array $context = array());
81560
81561
81562
81563
81564
81565
81566
81567
81568
81569
81570 public function error($message, array $context = array());
81571
81572
81573
81574
81575
81576
81577
81578
81579
81580
81581
81582
81583 public function warning($message, array $context = array());
81584
81585
81586
81587
81588
81589
81590
81591
81592
81593 public function notice($message, array $context = array());
81594
81595
81596
81597
81598
81599
81600
81601
81602
81603
81604
81605 public function info($message, array $context = array());
81606
81607
81608
81609
81610
81611
81612
81613
81614
81615 public function debug($message, array $context = array());
81616
81617
81618
81619
81620
81621
81622
81623
81624
81625
81626 public function log($level, $message, array $context = array());
81627 }
81628 <?php
81629
81630 namespace Psr\Log;
81631
81632
81633
81634
81635
81636
81637
81638
81639
81640 trait LoggerTrait
81641 {
81642
81643
81644
81645
81646
81647
81648
81649
81650 public function emergency($message, array $context = array())
81651 {
81652 $this->log(LogLevel::EMERGENCY, $message, $context);
81653 }
81654
81655
81656
81657
81658
81659
81660
81661
81662
81663
81664
81665
81666 public function alert($message, array $context = array())
81667 {
81668 $this->log(LogLevel::ALERT, $message, $context);
81669 }
81670
81671
81672
81673
81674
81675
81676
81677
81678
81679
81680
81681 public function critical($message, array $context = array())
81682 {
81683 $this->log(LogLevel::CRITICAL, $message, $context);
81684 }
81685
81686
81687
81688
81689
81690
81691
81692
81693
81694
81695 public function error($message, array $context = array())
81696 {
81697 $this->log(LogLevel::ERROR, $message, $context);
81698 }
81699
81700
81701
81702
81703
81704
81705
81706
81707
81708
81709
81710
81711 public function warning($message, array $context = array())
81712 {
81713 $this->log(LogLevel::WARNING, $message, $context);
81714 }
81715
81716
81717
81718
81719
81720
81721
81722
81723
81724 public function notice($message, array $context = array())
81725 {
81726 $this->log(LogLevel::NOTICE, $message, $context);
81727 }
81728
81729
81730
81731
81732
81733
81734
81735
81736
81737
81738
81739 public function info($message, array $context = array())
81740 {
81741 $this->log(LogLevel::INFO, $message, $context);
81742 }
81743
81744
81745
81746
81747
81748
81749
81750
81751
81752 public function debug($message, array $context = array())
81753 {
81754 $this->log(LogLevel::DEBUG, $message, $context);
81755 }
81756
81757
81758
81759
81760
81761
81762
81763
81764
81765
81766 abstract public function log($level, $message, array $context = array());
81767 }
81768 <?php
81769
81770 namespace Psr\Log;
81771
81772
81773
81774
81775
81776
81777
81778
81779
81780 class NullLogger extends AbstractLogger
81781 {
81782
81783
81784
81785
81786
81787
81788
81789
81790
81791 public function log($level, $message, array $context = array())
81792 {
81793
81794  }
81795 }
81796 <?php
81797
81798 namespace Psr\Log\Test;
81799
81800 use Psr\Log\LoggerInterface;
81801 use Psr\Log\LogLevel;
81802
81803
81804
81805
81806
81807
81808
81809 abstract class LoggerInterfaceTest extends \PHPUnit_Framework_TestCase
81810 {
81811
81812
81813
81814 abstract public function getLogger();
81815
81816
81817
81818
81819
81820
81821
81822
81823
81824
81825 abstract public function getLogs();
81826
81827 public function testImplements()
81828 {
81829 $this->assertInstanceOf('Psr\Log\LoggerInterface', $this->getLogger());
81830 }
81831
81832
81833
81834
81835 public function testLogsAtAllLevels($level, $message)
81836 {
81837 $logger = $this->getLogger();
81838 $logger->{$level}($message, array('user' => 'Bob'));
81839 $logger->log($level, $message, array('user' => 'Bob'));
81840
81841 $expected = array(
81842 $level.' message of level '.$level.' with context: Bob',
81843 $level.' message of level '.$level.' with context: Bob',
81844 );
81845 $this->assertEquals($expected, $this->getLogs());
81846 }
81847
81848 public function provideLevelsAndMessages()
81849 {
81850 return array(
81851 LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'),
81852 LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'),
81853 LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'),
81854 LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'),
81855 LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'),
81856 LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'),
81857 LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'),
81858 LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'),
81859 );
81860 }
81861
81862
81863
81864
81865 public function testThrowsOnInvalidLevel()
81866 {
81867 $logger = $this->getLogger();
81868 $logger->log('invalid level', 'Foo');
81869 }
81870
81871 public function testContextReplacement()
81872 {
81873 $logger = $this->getLogger();
81874 $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));
81875
81876 $expected = array('info {Message {nothing} Bob Bar a}');
81877 $this->assertEquals($expected, $this->getLogs());
81878 }
81879
81880 public function testObjectCastToString()
81881 {
81882 if (method_exists($this, 'createPartialMock')) {
81883 $dummy = $this->createPartialMock('Psr\Log\Test\DummyTest', array('__toString'));
81884 } else {
81885 $dummy = $this->getMock('Psr\Log\Test\DummyTest', array('__toString'));
81886 }
81887 $dummy->expects($this->once())
81888 ->method('__toString')
81889 ->will($this->returnValue('DUMMY'));
81890
81891 $this->getLogger()->warning($dummy);
81892
81893 $expected = array('warning DUMMY');
81894 $this->assertEquals($expected, $this->getLogs());
81895 }
81896
81897 public function testContextCanContainAnything()
81898 {
81899 $context = array(
81900 'bool' => true,
81901 'null' => null,
81902 'string' => 'Foo',
81903 'int' => 0,
81904 'float' => 0.5,
81905 'nested' => array('with object' => new DummyTest),
81906 'object' => new \DateTime,
81907 'resource' => fopen('php://memory', 'r'),
81908 );
81909
81910 $this->getLogger()->warning('Crazy context data', $context);
81911
81912 $expected = array('warning Crazy context data');
81913 $this->assertEquals($expected, $this->getLogs());
81914 }
81915
81916 public function testContextExceptionKeyCanBeExceptionOrOtherValues()
81917 {
81918 $logger = $this->getLogger();
81919 $logger->warning('Random message', array('exception' => 'oops'));
81920 $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail')));
81921
81922 $expected = array(
81923 'warning Random message',
81924 'critical Uncaught Exception!'
81925 );
81926 $this->assertEquals($expected, $this->getLogs());
81927 }
81928 }
81929
81930 class DummyTest
81931 {
81932 public function __toString()
81933 {
81934 }
81935 }
81936 <?php
81937
81938
81939
81940 require_once __DIR__ . '/composer/autoload_real.php';
81941
81942 return ComposerAutoloaderInitComposerPhar1505141966::getLoader();
81943 <?php
81944
81945
81946
81947 $vendorDir = dirname(dirname(__FILE__));
81948 $baseDir = dirname($vendorDir);
81949
81950 return array(
81951 );
81952 <?php
81953
81954
81955
81956 $vendorDir = dirname(dirname(__FILE__));
81957 $baseDir = dirname($vendorDir);
81958
81959 return array(
81960 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
81961 'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'),
81962 'Symfony\\Component\\Finder\\' => array($vendorDir . '/symfony/finder'),
81963 'Symfony\\Component\\Filesystem\\' => array($vendorDir . '/symfony/filesystem'),
81964 'Symfony\\Component\\Debug\\' => array($vendorDir . '/symfony/debug'),
81965 'Symfony\\Component\\Console\\' => array($vendorDir . '/symfony/console'),
81966 'Seld\\PharUtils\\' => array($vendorDir . '/seld/phar-utils/src'),
81967 'Seld\\JsonLint\\' => array($vendorDir . '/seld/jsonlint/src/Seld/JsonLint'),
81968 'Seld\\CliPrompt\\' => array($vendorDir . '/seld/cli-prompt/src'),
81969 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
81970 'JsonSchema\\' => array($vendorDir . '/justinrainbow/json-schema/src/JsonSchema'),
81971 'Composer\\Spdx\\' => array($vendorDir . '/composer/spdx-licenses/src'),
81972 'Composer\\Semver\\' => array($vendorDir . '/composer/semver/src'),
81973 'Composer\\CaBundle\\' => array($vendorDir . '/composer/ca-bundle/src'),
81974 'Composer\\' => array($baseDir . '/src/Composer'),
81975 );
81976 <?php
81977
81978
81979
81980 $vendorDir = dirname(dirname(__FILE__));
81981 $baseDir = dirname($vendorDir);
81982
81983 return array(
81984 );
81985 <?php
81986
81987
81988
81989 $vendorDir = dirname(dirname(__FILE__));
81990 $baseDir = dirname($vendorDir);
81991
81992 return array(
81993 '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
81994 );
81995 <?php
81996
81997
81998
81999 class ComposerAutoloaderInitComposerPhar1505141966
82000 {
82001 private static $loader;
82002
82003 public static function loadClassLoader($class)
82004 {
82005 if ('Composer\Autoload\ClassLoader' === $class) {
82006 require __DIR__ . '/ClassLoader.php';
82007 }
82008 }
82009
82010 public static function getLoader()
82011 {
82012 if (null !== self::$loader) {
82013 return self::$loader;
82014 }
82015
82016 spl_autoload_register(array('ComposerAutoloaderInitComposerPhar1505141966', 'loadClassLoader'), true, true);
82017 self::$loader = $loader = new \Composer\Autoload\ClassLoader();
82018 spl_autoload_unregister(array('ComposerAutoloaderInitComposerPhar1505141966', 'loadClassLoader'));
82019
82020 $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
82021 if ($useStaticLoader) {
82022 require_once __DIR__ . '/autoload_static.php';
82023
82024 call_user_func(\Composer\Autoload\ComposerStaticInitComposerPhar1505141966::getInitializer($loader));
82025 } else {
82026 $map = require __DIR__ . '/autoload_namespaces.php';
82027 foreach ($map as $namespace => $path) {
82028 $loader->set($namespace, $path);
82029 }
82030
82031 $map = require __DIR__ . '/autoload_psr4.php';
82032 foreach ($map as $namespace => $path) {
82033 $loader->setPsr4($namespace, $path);
82034 }
82035
82036 $classMap = require __DIR__ . '/autoload_classmap.php';
82037 if ($classMap) {
82038 $loader->addClassMap($classMap);
82039 }
82040 }
82041
82042 $loader->register(true);
82043
82044 if ($useStaticLoader) {
82045 $includeFiles = Composer\Autoload\ComposerStaticInitComposerPhar1505141966::$files;
82046 } else {
82047 $includeFiles = require __DIR__ . '/autoload_files.php';
82048 }
82049 foreach ($includeFiles as $fileIdentifier => $file) {
82050 composerRequireComposerPhar1505141966($fileIdentifier, $file);
82051 }
82052
82053 return $loader;
82054 }
82055 }
82056
82057 function composerRequireComposerPhar1505141966($fileIdentifier, $file)
82058 {
82059 if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
82060 require $file;
82061
82062 $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
82063 }
82064 }
82065 <?php
82066
82067
82068
82069 namespace Composer\Autoload;
82070
82071 class ComposerStaticInitComposerPhar1505141966
82072 {
82073 public static $files = array (
82074 '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
82075 );
82076
82077 public static $prefixLengthsPsr4 = array (
82078 'S' => 
82079 array (
82080 'Symfony\\Polyfill\\Mbstring\\' => 26,
82081 'Symfony\\Component\\Process\\' => 26,
82082 'Symfony\\Component\\Finder\\' => 25,
82083 'Symfony\\Component\\Filesystem\\' => 29,
82084 'Symfony\\Component\\Debug\\' => 24,
82085 'Symfony\\Component\\Console\\' => 26,
82086 'Seld\\PharUtils\\' => 15,
82087 'Seld\\JsonLint\\' => 14,
82088 'Seld\\CliPrompt\\' => 15,
82089 ),
82090 'P' => 
82091 array (
82092 'Psr\\Log\\' => 8,
82093 ),
82094 'J' => 
82095 array (
82096 'JsonSchema\\' => 11,
82097 ),
82098 'C' => 
82099 array (
82100 'Composer\\Spdx\\' => 14,
82101 'Composer\\Semver\\' => 16,
82102 'Composer\\CaBundle\\' => 18,
82103 'Composer\\' => 9,
82104 ),
82105 );
82106
82107 public static $prefixDirsPsr4 = array (
82108 'Symfony\\Polyfill\\Mbstring\\' => 
82109 array (
82110 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
82111 ),
82112 'Symfony\\Component\\Process\\' => 
82113 array (
82114 0 => __DIR__ . '/..' . '/symfony/process',
82115 ),
82116 'Symfony\\Component\\Finder\\' => 
82117 array (
82118 0 => __DIR__ . '/..' . '/symfony/finder',
82119 ),
82120 'Symfony\\Component\\Filesystem\\' => 
82121 array (
82122 0 => __DIR__ . '/..' . '/symfony/filesystem',
82123 ),
82124 'Symfony\\Component\\Debug\\' => 
82125 array (
82126 0 => __DIR__ . '/..' . '/symfony/debug',
82127 ),
82128 'Symfony\\Component\\Console\\' => 
82129 array (
82130 0 => __DIR__ . '/..' . '/symfony/console',
82131 ),
82132 'Seld\\PharUtils\\' => 
82133 array (
82134 0 => __DIR__ . '/..' . '/seld/phar-utils/src',
82135 ),
82136 'Seld\\JsonLint\\' => 
82137 array (
82138 0 => __DIR__ . '/..' . '/seld/jsonlint/src/Seld/JsonLint',
82139 ),
82140 'Seld\\CliPrompt\\' => 
82141 array (
82142 0 => __DIR__ . '/..' . '/seld/cli-prompt/src',
82143 ),
82144 'Psr\\Log\\' => 
82145 array (
82146 0 => __DIR__ . '/..' . '/psr/log/Psr/Log',
82147 ),
82148 'JsonSchema\\' => 
82149 array (
82150 0 => __DIR__ . '/..' . '/justinrainbow/json-schema/src/JsonSchema',
82151 ),
82152 'Composer\\Spdx\\' => 
82153 array (
82154 0 => __DIR__ . '/..' . '/composer/spdx-licenses/src',
82155 ),
82156 'Composer\\Semver\\' => 
82157 array (
82158 0 => __DIR__ . '/..' . '/composer/semver/src',
82159 ),
82160 'Composer\\CaBundle\\' => 
82161 array (
82162 0 => __DIR__ . '/..' . '/composer/ca-bundle/src',
82163 ),
82164 'Composer\\' => 
82165 array (
82166 0 => __DIR__ . '/../..' . '/src/Composer',
82167 ),
82168 );
82169
82170 public static function getInitializer(ClassLoader $loader)
82171 {
82172 return \Closure::bind(function () use ($loader) {
82173 $loader->prefixLengthsPsr4 = ComposerStaticInitComposerPhar1505141966::$prefixLengthsPsr4;
82174 $loader->prefixDirsPsr4 = ComposerStaticInitComposerPhar1505141966::$prefixDirsPsr4;
82175
82176 }, null, ClassLoader::class);
82177 }
82178 }
82179 <?php
82180
82181
82182
82183
82184
82185
82186
82187
82188
82189
82190
82191 namespace Composer\Autoload;
82192
82193
82194
82195
82196
82197
82198
82199
82200
82201
82202
82203
82204
82205
82206
82207
82208
82209
82210
82211
82212
82213
82214
82215
82216
82217
82218
82219
82220
82221 class ClassLoader
82222 {
82223
82224  private $prefixLengthsPsr4 = array();
82225 private $prefixDirsPsr4 = array();
82226 private $fallbackDirsPsr4 = array();
82227
82228
82229  private $prefixesPsr0 = array();
82230 private $fallbackDirsPsr0 = array();
82231
82232 private $useIncludePath = false;
82233 private $classMap = array();
82234 private $classMapAuthoritative = false;
82235 private $missingClasses = array();
82236 private $apcuPrefix;
82237
82238 public function getPrefixes()
82239 {
82240 if (!empty($this->prefixesPsr0)) {
82241 return call_user_func_array('array_merge', $this->prefixesPsr0);
82242 }
82243
82244 return array();
82245 }
82246
82247 public function getPrefixesPsr4()
82248 {
82249 return $this->prefixDirsPsr4;
82250 }
82251
82252 public function getFallbackDirs()
82253 {
82254 return $this->fallbackDirsPsr0;
82255 }
82256
82257 public function getFallbackDirsPsr4()
82258 {
82259 return $this->fallbackDirsPsr4;
82260 }
82261
82262 public function getClassMap()
82263 {
82264 return $this->classMap;
82265 }
82266
82267
82268
82269
82270 public function addClassMap(array $classMap)
82271 {
82272 if ($this->classMap) {
82273 $this->classMap = array_merge($this->classMap, $classMap);
82274 } else {
82275 $this->classMap = $classMap;
82276 }
82277 }
82278
82279
82280
82281
82282
82283
82284
82285
82286
82287 public function add($prefix, $paths, $prepend = false)
82288 {
82289 if (!$prefix) {
82290 if ($prepend) {
82291 $this->fallbackDirsPsr0 = array_merge(
82292 (array) $paths,
82293 $this->fallbackDirsPsr0
82294 );
82295 } else {
82296 $this->fallbackDirsPsr0 = array_merge(
82297 $this->fallbackDirsPsr0,
82298 (array) $paths
82299 );
82300 }
82301
82302 return;
82303 }
82304
82305 $first = $prefix[0];
82306 if (!isset($this->prefixesPsr0[$first][$prefix])) {
82307 $this->prefixesPsr0[$first][$prefix] = (array) $paths;
82308
82309 return;
82310 }
82311 if ($prepend) {
82312 $this->prefixesPsr0[$first][$prefix] = array_merge(
82313 (array) $paths,
82314 $this->prefixesPsr0[$first][$prefix]
82315 );
82316 } else {
82317 $this->prefixesPsr0[$first][$prefix] = array_merge(
82318 $this->prefixesPsr0[$first][$prefix],
82319 (array) $paths
82320 );
82321 }
82322 }
82323
82324
82325
82326
82327
82328
82329
82330
82331
82332
82333
82334 public function addPsr4($prefix, $paths, $prepend = false)
82335 {
82336 if (!$prefix) {
82337
82338  if ($prepend) {
82339 $this->fallbackDirsPsr4 = array_merge(
82340 (array) $paths,
82341 $this->fallbackDirsPsr4
82342 );
82343 } else {
82344 $this->fallbackDirsPsr4 = array_merge(
82345 $this->fallbackDirsPsr4,
82346 (array) $paths
82347 );
82348 }
82349 } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
82350
82351  $length = strlen($prefix);
82352 if ('\\' !== $prefix[$length - 1]) {
82353 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
82354 }
82355 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
82356 $this->prefixDirsPsr4[$prefix] = (array) $paths;
82357 } elseif ($prepend) {
82358
82359  $this->prefixDirsPsr4[$prefix] = array_merge(
82360 (array) $paths,
82361 $this->prefixDirsPsr4[$prefix]
82362 );
82363 } else {
82364
82365  $this->prefixDirsPsr4[$prefix] = array_merge(
82366 $this->prefixDirsPsr4[$prefix],
82367 (array) $paths
82368 );
82369 }
82370 }
82371
82372
82373
82374
82375
82376
82377
82378
82379 public function set($prefix, $paths)
82380 {
82381 if (!$prefix) {
82382 $this->fallbackDirsPsr0 = (array) $paths;
82383 } else {
82384 $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
82385 }
82386 }
82387
82388
82389
82390
82391
82392
82393
82394
82395
82396
82397 public function setPsr4($prefix, $paths)
82398 {
82399 if (!$prefix) {
82400 $this->fallbackDirsPsr4 = (array) $paths;
82401 } else {
82402 $length = strlen($prefix);
82403 if ('\\' !== $prefix[$length - 1]) {
82404 throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
82405 }
82406 $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
82407 $this->prefixDirsPsr4[$prefix] = (array) $paths;
82408 }
82409 }
82410
82411
82412
82413
82414
82415
82416 public function setUseIncludePath($useIncludePath)
82417 {
82418 $this->useIncludePath = $useIncludePath;
82419 }
82420
82421
82422
82423
82424
82425
82426
82427 public function getUseIncludePath()
82428 {
82429 return $this->useIncludePath;
82430 }
82431
82432
82433
82434
82435
82436
82437
82438 public function setClassMapAuthoritative($classMapAuthoritative)
82439 {
82440 $this->classMapAuthoritative = $classMapAuthoritative;
82441 }
82442
82443
82444
82445
82446
82447
82448 public function isClassMapAuthoritative()
82449 {
82450 return $this->classMapAuthoritative;
82451 }
82452
82453
82454
82455
82456
82457
82458 public function setApcuPrefix($apcuPrefix)
82459 {
82460 $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
82461 }
82462
82463
82464
82465
82466
82467
82468 public function getApcuPrefix()
82469 {
82470 return $this->apcuPrefix;
82471 }
82472
82473
82474
82475
82476
82477
82478 public function register($prepend = false)
82479 {
82480 spl_autoload_register(array($this, 'loadClass'), true, $prepend);
82481 }
82482
82483
82484
82485
82486 public function unregister()
82487 {
82488 spl_autoload_unregister(array($this, 'loadClass'));
82489 }
82490
82491
82492
82493
82494
82495
82496
82497 public function loadClass($class)
82498 {
82499 if ($file = $this->findFile($class)) {
82500 includeFile($file);
82501
82502 return true;
82503 }
82504 }
82505
82506
82507
82508
82509
82510
82511
82512
82513 public function findFile($class)
82514 {
82515
82516  if (isset($this->classMap[$class])) {
82517 return $this->classMap[$class];
82518 }
82519 if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
82520 return false;
82521 }
82522 if (null !== $this->apcuPrefix) {
82523 $file = apcu_fetch($this->apcuPrefix.$class, $hit);
82524 if ($hit) {
82525 return $file;
82526 }
82527 }
82528
82529 $file = $this->findFileWithExtension($class, '.php');
82530
82531
82532  if (false === $file && defined('HHVM_VERSION')) {
82533 $file = $this->findFileWithExtension($class, '.hh');
82534 }
82535
82536 if (null !== $this->apcuPrefix) {
82537 apcu_add($this->apcuPrefix.$class, $file);
82538 }
82539
82540 if (false === $file) {
82541
82542  $this->missingClasses[$class] = true;
82543 }
82544
82545 return $file;
82546 }
82547
82548 private function findFileWithExtension($class, $ext)
82549 {
82550
82551  $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
82552
82553 $first = $class[0];
82554 if (isset($this->prefixLengthsPsr4[$first])) {
82555 $subPath = $class;
82556 while (false !== $lastPos = strrpos($subPath, '\\')) {
82557 $subPath = substr($subPath, 0, $lastPos);
82558 $search = $subPath.'\\';
82559 if (isset($this->prefixDirsPsr4[$search])) {
82560 foreach ($this->prefixDirsPsr4[$search] as $dir) {
82561 $length = $this->prefixLengthsPsr4[$first][$search];
82562 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
82563 return $file;
82564 }
82565 }
82566 }
82567 }
82568 }
82569
82570
82571  foreach ($this->fallbackDirsPsr4 as $dir) {
82572 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
82573 return $file;
82574 }
82575 }
82576
82577
82578  if (false !== $pos = strrpos($class, '\\')) {
82579
82580  $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
82581 . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
82582 } else {
82583
82584  $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
82585 }
82586
82587 if (isset($this->prefixesPsr0[$first])) {
82588 foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
82589 if (0 === strpos($class, $prefix)) {
82590 foreach ($dirs as $dir) {
82591 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
82592 return $file;
82593 }
82594 }
82595 }
82596 }
82597 }
82598
82599
82600  foreach ($this->fallbackDirsPsr0 as $dir) {
82601 if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
82602 return $file;
82603 }
82604 }
82605
82606
82607  if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
82608 return $file;
82609 }
82610
82611 return false;
82612 }
82613 }
82614
82615
82616
82617
82618
82619
82620 function includeFile($file)
82621 {
82622 include $file;
82623 }
82624 ##
82625 ## Bundle of CA Root Certificates
82626 ##
82627 ## Certificate data from Mozilla as of: Wed Jun  7 03:12:05 2017 GMT
82628 ##
82629 ## This is a bundle of X.509 certificates of public Certificate Authorities
82630 ## (CA). These were automatically extracted from Mozilla's root certificates
82631 ## file (certdata.txt).  This file can be found in the mozilla source tree:
82632 ## https://hg.mozilla.org/releases/mozilla-release/raw-file/default/security/nss/lib/ckfw/builtins/certdata.txt
82633 ##
82634 ## It contains the certificates in PEM format and therefore
82635 ## can be directly used with curl / libcurl / php_curl, or with
82636 ## an Apache+mod_ssl webserver for SSL client authentication.
82637 ## Just configure this file as the SSLCACertificateFile.
82638 ##
82639 ## Conversion done with mk-ca-bundle.pl version 1.27.
82640 ## SHA256: 93753268e1c596aee21893fb1c6975338389132f15c942ed65fc394a904371d7
82641 ##
82642
82643
82644 GlobalSign Root CA
82645 ==================
82646 -----BEGIN CERTIFICATE-----
82647 MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx
82648 GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds
82649 b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV
82650 BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD
82651 VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa
82652 DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc
82653 THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb
82654 Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP
82655 c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX
82656 gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
82657 HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF
82658 AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj
82659 Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG
82660 j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH
82661 hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC
82662 X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
82663 -----END CERTIFICATE-----
82664
82665 GlobalSign Root CA - R2
82666 =======================
82667 -----BEGIN CERTIFICATE-----
82668 MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv
82669 YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
82670 bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
82671 aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
82672 bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6
82673 ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp
82674 s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN
82675 S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL
82676 TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C
82677 ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
82678 FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i
82679 YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN
82680 BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp
82681 9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu
82682 01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7
82683 9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
82684 TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
82685 -----END CERTIFICATE-----
82686
82687 Verisign Class 3 Public Primary Certification Authority - G3
82688 ============================================================
82689 -----BEGIN CERTIFICATE-----
82690 MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV
82691 UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
82692 cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
82693 IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh
82694 dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw
82695 CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy
82696 dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv
82697 cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg
82698 Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
82699 ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1
82700 EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc
82701 cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw
82702 EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj
82703 055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
82704 ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f
82705 j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
82706 /Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0
82707 xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa
82708 t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
82709 -----END CERTIFICATE-----
82710
82711 Entrust.net Premium 2048 Secure Server CA
82712 =========================================
82713 -----BEGIN CERTIFICATE-----
82714 MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u
82715 ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp
82716 bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV
82717 BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx
82718 NzUwNTFaFw0yOTA3MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3
82719 d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl
82720 MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u
82721 ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
82722 MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL
82723 Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr
82724 hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW
82725 nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi
82726 VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo0IwQDAOBgNVHQ8BAf8E
82727 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJ
82728 KoZIhvcNAQEFBQADggEBADubj1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPy
82729 T/4xmf3IDExoU8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
82730 zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5bu/8j72gZyxKT
82731 J1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+bYQLCIt+jerXmCHG8+c8eS9e
82732 nNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/ErfF6adulZkMV8gzURZVE=
82733 -----END CERTIFICATE-----
82734
82735 Baltimore CyberTrust Root
82736 =========================
82737 -----BEGIN CERTIFICATE-----
82738 MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE
82739 ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li
82740 ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC
82741 SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs
82742 dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME
82743 uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB
82744 UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C
82745 G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9
82746 XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr
82747 l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI
82748 VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB
82749 BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh
82750 cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5
82751 hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa
82752 Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H
82753 RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
82754 -----END CERTIFICATE-----
82755
82756 AddTrust Low-Value Services Root
82757 ================================
82758 -----BEGIN CERTIFICATE-----
82759 MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
82760 QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRU
82761 cnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMwMTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQsw
82762 CQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBO
82763 ZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEB
82764 AQUAA4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ulCDtbKRY6
82765 54eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6ntGO0/7Gcrjyvd7ZWxbWr
82766 oulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyldI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1
82767 Zmne3yzxbrww2ywkEtvrNTVokMsAsJchPXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJui
82768 GMx1I4S+6+JNM3GOGvDC+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8w
82769 HQYDVR0OBBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8EBTAD
82770 AQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBlMQswCQYDVQQGEwJT
82771 RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEw
82772 HwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxt
82773 ZBsfzQ3duQH6lmM0MkhHma6X7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0Ph
82774 iVYrqW9yTkkz43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY
82775 eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJlpz/+0WatC7xr
82776 mYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOAWiFeIc9TVPC6b4nbqKqVz4vj
82777 ccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk=
82778 -----END CERTIFICATE-----
82779
82780 AddTrust External Root
82781 ======================
82782 -----BEGIN CERTIFICATE-----
82783 MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
82784 QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD
82785 VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw
82786 NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU
82787 cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg
82788 Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821
82789 +iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw
82790 Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo
82791 aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy
82792 2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7
82793 7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P
82794 BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL
82795 VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk
82796 VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB
82797 IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl
82798 j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
82799 6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355
82800 e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u
82801 G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
82802 -----END CERTIFICATE-----
82803
82804 AddTrust Public Services Root
82805 =============================
82806 -----BEGIN CERTIFICATE-----
82807 MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
82808 QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSAwHgYDVQQDExdBZGRU
82809 cnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAxMDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJ
82810 BgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5l
82811 dHdvcmsxIDAeBgNVBAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEF
82812 AAOCAQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV6tsfSlbu
82813 nyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nXGCwwfQ56HmIexkvA/X1i
82814 d9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnPdzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSG
82815 Aa2Il+tmzV7R/9x98oTaunet3IAIx6eH1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAw
82816 HM+A+WD+eeSI8t0A65RF62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0G
82817 A1UdDgQWBBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
82818 /zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDELMAkGA1UEBhMCU0Ux
82819 FDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29yazEgMB4G
82820 A1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4
82821 JNojVhaTdt02KLmuG7jD8WS6IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL
82822 +YPoRNWyQSW/iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao
82823 GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh4SINhwBk/ox9
82824 Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQmXiLsks3/QppEIW1cxeMiHV9H
82825 EufOX1362KqxMy3ZdvJOOjMMK7MtkAY=
82826 -----END CERTIFICATE-----
82827
82828 AddTrust Qualified Certificates Root
82829 ====================================
82830 -----BEGIN CERTIFICATE-----
82831 MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
82832 QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSMwIQYDVQQDExpBZGRU
82833 cnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcx
82834 CzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQ
82835 IE5ldHdvcmsxIzAhBgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG
82836 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwqxBb/4Oxx
82837 64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G87B4pfYOQnrjfxvM0PC3
82838 KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i2O+tCBGaKZnhqkRFmhJePp1tUvznoD1o
82839 L/BLcHwTOK28FSXx1s6rosAx1i+f4P8UWfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GR
82840 wVY18BTcZTYJbqukB8c10cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HU
82841 MIHRMB0GA1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/
82842 BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6FrpGkwZzELMAkGA1UE
82843 BhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29y
82844 azEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlmaWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQAD
82845 ggEBABmrder4i2VhlRO6aQTvhsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxG
82846 GuoYQ992zPlmhpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X
82847 dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3P6CxB9bpT9ze
82848 RXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9YiQBCYz95OdBEsIJuQRno3eDB
82849 iFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5noxqE=
82850 -----END CERTIFICATE-----
82851
82852 Entrust Root Certification Authority
82853 ====================================
82854 -----BEGIN CERTIFICATE-----
82855 MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV
82856 BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw
82857 b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG
82858 A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0
82859 MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu
82860 MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu
82861 Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v
82862 dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
82863 ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz
82864 A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww
82865 Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68
82866 j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN
82867 rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw
82868 DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1
82869 MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH
82870 hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
82871 A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM
82872 Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa
82873 v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS
82874 W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0
82875 tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8
82876 -----END CERTIFICATE-----
82877
82878 GeoTrust Global CA
82879 ==================
82880 -----BEGIN CERTIFICATE-----
82881 MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
82882 Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw
82883 MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
82884 LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
82885 CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo
82886 BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet
82887 8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc
82888 T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU
82889 vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD
82890 AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk
82891 DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q
82892 zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4
82893 d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2
82894 mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p
82895 XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm
82896 Mw==
82897 -----END CERTIFICATE-----
82898
82899 GeoTrust Global CA 2
82900 ====================
82901 -----BEGIN CERTIFICATE-----
82902 MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
82903 R2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwHhcNMDQwMzA0MDUw
82904 MDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
82905 LjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
82906 ggEKAoIBAQDvPE1APRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/
82907 NTL8Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hLTytCOb1k
82908 LUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL5mkWRxHCJ1kDs6ZgwiFA
82909 Vvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7S4wMcoKK+xfNAGw6EzywhIdLFnopsk/b
82910 HdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQF
82911 MAMBAf8wHQYDVR0OBBYEFHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNH
82912 K266ZUapEBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6tdEPx7
82913 srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv/NgdRN3ggX+d6Yvh
82914 ZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywNA0ZF66D0f0hExghAzN4bcLUprbqL
82915 OzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkC
82916 x1YAzUm5s2x7UwQa4qjJqhIFI8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqF
82917 H4z1Ir+rzoPz4iIprn2DQKi6bA==
82918 -----END CERTIFICATE-----
82919
82920 GeoTrust Universal CA
82921 =====================
82922 -----BEGIN CERTIFICATE-----
82923 MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
82924 R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1
82925 MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu
82926 Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
82927 ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t
82928 JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e
82929 RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs
82930 7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d
82931 8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V
82932 qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga
82933 Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB
82934 Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu
82935 KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08
82936 ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0
82937 XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB
82938 hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
82939 aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2
82940 qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL
82941 oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK
82942 xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF
82943 KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2
82944 DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK
82945 xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU
82946 p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI
82947 P/rmMuGNG2+k5o7Y+SlIis5z/iw=
82948 -----END CERTIFICATE-----
82949
82950 GeoTrust Universal CA 2
82951 =======================
82952 -----BEGIN CERTIFICATE-----
82953 MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
82954 R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0
82955 MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg
82956 SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA
82957 A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0
82958 DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17
82959 j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q
82960 JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a
82961 QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2
82962 WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP
82963 20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn
82964 ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC
82965 SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG
82966 8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2
82967 +/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E
82968 BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
82969 dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ
82970 4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+
82971 mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq
82972 A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg
82973 Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP
82974 pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d
82975 FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp
82976 gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm
82977 X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
82978 -----END CERTIFICATE-----
82979
82980 Visa eCommerce Root
82981 ===================
82982 -----BEGIN CERTIFICATE-----
82983 MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQG
82984 EwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2Ug
82985 QXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2
82986 WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMm
82987 VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv
82988 bW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfL
82989 F9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8b
82990 RaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0
82991 TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI
82992 /k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzs
82993 GHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG
82994 MB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxc
82995 CLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUW
82996 YFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pz
82997 zkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu
82998 YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt
82999 398znM/jra6O1I7mT1GvFpLgXPYHDw==
83000 -----END CERTIFICATE-----
83001
83002 Certum Root CA
83003 ==============
83004 -----BEGIN CERTIFICATE-----
83005 MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQK
83006 ExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQTAeFw0wMjA2MTExMDQ2Mzla
83007 Fw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8u
83008 by4xEjAQBgNVBAMTCUNlcnR1bSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6x
83009 wS7TT3zNJc4YPk/EjG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdL
83010 kKWoePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GIULdtlkIJ
83011 89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapuOb7kky/ZR6By6/qmW6/K
83012 Uz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUgAKpoC6EahQGcxEZjgoi2IrHu/qpGWX7P
83013 NSzVttpd90gzFFS269lvzs2I1qsb2pY7HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkq
83014 hkiG9w0BAQUFAAOCAQEAuI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+
83015 GXYkHAQaTOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTgxSvg
83016 GrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1qCjqTE5s7FCMTY5w/
83017 0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5xO/fIR/RpbxXyEV6DHpx8Uq79AtoS
83018 qFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs6GAqm4VKQPNriiTsBhYscw==
83019 -----END CERTIFICATE-----
83020
83021 Comodo AAA Services root
83022 ========================
83023 -----BEGIN CERTIFICATE-----
83024 MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
83025 R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
83026 TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw
83027 MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl
83028 c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV
83029 BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
83030 ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG
83031 C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs
83032 i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW
83033 Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH
83034 Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK
83035 Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f
83036 BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl
83037 cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz
83038 LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm
83039 7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
83040 Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z
83041 8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C
83042 12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
83043 -----END CERTIFICATE-----
83044
83045 Comodo Secure Services root
83046 ===========================
83047 -----BEGIN CERTIFICATE-----
83048 MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
83049 R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
83050 TGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAw
83051 MDAwMFoXDTI4MTIzMTIzNTk1OVowfjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFu
83052 Y2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAi
83053 BgNVBAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
83054 ADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPMcm3ye5drswfxdySRXyWP
83055 9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3SHpR7LZQdqnXXs5jLrLxkU0C8j6ysNstc
83056 rbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rC
83057 oznl2yY4rYsK7hljxxwk3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3V
83058 p6ea5EQz6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNVHQ4E
83059 FgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w
83060 gYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1NlY3VyZUNlcnRpZmlj
83061 YXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRwOi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlm
83062 aWNhdGVTZXJ2aWNlcy5jcmwwDQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm
83063 4J4oqF7Tt/Q05qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj
83064 Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtIgKvcnDe4IRRL
83065 DXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJaD61JlfutuC23bkpgHl9j6Pw
83066 pCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDlizeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1H
83067 RR3B7Hzs/Sk=
83068 -----END CERTIFICATE-----
83069
83070 Comodo Trusted Services root
83071 ============================
83072 -----BEGIN CERTIFICATE-----
83073 MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
83074 R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
83075 TGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEw
83076 MDAwMDBaFw0yODEyMzEyMzU5NTlaMH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1h
83077 bmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUw
83078 IwYDVQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0BAQEFAAOC
83079 AQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWWfnJSoBVC21ndZHoa0Lh7
83080 3TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMtTGo87IvDktJTdyR0nAducPy9C1t2ul/y
83081 /9c3S0pgePfw+spwtOpZqqPOSC+pw7ILfhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6
83082 juljatEPmsbS9Is6FARW1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsS
83083 ivnkBbA7kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0GA1Ud
83084 DgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
83085 /zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21vZG9jYS5jb20vVHJ1c3RlZENlcnRp
83086 ZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRodHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENl
83087 cnRpZmljYXRlU2VydmljZXMuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8Ntw
83088 uleGFTQQuS9/HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32
83089 pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxISjBc/lDb+XbDA
83090 BHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+xqFx7D+gIIxmOom0jtTYsU0l
83091 R+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/AtyjcndBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O
83092 9y5Xt5hwXsjEeLBi
83093 -----END CERTIFICATE-----
83094
83095 QuoVadis Root CA
83096 ================
83097 -----BEGIN CERTIFICATE-----
83098 MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE
83099 ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
83100 eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz
83101 MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp
83102 cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD
83103 EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
83104 AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk
83105 J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL
83106 F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL
83107 YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen
83108 AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w
83109 PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y
83110 ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7
83111 MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj
83112 YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs
83113 ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh
83114 Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW
83115 Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu
83116 BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw
83117 FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0
83118 aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6
83119 tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo
83120 fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul
83121 LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x
83122 gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi
83123 5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi
83124 5nrQNiOKSnQ2+Q==
83125 -----END CERTIFICATE-----
83126
83127 QuoVadis Root CA 2
83128 ==================
83129 -----BEGIN CERTIFICATE-----
83130 MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
83131 EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx
83132 ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
83133 aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC
83134 DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6
83135 XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk
83136 lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB
83137 lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy
83138 lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt
83139 66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn
83140 wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh
83141 D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy
83142 BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie
83143 J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud
83144 DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU
83145 a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
83146 ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv
83147 Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3
83148 UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm
83149 VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK
83150 +JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW
83151 IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1
83152 WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X
83153 f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II
83154 4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8
83155 VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
83156 -----END CERTIFICATE-----
83157
83158 QuoVadis Root CA 3
83159 ==================
83160 -----BEGIN CERTIFICATE-----
83161 MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
83162 EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx
83163 OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
83164 aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
83165 DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg
83166 DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij
83167 KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K
83168 DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv
83169 BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp
83170 p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8
83171 nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX
83172 MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM
83173 Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz
83174 uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT
83175 BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj
83176 YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
83177 aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB
83178 BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD
83179 VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4
83180 ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE
83181 AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV
83182 qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s
83183 hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z
83184 POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2
83185 Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp
83186 8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC
83187 bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu
83188 g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p
83189 vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr
83190 qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=
83191 -----END CERTIFICATE-----
83192
83193 Security Communication Root CA
83194 ==============================
83195 -----BEGIN CERTIFICATE-----
83196 MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
83197 U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
83198 HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
83199 U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
83200 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw
83201 8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM
83202 DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX
83203 5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd
83204 DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2
83205 JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw
83206 DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g
83207 0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a
83208 mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ
83209 s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ
83210 6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi
83211 FL39vmwLAw==
83212 -----END CERTIFICATE-----
83213
83214 Sonera Class 2 Root CA
83215 ======================
83216 -----BEGIN CERTIFICATE-----
83217 MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG
83218 U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw
83219 NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh
83220 IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3
83221 /Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT
83222 dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG
83223 f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P
83224 tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH
83225 nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT
83226 XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt
83227 0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI
83228 cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph
83229 Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx
83230 EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH
83231 llpwrN9M
83232 -----END CERTIFICATE-----
83233
83234 UTN USERFirst Hardware Root CA
83235 ==============================
83236 -----BEGIN CERTIFICATE-----
83237 MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UE
83238 BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl
83239 IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAd
83240 BgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgx
83241 OTIyWjCBlzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0
83242 eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVz
83243 ZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwggEiMA0GCSqGSIb3
83244 DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlI
83245 wrthdBKWHTxqctU8EGc6Oe0rE81m65UJM6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFd
83246 tqdt++BxF2uiiPsA3/4aMXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8
83247 i4fDidNdoI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqIDsjf
83248 Pe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9KsyoUhbAgMBAAGjgbkw
83249 gbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKFyXyYbKJhDlV0HN9WF
83250 lp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNF
83251 UkZpcnN0LUhhcmR3YXJlLmNybDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUF
83252 BwMGBggrBgEFBQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM
83253 //bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28GpgoiskliCE7/yMgUsogW
83254 XecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gECJChicsZUN/KHAG8HQQZexB2
83255 lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kn
83256 iCrVWFCVH/A7HFe7fRQ5YiuayZSSKqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67
83257 nfhmqA==
83258 -----END CERTIFICATE-----
83259
83260 Camerfirma Chambers of Commerce Root
83261 ====================================
83262 -----BEGIN CERTIFICATE-----
83263 MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe
83264 QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i
83265 ZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAx
83266 NjEzNDNaFw0zNzA5MzAxNjEzNDRaMH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZp
83267 cm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3Jn
83268 MSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0BAQEFAAOC
83269 AQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtbunXF/KGIJPov7coISjlU
83270 xFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0dBmpAPrMMhe5cG3nCYsS4No41XQEMIwRH
83271 NaqbYE6gZj3LJgqcQKH0XZi/caulAGgq7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jW
83272 DA+wWFjbw2Y3npuRVDM30pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFV
83273 d9oKDMyXroDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIGA1Ud
83274 EwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5jaGFtYmVyc2lnbi5v
83275 cmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p26EpW1eLTXYGduHRooowDgYDVR0P
83276 AQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hh
83277 bWJlcnNpZ24ub3JnMCcGA1UdEgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYD
83278 VR0gBFEwTzBNBgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz
83279 aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAAxBl8IahsAi
83280 fJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZdp0AJPaxJRUXcLo0waLIJuvvD
83281 L8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wN
83282 UPf6s+xCX6ndbcj0dc97wXImsQEcXCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/n
83283 ADydb47kMgkdTXg0eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1
83284 erfutGWaIZDgqtCYvDi1czyL+Nw=
83285 -----END CERTIFICATE-----
83286
83287 Camerfirma Global Chambersign Root
83288 ==================================
83289 -----BEGIN CERTIFICATE-----
83290 MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe
83291 QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i
83292 ZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYx
83293 NDE4WhcNMzcwOTMwMTYxNDE4WjB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJt
83294 YSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEg
83295 MB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAw
83296 ggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0Mi+ITaFgCPS3CU6gSS9J
83297 1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/sQJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8O
83298 by4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpVeAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl
83299 6DJWk0aJqCWKZQbua795B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c
83300 8lCrEqWhz0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0TAQH/
83301 BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1iZXJzaWduLm9yZy9j
83302 aGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4wTcbOX60Qq+UDpfqpFDAOBgNVHQ8B
83303 Af8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAHMCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBj
83304 aGFtYmVyc2lnbi5vcmcwKgYDVR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9y
83305 ZzBbBgNVHSAEVDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh
83306 bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEA
83307 PDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUMbKGKfKX0j//U2K0X1S0E0T9Y
83308 gOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXiryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJ
83309 PJ7oKXqJ1/6v/2j1pReQvayZzKWGVwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4
83310 IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes
83311 t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A==
83312 -----END CERTIFICATE-----
83313
83314 XRamp Global CA Root
83315 ====================
83316 -----BEGIN CERTIFICATE-----
83317 MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE
83318 BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj
83319 dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
83320 dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx
83321 HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg
83322 U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
83323 dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu
83324 IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx
83325 foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE
83326 zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs
83327 AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry
83328 xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
83329 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap
83330 oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC
83331 AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc
83332 /Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
83333 qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n
83334 nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz
83335 8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw=
83336 -----END CERTIFICATE-----
83337
83338 Go Daddy Class 2 CA
83339 ===================
83340 -----BEGIN CERTIFICATE-----
83341 MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY
83342 VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp
83343 ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG
83344 A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
83345 RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD
83346 ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
83347 2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32
83348 qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j
83349 YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY
83350 vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O
83351 BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o
83352 atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu
83353 MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG
83354 A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim
83355 PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt
83356 I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
83357 HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI
83358 Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b
83359 vZ8=
83360 -----END CERTIFICATE-----
83361
83362 Starfield Class 2 CA
83363 ====================
83364 -----BEGIN CERTIFICATE-----
83365 MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc
83366 U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg
83367 Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo
83368 MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG
83369 A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG
83370 SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY
83371 bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ
83372 JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm
83373 epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN
83374 F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF
83375 MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f
83376 hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo
83377 bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g
83378 QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs
83379 afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM
83380 PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
83381 xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD
83382 KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3
83383 QBFGmh95DmK/D5fs4C8fF5Q=
83384 -----END CERTIFICATE-----
83385
83386 StartCom Certification Authority
83387 ================================
83388 -----BEGIN CERTIFICATE-----
83389 MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
83390 U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu
83391 ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0
83392 NjM2WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk
83393 LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg
83394 U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
83395 ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y
83396 o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/
83397 Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d
83398 eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt
83399 2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z
83400 6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ
83401 osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/
83402 untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc
83403 UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT
83404 37uMdBNSSwIDAQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
83405 FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9jZXJ0LnN0YXJ0
83406 Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3JsLnN0YXJ0Y29tLm9yZy9zZnNj
83407 YS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFMBgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUH
83408 AgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRw
83409 Oi8vY2VydC5zdGFydGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYg
83410 U3RhcnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlhYmlsaXR5
83411 LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2YgdGhlIFN0YXJ0Q29tIENl
83412 cnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFpbGFibGUgYXQgaHR0cDovL2NlcnQuc3Rh
83413 cnRjb20ub3JnL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilT
83414 dGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOC
83415 AgEAFmyZ9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8jhvh
83416 3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUWFjgKXlf2Ysd6AgXm
83417 vB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJzewT4F+irsfMuXGRuczE6Eri8sxHk
83418 fY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3
83419 fsNrarnDy0RLrHiQi+fHLB5LEUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZ
83420 EoalHmdkrQYuL6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
83421 yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuCO3NJo2pXh5Tl
83422 1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6Vum0ABj6y6koQOdjQK/W/7HW/
83423 lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkyShNOsF/5oirpt9P/FlUQqmMGqz9IgcgA38coro
83424 g14=
83425 -----END CERTIFICATE-----
83426
83427 Taiwan GRCA
83428 ===========
83429 -----BEGIN CERTIFICATE-----
83430 MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG
83431 EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X
83432 DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv
83433 dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD
83434 ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN
83435 w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5
83436 BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O
83437 1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO
83438 htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov
83439 J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7
83440 Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t
83441 B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB
83442 O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8
83443 lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV
83444 HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2
83445 09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ
83446 TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj
83447 Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2
83448 Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU
83449 D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz
83450 DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk
83451 Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk
83452 7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ
83453 CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy
83454 +fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS
83455 -----END CERTIFICATE-----
83456
83457 Swisscom Root CA 1
83458 ==================
83459 -----BEGIN CERTIFICATE-----
83460 MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQG
83461 EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy
83462 dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4
83463 MTgyMjA2MjBaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln
83464 aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIIC
83465 IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9m2BtRsiM
83466 MW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdihFvkcxC7mlSpnzNApbjyF
83467 NDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/TilftKaNXXsLmREDA/7n29uj/x2lzZAe
83468 AR81sH8A25Bvxn570e56eqeqDFdvpG3FEzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkC
83469 b6dJtDZd0KTeByy2dbcokdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn
83470 7uHbHaBuHYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNFvJbN
83471 cA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo19AOeCMgkckkKmUp
83472 WyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjCL3UcPX7ape8eYIVpQtPM+GP+HkM5
83473 haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJWbjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNY
83474 MUJDLXT5xp6mig/p/r+D5kNXJLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw
83475 HQYDVR0hBBYwFDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j
83476 BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzcK6FptWfUjNP9
83477 MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzfky9NfEBWMXrrpA9gzXrzvsMn
83478 jgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7IkVh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQ
83479 MbFamIp1TpBcahQq4FJHgmDmHtqBsfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4H
83480 VtA4oJVwIHaM190e3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtl
83481 vrsRls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ipmXeascCl
83482 OS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HHb6D0jqTsNFFbjCYDcKF3
83483 1QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksfrK/7DZBaZmBwXarNeNQk7shBoJMBkpxq
83484 nvy5JMWzFYJ+vq6VK+uxwNrjAWALXmmshFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCy
83485 x/yP2FS1k2Kdzs9Z+z0YzirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMW
83486 NY6E0F/6MBr1mmz0DlP5OlvRHA==
83487 -----END CERTIFICATE-----
83488
83489 DigiCert Assured ID Root CA
83490 ===========================
83491 -----BEGIN CERTIFICATE-----
83492 MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG
83493 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
83494 IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx
83495 MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
83496 ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew
83497 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO
83498 9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy
83499 UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW
83500 /lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy
83501 oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf
83502 GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF
83503 66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq
83504 hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc
83505 EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn
83506 SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i
83507 8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
83508 +o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
83509 -----END CERTIFICATE-----
83510
83511 DigiCert Global Root CA
83512 =======================
83513 -----BEGIN CERTIFICATE-----
83514 MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG
83515 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
83516 HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw
83517 MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
83518 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq
83519 hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn
83520 TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5
83521 BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H
83522 4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y
83523 7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB
83524 o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm
83525 8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF
83526 BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr
83527 EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt
83528 tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886
83529 UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
83530 CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
83531 -----END CERTIFICATE-----
83532
83533 DigiCert High Assurance EV Root CA
83534 ==================================
83535 -----BEGIN CERTIFICATE-----
83536 MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG
83537 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw
83538 KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw
83539 MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ
83540 MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu
83541 Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t
83542 Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS
83543 OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3
83544 MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ
83545 NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe
83546 h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB
83547 Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY
83548 JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ
83549 V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp
83550 myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK
83551 mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
83552 vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K
83553 -----END CERTIFICATE-----
83554
83555 Certplus Class 2 Primary CA
83556 ===========================
83557 -----BEGIN CERTIFICATE-----
83558 MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkGA1UE
83559 BhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkgQ0EwHhcN
83560 OTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2Vy
83561 dHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
83562 ADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR
83563 5aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyLkcAbmXuZ
83564 Vg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCdEgETjdyAYveVqUSISnFO
83565 YFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yasH7WLO7dDWWuwJKZtkIvEcupdM5i3y95e
83566 e++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRME
83567 CDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJ
83568 YIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29t
83569 L0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvD
83570 P9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1R
83571 TtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+
83572 7UCmnYR0ObncHoUW2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW
83573 //1IMwrh3KWBkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7
83574 l7+ijrRU
83575 -----END CERTIFICATE-----
83576
83577 DST Root CA X3
83578 ==============
83579 -----BEGIN CERTIFICATE-----
83580 MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK
83581 ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X
83582 DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1
83583 cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD
83584 ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT
83585 rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9
83586 UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy
83587 xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d
83588 utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T
83589 AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ
83590 MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug
83591 dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE
83592 GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw
83593 RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS
83594 fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
83595 -----END CERTIFICATE-----
83596
83597 DST ACES CA X6
83598 ==============
83599 -----BEGIN CERTIFICATE-----
83600 MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQG
83601 EwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QxETAPBgNVBAsTCERTVCBBQ0VT
83602 MRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0wMzExMjAyMTE5NThaFw0xNzExMjAyMTE5NTha
83603 MFsxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UE
83604 CxMIRFNUIEFDRVMxFzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOC
83605 AQ8AMIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPuktKe1jzI
83606 DZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7gLFViYsx+tC3dr5BPTCa
83607 pCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZHfAjIgrrep4c9oW24MFbCswKBXy314pow
83608 GCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4aahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPy
83609 MjwmR/onJALJfh1biEITajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1Ud
83610 EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rkc3Qu
83611 Y29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnRy
83612 dXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMtaW5kZXguaHRtbDAdBgNVHQ4EFgQU
83613 CXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZIhvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V2
83614 5FYrnJmQ6AgwbN99Pe7lv7UkQIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6t
83615 Fr8hlxCBPeP/h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq
83616 nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpRrscL9yuwNwXs
83617 vFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf29w4LTJxoeHtxMcfrHuBnQfO3
83618 oKfN5XozNmr6mis=
83619 -----END CERTIFICATE-----
83620
83621 SwissSign Gold CA - G2
83622 ======================
83623 -----BEGIN CERTIFICATE-----
83624 MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw
83625 EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN
83626 MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp
83627 c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B
83628 AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq
83629 t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C
83630 jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg
83631 vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF
83632 ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR
83633 AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend
83634 jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO
83635 peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR
83636 7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi
83637 GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw
83638 AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64
83639 OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
83640 L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm
83641 5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr
83642 44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf
83643 Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m
83644 Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp
83645 mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk
83646 vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf
83647 KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br
83648 NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj
83649 viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
83650 -----END CERTIFICATE-----
83651
83652 SwissSign Silver CA - G2
83653 ========================
83654 -----BEGIN CERTIFICATE-----
83655 MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT
83656 BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X
83657 DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3
83658 aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG
83659 9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644
83660 N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm
83661 +/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH
83662 6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu
83663 MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h
83664 qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5
83665 FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs
83666 ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc
83667 celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X
83668 CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
83669 BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB
83670 tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0
83671 cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P
83672 4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F
83673 kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L
83674 3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx
83675 /uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa
83676 DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP
83677 e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu
83678 WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ
83679 DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub
83680 DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
83681 -----END CERTIFICATE-----
83682
83683 GeoTrust Primary Certification Authority
83684 ========================================
83685 -----BEGIN CERTIFICATE-----
83686 MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG
83687 EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD
83688 ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx
83689 CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ
83690 cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
83691 CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN
83692 b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9
83693 nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge
83694 RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt
83695 tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
83696 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI
83697 hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K
83698 Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN
83699 NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa
83700 Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG
83701 1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
83702 -----END CERTIFICATE-----
83703
83704 thawte Primary Root CA
83705 ======================
83706 -----BEGIN CERTIFICATE-----
83707 MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE
83708 BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
83709 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
83710 cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3
83711 MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg
83712 SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv
83713 KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT
83714 FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs
83715 oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ
83716 1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc
83717 q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K
83718 aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p
83719 afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
83720 VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF
83721 AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE
83722 uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
83723 xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89
83724 jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH
83725 z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA==
83726 -----END CERTIFICATE-----
83727
83728 VeriSign Class 3 Public Primary Certification Authority - G5
83729 ============================================================
83730 -----BEGIN CERTIFICATE-----
83731 MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
83732 BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
83733 ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
83734 IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp
83735 ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB
83736 yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln
83737 biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh
83738 dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt
83739 YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
83740 ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz
83741 j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD
83742 Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/
83743 Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r
83744 fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/
83745 BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv
83746 Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
83747 aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
83748 SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+
83749 X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE
83750 KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC
83751 Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE
83752 ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
83753 -----END CERTIFICATE-----
83754
83755 SecureTrust CA
83756 ==============
83757 -----BEGIN CERTIFICATE-----
83758 MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG
83759 EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy
83760 dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe
83761 BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC
83762 ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX
83763 OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t
83764 DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH
83765 GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b
83766 01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH
83767 ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/
83768 BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj
83769 aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
83770 KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu
83771 SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf
83772 mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ
83773 nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
83774 3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
83775 -----END CERTIFICATE-----
83776
83777 Secure Global CA
83778 ================
83779 -----BEGIN CERTIFICATE-----
83780 MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG
83781 EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH
83782 bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg
83783 MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg
83784 Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx
83785 YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ
83786 bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g
83787 8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV
83788 HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi
83789 0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
83790 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn
83791 oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA
83792 MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+
83793 OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn
83794 CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5
83795 3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
83796 f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
83797 -----END CERTIFICATE-----
83798
83799 COMODO Certification Authority
83800 ==============================
83801 -----BEGIN CERTIFICATE-----
83802 MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE
83803 BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
83804 A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1
83805 dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb
83806 MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD
83807 T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
83808 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH
83809 +7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww
83810 xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV
83811 4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA
83812 1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI
83813 rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E
83814 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k
83815 b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC
83816 AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP
83817 OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
83818 RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc
83819 IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN
83820 +8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ==
83821 -----END CERTIFICATE-----
83822
83823 Network Solutions Certificate Authority
83824 =======================================
83825 -----BEGIN CERTIFICATE-----
83826 MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG
83827 EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr
83828 IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx
83829 MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
83830 MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G
83831 CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx
83832 jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT
83833 aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT
83834 crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc
83835 /Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB
83836 AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP
83837 BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv
83838 bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA
83839 A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q
83840 4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/
83841 GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
83842 wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD
83843 ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
83844 -----END CERTIFICATE-----
83845
83846 COMODO ECC Certification Authority
83847 ==================================
83848 -----BEGIN CERTIFICATE-----
83849 MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC
83850 R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
83851 ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB
83852 dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix
83853 GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
83854 Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo
83855 b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X
83856 4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni
83857 wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E
83858 BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG
83859 FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA
83860 U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
83861 -----END CERTIFICATE-----
83862
83863 Security Communication EV RootCA1
83864 =================================
83865 -----BEGIN CERTIFICATE-----
83866 MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
83867 U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMhU2VjdXJpdHkgQ29tbXVuaWNh
83868 dGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIzMloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UE
83869 BhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNl
83870 Y3VyaXR5IENvbW11bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
83871 AQoCggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSERMqm4miO
83872 /VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gOzXppFodEtZDkBp2uoQSX
83873 WHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4z
83874 ZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDFMxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4
83875 bepJz11sS6/vmsJWXMY1VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK
83876 9U2vP9eCOKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
83877 SIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HWtWS3irO4G8za+6xm
83878 iEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZq51ihPZRwSzJIxXYKLerJRO1RuGG
83879 Av8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDbEJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnW
83880 mHyojf6GPgcWkuF75x3sM3Z+Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEW
83881 T1MKZPlO9L9OVL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490
83882 -----END CERTIFICATE-----
83883
83884 OISTE WISeKey Global Root GA CA
83885 ===============================
83886 -----BEGIN CERTIFICATE-----
83887 MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE
83888 BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG
83889 A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH
83890 bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD
83891 VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw
83892 IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5
83893 IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9
83894 Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg
83895 Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD
83896 d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ
83897 /yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R
83898 LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw
83899 AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
83900 KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm
83901 MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4
83902 +vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa
83903 hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY
83904 okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0=
83905 -----END CERTIFICATE-----
83906
83907 Certigna
83908 ========
83909 -----BEGIN CERTIFICATE-----
83910 MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw
83911 EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3
83912 MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI
83913 Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q
83914 XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH
83915 GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p
83916 ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg
83917 DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf
83918 Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ
83919 tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ
83920 BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J
83921 SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA
83922 hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+
83923 ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu
83924 PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY
83925 1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
83926 WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
83927 -----END CERTIFICATE-----
83928
83929 Deutsche Telekom Root CA 2
83930 ==========================
83931 -----BEGIN CERTIFICATE-----
83932 MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT
83933 RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG
83934 A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5
83935 MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G
83936 A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS
83937 b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5
83938 bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI
83939 KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY
83940 AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK
83941 Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV
83942 jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV
83943 HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr
83944 E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy
83945 zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8
83946 rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G
83947 dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU
83948 Cm26OWMohpLzGITY+9HPBVZkVw==
83949 -----END CERTIFICATE-----
83950
83951 Cybertrust Global Root
83952 ======================
83953 -----BEGIN CERTIFICATE-----
83954 MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li
83955 ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4
83956 MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD
83957 ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
83958 +Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW
83959 0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL
83960 AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin
83961 89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT
83962 8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP
83963 BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2
83964 MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G
83965 A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO
83966 lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi
83967 5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2
83968 hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T
83969 X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
83970 WL1WMRJOEcgh4LMRkWXbtKaIOM5V
83971 -----END CERTIFICATE-----
83972
83973 ePKI Root Certification Authority
83974 =================================
83975 -----BEGIN CERTIFICATE-----
83976 MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG
83977 EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg
83978 Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx
83979 MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq
83980 MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B
83981 AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs
83982 IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi
83983 lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv
83984 qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX
83985 12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O
83986 WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+
83987 ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao
83988 lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/
83989 vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi
83990 Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi
83991 MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
83992 ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0
83993 1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq
83994 KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV
83995 xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP
83996 NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r
83997 GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE
83998 xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx
83999 gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy
84000 sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD
84001 BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw=
84002 -----END CERTIFICATE-----
84003
84004 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
84005 =============================================================================================================================
84006 -----BEGIN CERTIFICATE-----
84007 MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRSMRgwFgYDVQQH
84008 DA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJpbGltc2VsIHZlIFRla25vbG9q
84009 aWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSwVEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ry
84010 b25payB2ZSBLcmlwdG9sb2ppIEFyYcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNV
84011 BAsMGkthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUg
84012 S8O2ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAeFw0wNzA4
84013 MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIxGDAWBgNVBAcMD0dlYnpl
84014 IC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmlsaW1zZWwgdmUgVGVrbm9sb2ppayBBcmHF
84015 n3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBUQUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZl
84016 IEtyaXB0b2xvamkgQXJhxZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2Ft
84017 dSBTZXJ0aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7ZrIFNl
84018 cnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIBIjANBgkqhkiG9w0B
84019 AQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4hgb46ezzb8R1Sf1n68yJMlaCQvEhO
84020 Eav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yKO7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1
84021 xnnRFDDtG1hba+818qEhTsXOfJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR
84022 6Oqeyjh1jmKwlZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL
84023 hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQIDAQABo0IwQDAd
84024 BgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
84025 MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmPNOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4
84026 N5EY3ATIZJkrGG2AA1nJrvhY0D7twyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLT
84027 y9LQQfMmNkqblWwM7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYh
84028 LBOhgLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5noN+J1q2M
84029 dqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUsyZyQ2uypQjyttgI=
84030 -----END CERTIFICATE-----
84031
84032 certSIGN ROOT CA
84033 ================
84034 -----BEGIN CERTIFICATE-----
84035 MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD
84036 VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa
84037 Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE
84038 CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I
84039 JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH
84040 rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2
84041 ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD
84042 0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943
84043 AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B
84044 Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB
84045 AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8
84046 SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0
84047 x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt
84048 vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz
84049 TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD
84050 -----END CERTIFICATE-----
84051
84052 CNNIC ROOT
84053 ==========
84054 -----BEGIN CERTIFICATE-----
84055 MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJDTjEOMAwGA1UE
84056 ChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2MDcwOTE0WhcNMjcwNDE2MDcw
84057 OTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1Qw
84058 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzD
84059 o+/hn7E7SIX1mlwhIhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tiz
84060 VHa6dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZOV/kbZKKT
84061 VrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrCGHn2emU1z5DrvTOTn1Or
84062 czvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gNv7Sg2Ca+I19zN38m5pIEo3/PIKe38zrK
84063 y5nLAgMBAAGjczBxMBEGCWCGSAGG+EIBAQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscC
84064 wQ7vptU7ETAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991S
84065 lgrHAsEO76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnKOOK5
84066 Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvHugDnuL8BV8F3RTIM
84067 O/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7HgviyJA/qIYM/PmLXoXLT1tLYhFHxUV8
84068 BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fLbuXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2
84069 G8kS1sHNzYDzAgE8yGnLRUhj2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5m
84070 mxE=
84071 -----END CERTIFICATE-----
84072
84073 GeoTrust Primary Certification Authority - G3
84074 =============================================
84075 -----BEGIN CERTIFICATE-----
84076 MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE
84077 BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0
84078 IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy
84079 eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz
84080 NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo
84081 YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT
84082 LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI
84083 hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j
84084 K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE
84085 c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C
84086 IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu
84087 dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC
84088 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr
84089 2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9
84090 cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE
84091 Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
84092 AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s
84093 t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt
84094 -----END CERTIFICATE-----
84095
84096 thawte Primary Root CA - G2
84097 ===========================
84098 -----BEGIN CERTIFICATE-----
84099 MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC
84100 VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu
84101 IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg
84102 Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV
84103 MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG
84104 b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt
84105 IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS
84106 LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5
84107 8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU
84108 mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN
84109 G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K
84110 rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
84111 -----END CERTIFICATE-----
84112
84113 thawte Primary Root CA - G3
84114 ===========================
84115 -----BEGIN CERTIFICATE-----
84116 MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE
84117 BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
84118 aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
84119 cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w
84120 ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
84121 d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD
84122 VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG
84123 A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
84124 MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At
84125 P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC
84126 +BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY
84127 7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW
84128 vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E
84129 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ
84130 KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK
84131 A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu
84132 t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC
84133 8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm
84134 er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A=
84135 -----END CERTIFICATE-----
84136
84137 GeoTrust Primary Certification Authority - G2
84138 =============================================
84139 -----BEGIN CERTIFICATE-----
84140 MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC
84141 VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu
84142 Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD
84143 ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1
84144 OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
84145 MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl
84146 b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG
84147 BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc
84148 KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD
84149 VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+
84150 EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m
84151 ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2
84152 npaqBA+K
84153 -----END CERTIFICATE-----
84154
84155 VeriSign Universal Root Certification Authority
84156 ===============================================
84157 -----BEGIN CERTIFICATE-----
84158 MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE
84159 BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
84160 ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
84161 IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u
84162 IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV
84163 UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
84164 cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
84165 IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0
84166 aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj
84167 1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP
84168 MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72
84169 9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I
84170 AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR
84171 tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G
84172 CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O
84173 a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
84174 DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3
84175 Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx
84176 Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx
84177 P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P
84178 wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4
84179 mJO37M2CYfE45k+XmCpajQ==
84180 -----END CERTIFICATE-----
84181
84182 VeriSign Class 3 Public Primary Certification Authority - G4
84183 ============================================================
84184 -----BEGIN CERTIFICATE-----
84185 MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC
84186 VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3
84187 b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz
84188 ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj
84189 YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL
84190 MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU
84191 cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo
84192 b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5
84193 IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8
84194 Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz
84195 rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB
84196 /zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw
84197 HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u
84198 Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD
84199 A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx
84200 AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
84201 -----END CERTIFICATE-----
84202
84203 NetLock Arany (Class Gold) Főtanúsítvány
84204 ========================================
84205 -----BEGIN CERTIFICATE-----
84206 MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G
84207 A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610
84208 dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB
84209 cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx
84210 MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO
84211 ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv
84212 biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6
84213 c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu
84214 0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw
84215 /HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk
84216 H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw
84217 fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1
84218 neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB
84219 BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW
84220 qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta
84221 YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
84222 bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna
84223 NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu
84224 dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
84225 -----END CERTIFICATE-----
84226
84227 Staat der Nederlanden Root CA - G2
84228 ==================================
84229 -----BEGIN CERTIFICATE-----
84230 MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
84231 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
84232 Um9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oXDTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMC
84233 TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
84234 ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ
84235 5291qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8SpuOUfiUtn
84236 vWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPUZ5uW6M7XxgpT0GtJlvOj
84237 CwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvEpMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiil
84238 e7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCR
84239 OME4HYYEhLoaJXhena/MUGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpI
84240 CT0ugpTNGmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy5V65
84241 48r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv6q012iDTiIJh8BIi
84242 trzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEKeN5KzlW/HdXZt1bv8Hb/C3m1r737
84243 qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMB
84244 AAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcC
84245 ARYxaHR0cDovL3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV
84246 HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqGSIb3DQEBCwUA
84247 A4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLySCZa59sCrI2AGeYwRTlHSeYAz
84248 +51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwj
84249 f/ST7ZwaUb7dRUG/kSS0H4zpX897IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaN
84250 kqbG9AclVMwWVxJKgnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfk
84251 CpYL+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxLvJxxcypF
84252 URmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkmbEgeqmiSBeGCc1qb3Adb
84253 CG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvkN1trSt8sV4pAWja63XVECDdCcAz+3F4h
84254 oKOKwJCcaNpQ5kUQR3i2TtJlycM33+FCY7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoV
84255 IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm
84256 66+KAQ==
84257 -----END CERTIFICATE-----
84258
84259 Hongkong Post Root CA 1
84260 =======================
84261 -----BEGIN CERTIFICATE-----
84262 MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT
84263 DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx
84264 NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n
84265 IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF
84266 AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1
84267 ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr
84268 auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh
84269 qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY
84270 V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV
84271 HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i
84272 h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio
84273 l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei
84274 IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps
84275 T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT
84276 c4afU9hDDl3WY4JxHYB0yvbiAmvZWg==
84277 -----END CERTIFICATE-----
84278
84279 SecureSign RootCA11
84280 ===================
84281 -----BEGIN CERTIFICATE-----
84282 MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi
84283 SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS
84284 b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw
84285 KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1
84286 cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL
84287 TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO
84288 wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq
84289 g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP
84290 O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA
84291 bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX
84292 t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh
84293 OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r
84294 bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ
84295 Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01
84296 y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061
84297 lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I=
84298 -----END CERTIFICATE-----
84299
84300 ACEDICOM Root
84301 =============
84302 -----BEGIN CERTIFICATE-----
84303 MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UEAwwNQUNFRElD
84304 T00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMB4XDTA4
84305 MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEWMBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoG
84306 A1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEF
84307 AAOCAg8AMIICCgKCAgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHk
84308 WLn709gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7XBZXehuD
84309 YAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5PGrjm6gSSrj0RuVFCPYew
84310 MYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAKt0SdE3QrwqXrIhWYENiLxQSfHY9g5QYb
84311 m8+5eaA9oiM/Qj9r+hwDezCNzmzAv+YbX79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbk
84312 HQl/Sog4P75n/TSW9R28MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTT
84313 xKJxqvQUfecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI2Sf2
84314 3EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyHK9caUPgn6C9D4zq9
84315 2Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEaeZAwUswdbxcJzbPEHXEUkFDWug/Fq
84316 TYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz
84317 4SsrSbbXc6GqlPUB53NlTKxQMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU
84318 9QHnc2VMrFAwRAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv
84319 bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWImfQwng4/F9tqg
84320 aHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3gvoFNTPhNahXwOf9jU8/kzJP
84321 eGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKeI6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1Pwk
84322 zQSulgUV1qzOMPPKC8W64iLgpq0i5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1
84323 ThCojz2GuHURwCRiipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oI
84324 KiMnMCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZo5NjEFIq
84325 nxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6zqylfDJKZ0DcMDQj3dcE
84326 I2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacNGHk0vFQYXlPKNFHtRQrmjseCNj6nOGOp
84327 MCwXEGCSn1WHElkQwg9naRHMTh5+Spqtr0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3o
84328 tkYNbn5XOmeUwssfnHdKZ05phkOTOPu220+DkdRgfks+KzgHVZhepA==
84329 -----END CERTIFICATE-----
84330
84331 Microsec e-Szigno Root CA 2009
84332 ==============================
84333 -----BEGIN CERTIFICATE-----
84334 MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER
84335 MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv
84336 c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
84337 dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE
84338 BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt
84339 U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw
84340 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA
84341 fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG
84342 0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA
84343 pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm
84344 1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC
84345 AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf
84346 QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE
84347 FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o
84348 lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX
84349 I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
84350 tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02
84351 yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi
84352 LXpUq3DDfSJlgnCW
84353 -----END CERTIFICATE-----
84354
84355 GlobalSign Root CA - R3
84356 =======================
84357 -----BEGIN CERTIFICATE-----
84358 MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv
84359 YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
84360 bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
84361 aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
84362 bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt
84363 iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ
84364 0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3
84365 rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl
84366 OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2
84367 xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
84368 FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7
84369 lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8
84370 EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E
84371 bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18
84372 YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r
84373 kpeDMdmztcpHWD9f
84374 -----END CERTIFICATE-----
84375
84376 Autoridad de Certificacion Firmaprofesional CIF A62634068
84377 =========================================================
84378 -----BEGIN CERTIFICATE-----
84379 MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA
84380 BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
84381 MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw
84382 QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB
84383 NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD
84384 Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P
84385 B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY
84386 7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH
84387 ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI
84388 plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX
84389 MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX
84390 LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK
84391 bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU
84392 vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud
84393 EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH
84394 DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
84395 cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA
84396 bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx
84397 ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx
84398 51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk
84399 R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP
84400 T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f
84401 Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl
84402 osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR
84403 crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR
84404 saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD
84405 KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi
84406 6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
84407 -----END CERTIFICATE-----
84408
84409 Izenpe.com
84410 ==========
84411 -----BEGIN CERTIFICATE-----
84412 MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG
84413 EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz
84414 MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu
84415 QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ
84416 03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK
84417 ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU
84418 +zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC
84419 PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT
84420 OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK
84421 F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK
84422 0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+
84423 0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB
84424 leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID
84425 AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+
84426 SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG
84427 NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
84428 MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
84429 BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l
84430 Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga
84431 kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q
84432 hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs
84433 g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5
84434 aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5
84435 nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC
84436 ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo
84437 Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z
84438 WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
84439 -----END CERTIFICATE-----
84440
84441 Chambers of Commerce Root - 2008
84442 ================================
84443 -----BEGIN CERTIFICATE-----
84444 MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD
84445 MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
84446 bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
84447 QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy
84448 Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl
84449 ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF
84450 EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl
84451 cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
84452 AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA
84453 XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj
84454 h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/
84455 ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk
84456 NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g
84457 D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331
84458 lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ
84459 0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj
84460 ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2
84461 EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI
84462 G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ
84463 BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh
84464 bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh
84465 bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC
84466 CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH
84467 AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1
84468 wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH
84469 3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU
84470 RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6
84471 M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1
84472 YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF
84473 9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK
84474 zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG
84475 nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg
84476 OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ
84477 -----END CERTIFICATE-----
84478
84479 Global Chambersign Root - 2008
84480 ==============================
84481 -----BEGIN CERTIFICATE-----
84482 MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD
84483 MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
84484 bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
84485 QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx
84486 NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg
84487 Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ
84488 QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD
84489 aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf
84490 VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf
84491 XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0
84492 ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB
84493 /gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA
84494 TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M
84495 H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe
84496 Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF
84497 HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh
84498 wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB
84499 AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT
84500 BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE
84501 BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm
84502 aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm
84503 aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp
84504 1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0
84505 dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG
84506 /5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6
84507 ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s
84508 dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg
84509 9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH
84510 foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du
84511 qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr
84512 P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq
84513 c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z
84514 09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B
84515 -----END CERTIFICATE-----
84516
84517 Go Daddy Root Certificate Authority - G2
84518 ========================================
84519 -----BEGIN CERTIFICATE-----
84520 MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
84521 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu
84522 MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
84523 MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
84524 b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G
84525 A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
84526 hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq
84527 9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD
84528 +qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd
84529 fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl
84530 NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC
84531 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9
84532 BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac
84533 vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r
84534 5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV
84535 N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
84536 LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1
84537 -----END CERTIFICATE-----
84538
84539 Starfield Root Certificate Authority - G2
84540 =========================================
84541 -----BEGIN CERTIFICATE-----
84542 MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
84543 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
84544 b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0
84545 eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw
84546 DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg
84547 VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB
84548 dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv
84549 W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs
84550 bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk
84551 N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf
84552 ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU
84553 JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
84554 AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol
84555 TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx
84556 4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw
84557 F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
84558 pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ
84559 c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
84560 -----END CERTIFICATE-----
84561
84562 Starfield Services Root Certificate Authority - G2
84563 ==================================================
84564 -----BEGIN CERTIFICATE-----
84565 MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
84566 B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
84567 b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl
84568 IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV
84569 BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT
84570 dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg
84571 Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
84572 AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2
84573 h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa
84574 hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP
84575 LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB
84576 rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
84577 AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG
84578 SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP
84579 E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy
84580 xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
84581 iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza
84582 YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6
84583 -----END CERTIFICATE-----
84584
84585 AffirmTrust Commercial
84586 ======================
84587 -----BEGIN CERTIFICATE-----
84588 MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS
84589 BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw
84590 MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
84591 bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF
84592 AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb
84593 DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV
84594 C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6
84595 BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww
84596 MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV
84597 HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
84598 AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG
84599 hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi
84600 qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv
84601 0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh
84602 sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
84603 -----END CERTIFICATE-----
84604
84605 AffirmTrust Networking
84606 ======================
84607 -----BEGIN CERTIFICATE-----
84608 MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS
84609 BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw
84610 MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
84611 bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF
84612 AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE
84613 Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI
84614 dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24
84615 /PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb
84616 h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV
84617 HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
84618 AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu
84619 UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6
84620 12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23
84621 WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9
84622 /ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
84623 -----END CERTIFICATE-----
84624
84625 AffirmTrust Premium
84626 ===================
84627 -----BEGIN CERTIFICATE-----
84628 MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS
84629 BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy
84630 OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy
84631 dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
84632 MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn
84633 BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV
84634 5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs
84635 +7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd
84636 GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R
84637 p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI
84638 S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04
84639 6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5
84640 /bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo
84641 +Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB
84642 /wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv
84643 MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
84644 Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC
84645 6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S
84646 L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK
84647 +4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV
84648 BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg
84649 IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60
84650 g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb
84651 zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw==
84652 -----END CERTIFICATE-----
84653
84654 AffirmTrust Premium ECC
84655 =======================
84656 -----BEGIN CERTIFICATE-----
84657 MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV
84658 BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx
84659 MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U
84660 cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA
84661 IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ
84662 N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW
84663 BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK
84664 BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X
84665 57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM
84666 eQ==
84667 -----END CERTIFICATE-----
84668
84669 Certum Trusted Network CA
84670 =========================
84671 -----BEGIN CERTIFICATE-----
84672 MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK
84673 ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv
84674 biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy
84675 MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU
84676 ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
84677 MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
84678 AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC
84679 l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J
84680 J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4
84681 fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0
84682 cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB
84683 Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw
84684 DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj
84685 jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1
84686 mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj
84687 Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
84688 03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
84689 -----END CERTIFICATE-----
84690
84691 Certinomis - Autorité Racine
84692 ============================
84693 -----BEGIN CERTIFICATE-----
84694 MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjETMBEGA1UEChMK
84695 Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAkBgNVBAMMHUNlcnRpbm9taXMg
84696 LSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkG
84697 A1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYw
84698 JAYDVQQDDB1DZXJ0aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQAD
84699 ggIPADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jYF1AMnmHa
84700 wE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N8y4oH3DfVS9O7cdxbwly
84701 Lu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWerP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw
84702 2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92N
84703 jMD2AR5vpTESOH2VwnHu7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9q
84704 c1pkIuVC28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6lSTC
84705 lrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1Enn1So2+WLhl+HPNb
84706 xxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB0iSVL1N6aaLwD4ZFjliCK0wi1F6g
84707 530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql095gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna
84708 4NH4+ej9Uji29YnfAgMBAAGjWzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
84709 A1UdDgQWBBQNjLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ
84710 KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9sov3/4gbIOZ/x
84711 WqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZMOH8oMDX/nyNTt7buFHAAQCva
84712 R6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40
84713 nJ+U8/aGH88bc62UeYdocMMzpXDn2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1B
84714 CxMjidPJC+iKunqjo3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjv
84715 JL1vnxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG5ERQL1TE
84716 qkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWqpdEdnV1j6CTmNhTih60b
84717 WfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZbdsLLO7XSAPCjDuGtbkD326C00EauFddE
84718 wk01+dIL8hf2rGbVJLJP0RyZwG71fet0BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/
84719 vgt2Fl43N+bYdJeimUV5
84720 -----END CERTIFICATE-----
84721
84722 TWCA Root Certification Authority
84723 =================================
84724 -----BEGIN CERTIFICATE-----
84725 MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ
84726 VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh
84727 dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG
84728 EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB
84729 IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
84730 AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx
84731 QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC
84732 oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP
84733 4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r
84734 y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB
84735 BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG
84736 9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC
84737 mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW
84738 QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY
84739 T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny
84740 Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
84741 -----END CERTIFICATE-----
84742
84743 Security Communication RootCA2
84744 ==============================
84745 -----BEGIN CERTIFICATE-----
84746 MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
84747 U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh
84748 dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC
84749 SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy
84750 aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
84751 ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++
84752 +T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R
84753 3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV
84754 spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K
84755 EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8
84756 QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
84757 CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj
84758 u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk
84759 3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q
84760 tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29
84761 mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
84762 -----END CERTIFICATE-----
84763
84764 EC-ACC
84765 ======
84766 -----BEGIN CERTIFICATE-----
84767 MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE
84768 BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w
84769 ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD
84770 VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE
84771 CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT
84772 BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7
84773 MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt
84774 SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl
84775 Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh
84776 cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND
84777 MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK
84778 w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT
84779 ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4
84780 HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a
84781 E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw
84782 0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E
84783 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD
84784 VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0
84785 Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l
84786 dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ
84787 lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa
84788 Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe
84789 l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2
84790 E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D
84791 5EI=
84792 -----END CERTIFICATE-----
84793
84794 Hellenic Academic and Research Institutions RootCA 2011
84795 =======================================================
84796 -----BEGIN CERTIFICATE-----
84797 MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT
84798 O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y
84799 aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
84800 IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT
84801 AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
84802 IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo
84803 IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
84804 AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI
84805 1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa
84806 71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u
84807 8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH
84808 3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/
84809 MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8
84810 MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu
84811 b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt
84812 XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
84813 TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD
84814 /md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N
84815 7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4
84816 -----END CERTIFICATE-----
84817
84818 Actalis Authentication Root CA
84819 ==============================
84820 -----BEGIN CERTIFICATE-----
84821 MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM
84822 BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE
84823 AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky
84824 MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz
84825 IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
84826 IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ
84827 wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa
84828 by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6
84829 zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f
84830 YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2
84831 oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l
84832 EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7
84833 hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8
84834 EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5
84835 jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY
84836 iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
84837 ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI
84838 WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0
84839 JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx
84840 K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+
84841 Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC
84842 4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo
84843 2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz
84844 lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem
84845 OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9
84846 vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
84847 -----END CERTIFICATE-----
84848
84849 Trustis FPS Root CA
84850 ===================
84851 -----BEGIN CERTIFICATE-----
84852 MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG
84853 EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290
84854 IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV
84855 BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ
84856 KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ
84857 RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk
84858 H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa
84859 cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt
84860 o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA
84861 AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd
84862 BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c
84863 GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC
84864 yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P
84865 8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV
84866 l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl
84867 iB6XzCGcKQENZetX2fNXlrtIzYE=
84868 -----END CERTIFICATE-----
84869
84870 StartCom Certification Authority
84871 ================================
84872 -----BEGIN CERTIFICATE-----
84873 MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
84874 U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu
84875 ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0
84876 NjM3WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk
84877 LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg
84878 U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
84879 ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y
84880 o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/
84881 Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d
84882 eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt
84883 2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z
84884 6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ
84885 osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/
84886 untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc
84887 UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT
84888 37uMdBNSSwIDAQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
84889 VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFulF2mHMMo0aEPQ
84890 Qa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCCATgwLgYIKwYBBQUHAgEWImh0
84891 dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cu
84892 c3RhcnRzc2wuY29tL2ludGVybWVkaWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENv
84893 bW1lcmNpYWwgKFN0YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0
84894 aGUgc2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0aWZpY2F0
84895 aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t
84896 L3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBG
84897 cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5
84898 fPGFf59Jb2vKXfuM/gTFwWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWm
84899 N3PH/UvSTa0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst0OcN
84900 Org+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNcpRJvkrKTlMeIFw6T
84901 tn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKlCcWw0bdT82AUuoVpaiF8H3VhFyAX
84902 e2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVFP0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA
84903 2MFrLH9ZXF2RsXAiV+uKa0hK1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBs
84904 HvUwyKMQ5bLmKhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE
84905 JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ8dCAWZvLMdib
84906 D4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnmfyWl8kgAwKQB2j8=
84907 -----END CERTIFICATE-----
84908
84909 StartCom Certification Authority G2
84910 ===================================
84911 -----BEGIN CERTIFICATE-----
84912 MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
84913 U3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
84914 RzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UE
84915 ChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3Jp
84916 dHkgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8O
84917 o1XJJZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsDvfOpL9HG
84918 4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnooD/Uefyf3lLE3PbfHkffi
84919 Aez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/Q0kGi4xDuFby2X8hQxfqp0iVAXV16iul
84920 Q5XqFYSdCI0mblWbq9zSOdIxHWDirMxWRST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbs
84921 O+wmETRIjfaAKxojAuuKHDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8H
84922 vKTlXcxNnw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM0D4L
84923 nMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/iUUjXuG+v+E5+M5iS
84924 FGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9Ha90OrInwMEePnWjFqmveiJdnxMa
84925 z6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHgTuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8E
84926 BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJ
84927 KoZIhvcNAQELBQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K
84928 2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfXUfEpY9Z1zRbk
84929 J4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl6/2o1PXWT6RbdejF0mCy2wl+
84930 JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG
84931 /+gyRr61M3Z3qAFdlsHB1b6uJcDJHgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTc
84932 nIhT76IxW1hPkWLIwpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/Xld
84933 blhYXzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5lIxKVCCIc
84934 l85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoohdVddLHRDiBYmxOlsGOm
84935 7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulrso8uBtjRkcfGEvRM/TAXw8HaOFvjqerm
84936 obp573PYtlNXLfbQ4ddI
84937 -----END CERTIFICATE-----
84938
84939 Buypass Class 2 Root CA
84940 =======================
84941 -----BEGIN CERTIFICATE-----
84942 MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
84943 QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X
84944 DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
84945 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw
84946 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1
84947 g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn
84948 9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b
84949 /+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU
84950 CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff
84951 awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI
84952 zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn
84953 Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX
84954 Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs
84955 M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
84956 VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
84957 AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s
84958 A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI
84959 osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S
84960 aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd
84961 DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD
84962 LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0
84963 oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC
84964 wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS
84965 CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN
84966 rJgWVqA=
84967 -----END CERTIFICATE-----
84968
84969 Buypass Class 3 Root CA
84970 =======================
84971 -----BEGIN CERTIFICATE-----
84972 MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
84973 QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X
84974 DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
84975 eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw
84976 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH
84977 sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR
84978 5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh
84979 7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ
84980 ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH
84981 2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV
84982 /afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ
84983 RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA
84984 Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq
84985 j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
84986 VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
84987 AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV
84988 cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G
84989 uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG
84990 Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8
84991 ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2
84992 KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz
84993 6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug
84994 UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe
84995 eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi
84996 Cp/HuZc=
84997 -----END CERTIFICATE-----
84998
84999 T-TeleSec GlobalRoot Class 3
85000 ============================
85001 -----BEGIN CERTIFICATE-----
85002 MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
85003 IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
85004 cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx
85005 MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
85006 dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
85007 ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3
85008 DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK
85009 9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU
85010 NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF
85011 iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W
85012 0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA
85013 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr
85014 AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb
85015 fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT
85016 ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h
85017 P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
85018 e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw==
85019 -----END CERTIFICATE-----
85020
85021 EE Certification Centre Root CA
85022 ===============================
85023 -----BEGIN CERTIFICATE-----
85024 MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG
85025 EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy
85026 dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw
85027 MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB
85028 UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy
85029 ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB
85030 DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM
85031 TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2
85032 rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw
85033 93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN
85034 P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T
85035 AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ
85036 MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF
85037 BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj
85038 xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM
85039 lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u
85040 uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU
85041 3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM
85042 dcGWxZ0=
85043 -----END CERTIFICATE-----
85044
85045 TURKTRUST Certificate Services Provider Root 2007
85046 =================================================
85047 -----BEGIN CERTIFICATE-----
85048 MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOcUktUUlVTVCBF
85049 bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP
85050 MA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg
85051 QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4X
85052 DTA3MTIyNTE4MzcxOVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxl
85053 a3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMCVFIxDzAN
85054 BgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp
85055 bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4gKGMpIEFyYWzEsWsgMjAwNzCCASIw
85056 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9N
85057 YvDdE3ePYakqtdTyuTFYKTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQv
85058 KUmi8wUG+7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveGHtya
85059 KhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6PIzdezKKqdfcYbwnT
85060 rqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M733WB2+Y8a+xwXrXgTW4qhe04MsC
85061 AwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHkYb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAP
85062 BgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/s
85063 Px+EnWVUXKgWAkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I
85064 aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5mxRZNTZPz/OO
85065 Xl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsaXRik7r4EW5nVcV9VZWRi1aKb
85066 BFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZqxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAK
85067 poRq0Tl9
85068 -----END CERTIFICATE-----
85069
85070 D-TRUST Root Class 3 CA 2 2009
85071 ==============================
85072 -----BEGIN CERTIFICATE-----
85073 MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQK
85074 DAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTAe
85075 Fw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NThaME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxE
85076 LVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIw
85077 DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOAD
85078 ER03UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42tSHKXzlA
85079 BF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9RySPocq60vFYJfxLLHLGv
85080 KZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsMlFqVlNpQmvH/pStmMaTJOKDfHR+4CS7z
85081 p+hnUquVH+BGPtikw8paxTGA6Eian5Rp/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUC
85082 AwEAAaOCARowggEWMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ
85083 4PGEMA4GA1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVjdG9y
85084 eS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUyMENBJTIwMiUyMDIw
85085 MDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwQ6BBoD+G
85086 PWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3JsL2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAw
85087 OS5jcmwwDQYJKoZIhvcNAQELBQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm
85088 2H6NMLVwMeniacfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
85089 o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4KzCUqNQT4YJEV
85090 dT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8PIWmawomDeCTmGCufsYkl4ph
85091 X5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3YJohw1+qRzT65ysCQblrGXnRl11z+o+I=
85092 -----END CERTIFICATE-----
85093
85094 D-TRUST Root Class 3 CA 2 EV 2009
85095 =================================
85096 -----BEGIN CERTIFICATE-----
85097 MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
85098 DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
85099 OTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUwNDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQK
85100 DAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAw
85101 OTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfS
85102 egpnljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM03TP1YtHh
85103 zRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6ZqQTMFexgaDbtCHu39b+T
85104 7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lRp75mpoo6Kr3HGrHhFPC+Oh25z1uxav60
85105 sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure35
85106 11H3a6UCAwEAAaOCASQwggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyv
85107 cop9NteaHNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFwOi8v
85108 ZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xhc3MlMjAzJTIwQ0El
85109 MjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1ERT9jZXJ0aWZpY2F0ZXJldm9jYXRp
85110 b25saXN0MEagRKBChkBodHRwOi8vd3d3LmQtdHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xh
85111 c3NfM19jYV8yX2V2XzIwMDkuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+
85112 PPoeUSbrh/Yp3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05
85113 nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNFCSuGdXzfX2lX
85114 ANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7naxpeG0ILD5EJt/rDiZE4OJudA
85115 NCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqXKVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVv
85116 w9y4AyHqnxbxLFS1
85117 -----END CERTIFICATE-----
85118
85119 PSCProcert
85120 ==========
85121 -----BEGIN CERTIFICATE-----
85122 MIIJhjCCB26gAwIBAgIBCzANBgkqhkiG9w0BAQsFADCCAR4xPjA8BgNVBAMTNUF1dG9yaWRhZCBk
85123 ZSBDZXJ0aWZpY2FjaW9uIFJhaXogZGVsIEVzdGFkbyBWZW5lem9sYW5vMQswCQYDVQQGEwJWRTEQ
85124 MA4GA1UEBxMHQ2FyYWNhczEZMBcGA1UECBMQRGlzdHJpdG8gQ2FwaXRhbDE2MDQGA1UEChMtU2lz
85125 dGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMUMwQQYDVQQLEzpTdXBl
85126 cmludGVuZGVuY2lhIGRlIFNlcnZpY2lvcyBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMSUw
85127 IwYJKoZIhvcNAQkBFhZhY3JhaXpAc3VzY2VydGUuZ29iLnZlMB4XDTEwMTIyODE2NTEwMFoXDTIw
85128 MTIyNTIzNTk1OVowgdExJjAkBgkqhkiG9w0BCQEWF2NvbnRhY3RvQHByb2NlcnQubmV0LnZlMQ8w
85129 DQYDVQQHEwZDaGFjYW8xEDAOBgNVBAgTB01pcmFuZGExKjAoBgNVBAsTIVByb3ZlZWRvciBkZSBD
85130 ZXJ0aWZpY2Fkb3MgUFJPQ0VSVDE2MDQGA1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZp
85131 Y2FjaW9uIEVsZWN0cm9uaWNhMQswCQYDVQQGEwJWRTETMBEGA1UEAxMKUFNDUHJvY2VydDCCAiIw
85132 DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANW39KOUM6FGqVVhSQ2oh3NekS1wwQYalNo97BVC
85133 wfWMrmoX8Yqt/ICV6oNEolt6Vc5Pp6XVurgfoCfAUFM+jbnADrgV3NZs+J74BCXfgI8Qhd19L3uA
85134 3VcAZCP4bsm+lU/hdezgfl6VzbHvvnpC2Mks0+saGiKLt38GieU89RLAu9MLmV+QfI4tL3czkkoh
85135 RqipCKzx9hEC2ZUWno0vluYC3XXCFCpa1sl9JcLB/KpnheLsvtF8PPqv1W7/U0HU9TI4seJfxPmO
85136 EO8GqQKJ/+MMbpfg353bIdD0PghpbNjU5Db4g7ayNo+c7zo3Fn2/omnXO1ty0K+qP1xmk6wKImG2
85137 0qCZyFSTXai20b1dCl53lKItwIKOvMoDKjSuc/HUtQy9vmebVOvh+qBa7Dh+PsHMosdEMXXqP+UH
85138 0quhJZb25uSgXTcYOWEAM11G1ADEtMo88aKjPvM6/2kwLkDd9p+cJsmWN63nOaK/6mnbVSKVUyqU
85139 td+tFjiBdWbjxywbk5yqjKPK2Ww8F22c3HxT4CAnQzb5EuE8XL1mv6JpIzi4mWCZDlZTOpx+FIyw
85140 Bm/xhnaQr/2v/pDGj59/i5IjnOcVdo/Vi5QTcmn7K2FjiO/mpF7moxdqWEfLcU8UC17IAggmosvp
85141 r2uKGcfLFFb14dq12fy/czja+eevbqQ34gcnAgMBAAGjggMXMIIDEzASBgNVHRMBAf8ECDAGAQH/
85142 AgEBMDcGA1UdEgQwMC6CD3N1c2NlcnRlLmdvYi52ZaAbBgVghl4CAqASDBBSSUYtRy0yMDAwNDAz
85143 Ni0wMB0GA1UdDgQWBBRBDxk4qpl/Qguk1yeYVKIXTC1RVDCCAVAGA1UdIwSCAUcwggFDgBStuyId
85144 xuDSAaj9dlBSk+2YwU2u06GCASakggEiMIIBHjE+MDwGA1UEAxM1QXV0b3JpZGFkIGRlIENlcnRp
85145 ZmljYWNpb24gUmFpeiBkZWwgRXN0YWRvIFZlbmV6b2xhbm8xCzAJBgNVBAYTAlZFMRAwDgYDVQQH
85146 EwdDYXJhY2FzMRkwFwYDVQQIExBEaXN0cml0byBDYXBpdGFsMTYwNAYDVQQKEy1TaXN0ZW1hIE5h
85147 Y2lvbmFsIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExQzBBBgNVBAsTOlN1cGVyaW50ZW5k
85148 ZW5jaWEgZGUgU2VydmljaW9zIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExJTAjBgkqhkiG
85149 9w0BCQEWFmFjcmFpekBzdXNjZXJ0ZS5nb2IudmWCAQowDgYDVR0PAQH/BAQDAgEGME0GA1UdEQRG
85150 MESCDnByb2NlcnQubmV0LnZloBUGBWCGXgIBoAwMClBTQy0wMDAwMDKgGwYFYIZeAgKgEgwQUklG
85151 LUotMzE2MzUzNzMtNzB2BgNVHR8EbzBtMEagRKBChkBodHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52
85152 ZS9sY3IvQ0VSVElGSUNBRE8tUkFJWi1TSEEzODRDUkxERVIuY3JsMCOgIaAfhh1sZGFwOi8vYWNy
85153 YWl6LnN1c2NlcnRlLmdvYi52ZTA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHA6Ly9v
85154 Y3NwLnN1c2NlcnRlLmdvYi52ZTBBBgNVHSAEOjA4MDYGBmCGXgMBAjAsMCoGCCsGAQUFBwIBFh5o
85155 dHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52ZS9kcGMwDQYJKoZIhvcNAQELBQADggIBACtZ6yKZu4Sq
85156 T96QxtGGcSOeSwORR3C7wJJg7ODU523G0+1ng3dS1fLld6c2suNUvtm7CpsR72H0xpkzmfWvADmN
85157 g7+mvTV+LFwxNG9s2/NkAZiqlCxB3RWGymspThbASfzXg0gTB1GEMVKIu4YXx2sviiCtxQuPcD4q
85158 uxtxj7mkoP3YldmvWb8lK5jpY5MvYB7Eqvh39YtsL+1+LrVPQA3uvFd359m21D+VJzog1eWuq2w1
85159 n8GhHVnchIHuTQfiSLaeS5UtQbHh6N5+LwUeaO6/u5BlOsju6rEYNxxik6SgMexxbJHmpHmJWhSn
85160 FFAFTKQAVzAswbVhltw+HoSvOULP5dAssSS830DD7X9jSr3hTxJkhpXzsOfIt+FTvZLm8wyWuevo
85161 5pLtp4EJFAv8lXrPj9Y0TzYS3F7RNHXGRoAvlQSMx4bEqCaJqD8Zm4G7UaRKhqsLEQ+xrmNTbSjq
85162 3TNWOByyrYDT13K9mmyZY+gAu0F2BbdbmRiKw7gSXFbPVgx96OLP7bx0R/vu0xdOIk9W/1DzLuY5
85163 poLWccret9W6aAjtmcz9opLLabid+Qqkpj5PkygqYWwHJgD/ll9ohri4zspV4KuxPX+Y1zMOWj3Y
85164 eMLEYC/HYvBhkdI4sPaeVdtAgAUSM84dkpvRabP/v/GSCmE1P93+hvS84Bpxs2Km
85165 -----END CERTIFICATE-----
85166
85167 China Internet Network Information Center EV Certificates Root
85168 ==============================================================
85169 -----BEGIN CERTIFICATE-----
85170 MIID9zCCAt+gAwIBAgIESJ8AATANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMCQ04xMjAwBgNV
85171 BAoMKUNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyMUcwRQYDVQQDDD5D
85172 aGluYSBJbnRlcm5ldCBOZXR3b3JrIEluZm9ybWF0aW9uIENlbnRlciBFViBDZXJ0aWZpY2F0ZXMg
85173 Um9vdDAeFw0xMDA4MzEwNzExMjVaFw0zMDA4MzEwNzExMjVaMIGKMQswCQYDVQQGEwJDTjEyMDAG
85174 A1UECgwpQ2hpbmEgSW50ZXJuZXQgTmV0d29yayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMM
85175 PkNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRpZmljYXRl
85176 cyBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm35z7r07eKpkQ0H1UN+U8i6y
85177 jUqORlTSIRLIOTJCBumD1Z9S7eVnAztUwYyZmczpwA//DdmEEbK40ctb3B75aDFk4Zv6dOtouSCV
85178 98YPjUesWgbdYavi7NifFy2cyjw1l1VxzUOFsUcW9SxTgHbP0wBkvUCZ3czY28Sf1hNfQYOL+Q2H
85179 klY0bBoQCxfVWhyXWIQ8hBouXJE0bhlffxdpxWXvayHG1VA6v2G5BY3vbzQ6sm8UY78WO5upKv23
85180 KzhmBsUs4qpnHkWnjQRmQvaPK++IIGmPMowUc9orhpFjIpryp9vOiYurXccUwVswah+xt54ugQEC
85181 7c+WXmPbqOY4twIDAQABo2MwYTAfBgNVHSMEGDAWgBR8cks5x8DbYqVPm6oYNJKiyoOCWTAPBgNV
85182 HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUfHJLOcfA22KlT5uqGDSSosqD
85183 glkwDQYJKoZIhvcNAQEFBQADggEBACrDx0M3j92tpLIM7twUbY8opJhJywyA6vPtI2Z1fcXTIWd5
85184 0XPFtQO3WKwMVC/GVhMPMdoG52U7HW8228gd+f2ABsqjPWYWqJ1MFn3AlUa1UeTiH9fqBk1jjZaM
85185 7+czV0I664zBechNdn3e9rG3geCg+aF4RhcaVpjwTj2rHO3sOdwHSPdj/gauwqRcalsyiMXHM4Ws
85186 ZkJHwlgkmeHlPuV1LI5D1l08eB6olYIpUNHRFrrvwb562bTYzB5MRuF3sTGrvSrIzo9uoV1/A3U0
85187 5K2JRVRevq4opbs/eHnrc7MKDf2+yfdWrPa37S+bISnHOLaVxATywy39FCqQmbkHzJ8=
85188 -----END CERTIFICATE-----
85189
85190 Swisscom Root CA 2
85191 ==================
85192 -----BEGIN CERTIFICATE-----
85193 MIIF2TCCA8GgAwIBAgIQHp4o6Ejy5e/DfEoeWhhntjANBgkqhkiG9w0BAQsFADBkMQswCQYDVQQG
85194 EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy
85195 dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMjAeFw0xMTA2MjQwODM4MTRaFw0zMTA2
85196 MjUwNzM4MTRaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln
85197 aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAyMIIC
85198 IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlUJOhJ1R5tMJ6HJaI2nbeHCOFvErjw0DzpPM
85199 LgAIe6szjPTpQOYXTKueuEcUMncy3SgM3hhLX3af+Dk7/E6J2HzFZ++r0rk0X2s682Q2zsKwzxNo
85200 ysjL67XiPS4h3+os1OD5cJZM/2pYmLcX5BtS5X4HAB1f2uY+lQS3aYg5oUFgJWFLlTloYhyxCwWJ
85201 wDaCFCE/rtuh/bxvHGCGtlOUSbkrRsVPACu/obvLP+DHVxxX6NZp+MEkUp2IVd3Chy50I9AU/SpH
85202 Wrumnf2U5NGKpV+GY3aFy6//SSj8gO1MedK75MDvAe5QQQg1I3ArqRa0jG6F6bYRzzHdUyYb3y1a
85203 SgJA/MTAtukxGggo5WDDH8SQjhBiYEQN7Aq+VRhxLKX0srwVYv8c474d2h5Xszx+zYIdkeNL6yxS
85204 NLCK/RJOlrDrcH+eOfdmQrGrrFLadkBXeyq96G4DsguAhYidDMfCd7Camlf0uPoTXGiTOmekl9Ab
85205 mbeGMktg2M7v0Ax/lZ9vh0+Hio5fCHyqW/xavqGRn1V9TrALacywlKinh/LTSlDcX3KwFnUey7QY
85206 Ypqwpzmqm59m2I2mbJYV4+by+PGDYmy7Velhk6M99bFXi08jsJvllGov34zflVEpYKELKeRcVVi3
85207 qPyZ7iVNTA6z00yPhOgpD/0QVAKFyPnlw4vP5w8CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw
85208 HQYDVR0hBBYwFDASBgdghXQBUwIBBgdghXQBUwIBMBIGA1UdEwEB/wQIMAYBAf8CAQcwHQYDVR0O
85209 BBYEFE0mICKJS9PVpAqhb97iEoHF8TwuMB8GA1UdIwQYMBaAFE0mICKJS9PVpAqhb97iEoHF8Twu
85210 MA0GCSqGSIb3DQEBCwUAA4ICAQAyCrKkG8t9voJXiblqf/P0wS4RfbgZPnm3qKhyN2abGu2sEzsO
85211 v2LwnN+ee6FTSA5BesogpxcbtnjsQJHzQq0Qw1zv/2BZf82Fo4s9SBwlAjxnffUy6S8w5X2lejjQ
85212 82YqZh6NM4OKb3xuqFp1mrjX2lhIREeoTPpMSQpKwhI3qEAMw8jh0FcNlzKVxzqfl9NX+Ave5XLz
85213 o9v/tdhZsnPdTSpxsrpJ9csc1fV5yJmz/MFMdOO0vSk3FQQoHt5FRnDsr7p4DooqzgB53MBfGWcs
85214 a0vvaGgLQ+OswWIJ76bdZWGgr4RVSJFSHMYlkSrQwSIjYVmvRRGFHQEkNI/Ps/8XciATwoCqISxx
85215 OQ7Qj1zB09GOInJGTB2Wrk9xseEFKZZZ9LuedT3PDTcNYtsmjGOpI99nBjx8Oto0QuFmtEYE3saW
85216 mA9LSHokMnWRn6z3aOkquVVlzl1h0ydw2Df+n7mvoC5Wt6NlUe07qxS/TFED6F+KBZvuim6c779o
85217 +sjaC+NCydAXFJy3SuCvkychVSa1ZC+N8f+mQAWFBVzKBxlcCxMoTFh/wqXvRdpg065lYZ1Tg3TC
85218 rvJcwhbtkj6EPnNgiLx29CzP0H1907he0ZESEOnN3col49XtmS++dYFLJPlFRpTJKSFTnCZFqhMX
85219 5OfNeOI5wSsSnqaeG8XmDtkx2Q==
85220 -----END CERTIFICATE-----
85221
85222 Swisscom Root EV CA 2
85223 =====================
85224 -----BEGIN CERTIFICATE-----
85225 MIIF4DCCA8igAwIBAgIRAPL6ZOJ0Y9ON/RAdBB92ylgwDQYJKoZIhvcNAQELBQAwZzELMAkGA1UE
85226 BhMCY2gxETAPBgNVBAoTCFN3aXNzY29tMSUwIwYDVQQLExxEaWdpdGFsIENlcnRpZmljYXRlIFNl
85227 cnZpY2VzMR4wHAYDVQQDExVTd2lzc2NvbSBSb290IEVWIENBIDIwHhcNMTEwNjI0MDk0NTA4WhcN
85228 MzEwNjI1MDg0NTA4WjBnMQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsT
85229 HERpZ2l0YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxHjAcBgNVBAMTFVN3aXNzY29tIFJvb3QgRVYg
85230 Q0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMT3HS9X6lds93BdY7BxUglgRCgz
85231 o3pOCvrY6myLURYaVa5UJsTMRQdBTxB5f3HSek4/OE6zAMaVylvNwSqD1ycfMQ4jFrclyxy0uYAy
85232 Xhqdk/HoPGAsp15XGVhRXrwsVgu42O+LgrQ8uMIkqBPHoCE2G3pXKSinLr9xJZDzRINpUKTk4Rti
85233 GZQJo/PDvO/0vezbE53PnUgJUmfANykRHvvSEaeFGHR55E+FFOtSN+KxRdjMDUN/rhPSays/p8Li
85234 qG12W0OfvrSdsyaGOx9/5fLoZigWJdBLlzin5M8J0TbDC77aO0RYjb7xnglrPvMyxyuHxuxenPaH
85235 Za0zKcQvidm5y8kDnftslFGXEBuGCxobP/YCfnvUxVFkKJ3106yDgYjTdLRZncHrYTNaRdHLOdAG
85236 alNgHa/2+2m8atwBz735j9m9W8E6X47aD0upm50qKGsaCnw8qyIL5XctcfaCNYGu+HuB5ur+rPQa
85237 m3Rc6I8k9l2dRsQs0h4rIWqDJ2dVSqTjyDKXZpBy2uPUZC5f46Fq9mDU5zXNysRojddxyNMkM3Ox
85238 bPlq4SjbX8Y96L5V5jcb7STZDxmPX2MYWFCBUWVv8p9+agTnNCRxunZLWB4ZvRVgRaoMEkABnRDi
85239 xzgHcgplwLa7JSnaFp6LNYth7eVxV4O1PHGf40+/fh6Bn0GXAgMBAAGjgYYwgYMwDgYDVR0PAQH/
85240 BAQDAgGGMB0GA1UdIQQWMBQwEgYHYIV0AVMCAgYHYIV0AVMCAjASBgNVHRMBAf8ECDAGAQH/AgED
85241 MB0GA1UdDgQWBBRF2aWBbj2ITY1x0kbBbkUe88SAnTAfBgNVHSMEGDAWgBRF2aWBbj2ITY1x0kbB
85242 bkUe88SAnTANBgkqhkiG9w0BAQsFAAOCAgEAlDpzBp9SSzBc1P6xXCX5145v9Ydkn+0UjrgEjihL
85243 j6p7jjm02Vj2e6E1CqGdivdj5eu9OYLU43otb98TPLr+flaYC/NUn81ETm484T4VvwYmneTwkLbU
85244 wp4wLh/vx3rEUMfqe9pQy3omywC0Wqu1kx+AiYQElY2NfwmTv9SoqORjbdlk5LgpWgi/UOGED1V7
85245 XwgiG/W9mR4U9s70WBCCswo9GcG/W6uqmdjyMb3lOGbcWAXH7WMaLgqXfIeTK7KK4/HsGOV1timH
85246 59yLGn602MnTihdsfSlEvoqq9X46Lmgxk7lq2prg2+kupYTNHAq4Sgj5nPFhJpiTt3tm7JFe3VE/
85247 23MPrQRYCd0EApUKPtN236YQHoA96M2kZNEzx5LH4k5E4wnJTsJdhw4Snr8PyQUQ3nqjsTzyP6Wq
85248 J3mtMX0f/fwZacXduT98zca0wjAefm6S139hdlqP65VNvBFuIXxZN5nQBrz5Bm0yFqXZaajh3DyA
85249 HmBR3NdUIR7KYndP+tiPsys6DXhyyWhBWkdKwqPrGtcKqzwyVcgKEZzfdNbwQBUdyLmPtTbFr/gi
85250 uMod89a2GQ+fYWVq6nTIfI/DT11lgh/ZDYnadXL77/FHZxOzyNEZiCcmmpl5fx7kLD977vHeTYuW
85251 l8PVP3wbI+2ksx0WckNLIOFZfsLorSa/ovc=
85252 -----END CERTIFICATE-----
85253
85254 CA Disig Root R1
85255 ================
85256 -----BEGIN CERTIFICATE-----
85257 MIIFaTCCA1GgAwIBAgIJAMMDmu5QkG4oMA0GCSqGSIb3DQEBBQUAMFIxCzAJBgNVBAYTAlNLMRMw
85258 EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp
85259 ZyBSb290IFIxMB4XDTEyMDcxOTA5MDY1NloXDTQyMDcxOTA5MDY1NlowUjELMAkGA1UEBhMCU0sx
85260 EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp
85261 c2lnIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCqw3j33Jijp1pedxiy
85262 3QRkD2P9m5YJgNXoqqXinCaUOuiZc4yd39ffg/N4T0Dhf9Kn0uXKE5Pn7cZ3Xza1lK/oOI7bm+V8
85263 u8yN63Vz4STN5qctGS7Y1oprFOsIYgrY3LMATcMjfF9DCCMyEtztDK3AfQ+lekLZWnDZv6fXARz2
85264 m6uOt0qGeKAeVjGu74IKgEH3G8muqzIm1Cxr7X1r5OJeIgpFy4QxTaz+29FHuvlglzmxZcfe+5nk
85265 CiKxLU3lSCZpq+Kq8/v8kiky6bM+TR8noc2OuRf7JT7JbvN32g0S9l3HuzYQ1VTW8+DiR0jm3hTa
85266 YVKvJrT1cU/J19IG32PK/yHoWQbgCNWEFVP3Q+V8xaCJmGtzxmjOZd69fwX3se72V6FglcXM6pM6
85267 vpmumwKjrckWtc7dXpl4fho5frLABaTAgqWjR56M6ly2vGfb5ipN0gTco65F97yLnByn1tUD3AjL
85268 LhbKXEAz6GfDLuemROoRRRw1ZS0eRWEkG4IupZ0zXWX4Qfkuy5Q/H6MMMSRE7cderVC6xkGbrPAX
85269 ZcD4XW9boAo0PO7X6oifmPmvTiT6l7Jkdtqr9O3jw2Dv1fkCyC2fg69naQanMVXVz0tv/wQFx1is
85270 XxYb5dKj6zHbHzMVTdDypVP1y+E9Tmgt2BLdqvLmTZtJ5cUoobqwWsagtQIDAQABo0IwQDAPBgNV
85271 HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUiQq0OJMa5qvum5EY+fU8PjXQ
85272 04IwDQYJKoZIhvcNAQEFBQADggIBADKL9p1Kyb4U5YysOMo6CdQbzoaz3evUuii+Eq5FLAR0rBNR
85273 xVgYZk2C2tXck8An4b58n1KeElb21Zyp9HWc+jcSjxyT7Ff+Bw+r1RL3D65hXlaASfX8MPWbTx9B
85274 LxyE04nH4toCdu0Jz2zBuByDHBb6lM19oMgY0sidbvW9adRtPTXoHqJPYNcHKfyyo6SdbhWSVhlM
85275 CrDpfNIZTUJG7L399ldb3Zh+pE3McgODWF3vkzpBemOqfDqo9ayk0d2iLbYq/J8BjuIQscTK5Gfb
85276 VSUZP/3oNn6z4eGBrxEWi1CXYBmCAMBrTXO40RMHPuq2MU/wQppt4hF05ZSsjYSVPCGvxdpHyN85
85277 YmLLW1AL14FABZyb7bq2ix4Eb5YgOe2kfSnbSM6C3NQCjR0EMVrHS/BsYVLXtFHCgWzN4funodKS
85278 ds+xDzdYpPJScWc/DIh4gInByLUfkmO+p3qKViwaqKactV2zY9ATIKHrkWzQjX2v3wvkF7mGnjix
85279 lAxYjOBVqjtjbZqJYLhkKpLGN/R+Q0O3c+gB53+XD9fyexn9GtePyfqFa3qdnom2piiZk4hA9z7N
85280 UaPK6u95RyG1/jLix8NRb76AdPCkwzryT+lf3xkK8jsTQ6wxpLPn6/wY1gGp8yqPNg7rtLG8t0zJ
85281 a7+h89n07eLw4+1knj0vllJPgFOL
85282 -----END CERTIFICATE-----
85283
85284 CA Disig Root R2
85285 ================
85286 -----BEGIN CERTIFICATE-----
85287 MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNVBAYTAlNLMRMw
85288 EQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMuMRkwFwYDVQQDExBDQSBEaXNp
85289 ZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQyMDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sx
85290 EzARBgNVBAcTCkJyYXRpc2xhdmExEzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERp
85291 c2lnIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbC
85292 w3OeNcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNHPWSb6Wia
85293 xswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3Ix2ymrdMxp7zo5eFm1tL7
85294 A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbeQTg06ov80egEFGEtQX6sx3dOy1FU+16S
85295 GBsEWmjGycT6txOgmLcRK7fWV8x8nhfRyyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqV
85296 g8NTEQxzHQuyRpDRQjrOQG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa
85297 5Beny912H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJQfYE
85298 koopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUDi/ZnWejBBhG93c+A
85299 Ak9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORsnLMOPReisjQS1n6yqEm70XooQL6i
85300 Fh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNV
85301 HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5u
85302 Qu0wDQYJKoZIhvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM
85303 tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqfGopTpti72TVV
85304 sRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkblvdhuDvEK7Z4bLQjb/D907Je
85305 dR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka+elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W8
85306 1k/BfDxujRNt+3vrMNDcTa/F1balTFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjx
85307 mHHEt38OFdAlab0inSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01
85308 utI3gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18DrG5gPcFw0
85309 sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3OszMOl6W8KjptlwlCFtaOg
85310 UxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8xL4ysEr3vQCj8KWefshNPZiTEUxnpHikV
85311 7+ZtsH8tZ/3zbBt1RqPlShfppNcL
85312 -----END CERTIFICATE-----
85313
85314 ACCVRAIZ1
85315 =========
85316 -----BEGIN CERTIFICATE-----
85317 MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UEAwwJQUNDVlJB
85318 SVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQswCQYDVQQGEwJFUzAeFw0xMTA1
85319 MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQBgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwH
85320 UEtJQUNDVjENMAsGA1UECgwEQUNDVjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
85321 DwAwggIKAoICAQCbqau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gM
85322 jmoYHtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWoG2ioPej0
85323 RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpAlHPrzg5XPAOBOp0KoVdD
85324 aaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhrIA8wKFSVf+DuzgpmndFALW4ir50awQUZ
85325 0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDG
85326 WuzndN9wrqODJerWx5eHk6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs7
85327 8yM2x/474KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMOm3WR
85328 5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpacXpkatcnYGMN285J
85329 9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPluUsXQA+xtrn13k/c4LOsOxFwYIRK
85330 Q26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYIKwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRw
85331 Oi8vd3d3LmFjY3YuZXMvZmlsZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEu
85332 Y3J0MB8GCCsGAQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2
85333 VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeTVfZW6oHlNsyM
85334 Hj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIGCCsGAQUFBwICMIIBFB6CARAA
85335 QQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUAcgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBh
85336 AO0AegAgAGQAZQAgAGwAYQAgAEEAQwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUA
85337 YwBuAG8AbABvAGcA7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBj
85338 AHQAcgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAAQwBQAFMA
85339 IABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUAczAwBggrBgEFBQcCARYk
85340 aHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2MuaHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0
85341 dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRtaW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2
85342 MV9kZXIuY3JsMA4GA1UdDwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZI
85343 hvcNAQEFBQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdpD70E
85344 R9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gUJyCpZET/LtZ1qmxN
85345 YEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+mAM/EKXMRNt6GGT6d7hmKG9Ww7Y49
85346 nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepDvV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJ
85347 TS+xJlsndQAJxGJ3KQhfnlmstn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3
85348 sCPdK6jT2iWH7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h
85349 I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szAh1xA2syVP1Xg
85350 Nce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xFd3+YJ5oyXSrjhO7FmGYvliAd
85351 3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2HpPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3p
85352 EfbRD0tVNEYqi4Y7
85353 -----END CERTIFICATE-----
85354
85355 TWCA Global Root CA
85356 ===================
85357 -----BEGIN CERTIFICATE-----
85358 MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcxEjAQBgNVBAoT
85359 CVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMTVFdDQSBHbG9iYWwgUm9vdCBD
85360 QTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQK
85361 EwlUQUlXQU4tQ0ExEDAOBgNVBAsTB1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3Qg
85362 Q0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2C
85363 nJfF10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz0ALfUPZV
85364 r2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfChMBwqoJimFb3u/Rk28OKR
85365 Q4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbHzIh1HrtsBv+baz4X7GGqcXzGHaL3SekV
85366 tTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1W
85367 KKD+u4ZqyPpcC1jcxkt2yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99
85368 sy2sbZCilaLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYPoA/p
85369 yJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQABDzfuBSO6N+pjWxn
85370 kjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcEqYSjMq+u7msXi7Kx/mzhkIyIqJdI
85371 zshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMC
85372 AQYwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6g
85373 cFGn90xHNcgL1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn
85374 LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WFH6vPNOw/KP4M
85375 8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNoRI2T9GRwoD2dKAXDOXC4Ynsg
85376 /eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlg
85377 lPx4mI88k1HtQJAH32RjJMtOcQWh15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryP
85378 A9gK8kxkRr05YuWW6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3m
85379 i4TWnsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5jwa19hAM8
85380 EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWzaGHQRiapIVJpLesux+t3
85381 zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmyKwbQBM0=
85382 -----END CERTIFICATE-----
85383
85384 TeliaSonera Root CA v1
85385 ======================
85386 -----BEGIN CERTIFICATE-----
85387 MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAwNzEUMBIGA1UE
85388 CgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJvb3QgQ0EgdjEwHhcNMDcxMDE4
85389 MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYDVQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwW
85390 VGVsaWFTb25lcmEgUm9vdCBDQSB2MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+
85391 6yfwIaPzaSZVfp3FVRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA
85392 3GV17CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+XZ75Ljo1k
85393 B1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+/jXh7VB7qTCNGdMJjmhn
85394 Xb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxH
85395 oLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkmdtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3
85396 F0fUTPHSiXk+TT2YqGHeOh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJ
85397 oWjiUIMusDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4pgd7
85398 gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fsslESl1MpWtTwEhDc
85399 TwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQarMCpgKIv7NHfirZ1fpoeDVNAgMB
85400 AAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qW
85401 DNXr+nuqF+gTEjANBgkqhkiG9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNm
85402 zqjMDfz1mgbldxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx
85403 0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1TjTQpgcmLNkQfW
85404 pb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBedY2gea+zDTYa4EzAvXUYNR0PV
85405 G6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpc
85406 c41teyWRyu5FrgZLAMzTsVlQ2jqIOylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOT
85407 JsjrDNYmiLbAJM+7vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2
85408 qReWt88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcnHL/EVlP6
85409 Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVxSK236thZiNSQvxaz2ems
85410 WWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
85411 -----END CERTIFICATE-----
85412
85413 E-Tugra Certification Authority
85414 ===============================
85415 -----BEGIN CERTIFICATE-----
85416 MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNVBAYTAlRSMQ8w
85417 DQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamls
85418 ZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN
85419 ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMw
85420 NTEyMDk0OFoXDTIzMDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmEx
85421 QDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxl
85422 cmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQD
85423 DB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
85424 MIICCgKCAgEA4vU/kwVRHoViVF56C/UYB4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vd
85425 hQd2h8y/L5VMzH2nPbxHD5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5K
85426 CKpbknSFQ9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEoq1+g
85427 ElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3Dk14opz8n8Y4e0ypQ
85428 BaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcHfC425lAcP9tDJMW/hkd5s3kc91r0
85429 E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsutdEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gz
85430 rt48Ue7LE3wBf4QOXVGUnhMMti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAq
85431 jqFGOjGY5RH8zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn
85432 rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUXU8u3Zg5mTPj5
85433 dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6Jyr+zE7S6E5UMA8GA1UdEwEB
85434 /wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEG
85435 MA0GCSqGSIb3DQEBCwUAA4ICAQAFNzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAK
85436 kEh47U6YA5n+KGCRHTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jO
85437 XKqYGwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c77NCR807
85438 VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3+GbHeJAAFS6LrVE1Uweo
85439 a2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WKvJUawSg5TB9D0pH0clmKuVb8P7Sd2nCc
85440 dlqMQ1DujjByTd//SffGqWfZbawCEeI6FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEV
85441 KV0jq9BgoRJP3vQXzTLlyb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gT
85442 Dx4JnW2PAJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpDy4Q0
85443 8ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8dNL/+I5c30jn6PQ0G
85444 C7TbO6Orb1wdtn7os4I07QZcJA==
85445 -----END CERTIFICATE-----
85446
85447 T-TeleSec GlobalRoot Class 2
85448 ============================
85449 -----BEGIN CERTIFICATE-----
85450 MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
85451 IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
85452 cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgx
85453 MDAxMTA0MDE0WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
85454 dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
85455 ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0GCSqGSIb3
85456 DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUdAqSzm1nzHoqvNK38DcLZ
85457 SBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiCFoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/F
85458 vudocP05l03Sx5iRUKrERLMjfTlH6VJi1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx970
85459 2cu+fjOlbpSD8DT6IavqjnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGV
85460 WOHAD3bZwI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGjQjBA
85461 MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/WSA2AHmgoCJrjNXy
85462 YdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhyNsZt+U2e+iKo4YFWz827n+qrkRk4
85463 r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPACuvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNf
85464 vNoBYimipidx5joifsFvHZVwIEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR
85465 3p1m0IvVVGb6g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN
85466 9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlPBSeOE6Fuwg==
85467 -----END CERTIFICATE-----
85468
85469 Atos TrustedRoot 2011
85470 =====================
85471 -----BEGIN CERTIFICATE-----
85472 MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UEAwwVQXRvcyBU
85473 cnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0xMTA3MDcxNDU4
85474 MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMMFUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsG
85475 A1UECgwEQXRvczELMAkGA1UEBhMCREUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCV
85476 hTuXbyo7LjvPpvMpNb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr
85477 54rMVD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+SZFhyBH+
85478 DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ4J7sVaE3IqKHBAUsR320
85479 HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0Lcp2AMBYHlT8oDv3FdU9T1nSatCQujgKR
85480 z3bFmx5VdJx4IbHwLfELn8LVlhgf8FQieowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7R
85481 l+lwrrw7GWzbITAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZ
85482 bNshMBgGA1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
85483 CwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8jvZfza1zv7v1Apt+h
85484 k6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kPDpFrdRbhIfzYJsdHt6bPWHJxfrrh
85485 TZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pcmaHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a9
85486 61qn8FYiqTxlVMYVqL2Gns2Dlmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G
85487 3mB/ufNPRJLvKrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
85488 -----END CERTIFICATE-----
85489
85490 QuoVadis Root CA 1 G3
85491 =====================
85492 -----BEGIN CERTIFICATE-----
85493 MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQELBQAwSDELMAkG
85494 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
85495 b3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJN
85496 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEg
85497 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakE
85498 PBtVwedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWerNrwU8lm
85499 PNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF34168Xfuw6cwI2H44g4hWf6
85500 Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh4Pw5qlPafX7PGglTvF0FBM+hSo+LdoIN
85501 ofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXpUhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/l
85502 g6AnhF4EwfWQvTA9xO+oabw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV
85503 7qJZjqlc3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/GKubX
85504 9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSthfbZxbGL0eUQMk1f
85505 iyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KOTk0k+17kBL5yG6YnLUlamXrXXAkg
85506 t3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOtzCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
85507 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZI
85508 hvcNAQELBQADggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC
85509 MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2cDMT/uFPpiN3
85510 GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUNqXsCHKnQO18LwIE6PWThv6ct
85511 Tr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP
85512 +V04ikkwj+3x6xn0dxoxGE1nVGwvb2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh
85513 3jRJjehZrJ3ydlo28hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fa
85514 wx/kNSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNjZgKAvQU6
85515 O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhpq1467HxpvMc7hU6eFbm0
85516 FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFtnh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOV
85517 hMJKzRwuJIczYOXD
85518 -----END CERTIFICATE-----
85519
85520 QuoVadis Root CA 2 G3
85521 =====================
85522 -----BEGIN CERTIFICATE-----
85523 MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQELBQAwSDELMAkG
85524 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
85525 b3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJN
85526 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIg
85527 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFh
85528 ZiFfqq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMWn4rjyduY
85529 NM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ymc5GQYaYDFCDy54ejiK2t
85530 oIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+o
85531 MiwMzAkd056OXbxMmO7FGmh77FOm6RQ1o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+l
85532 V0POKa2Mq1W/xPtbAd0jIaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZo
85533 L1NesNKqIcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz8eQQ
85534 sSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43ehvNURG3YBZwjgQQvD
85535 6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l7ZizlWNof/k19N+IxWA1ksB8aRxh
85536 lRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALGcC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
85537 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZI
85538 hvcNAQELBQADggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66
85539 AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RCroijQ1h5fq7K
85540 pVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0GaW/ZZGYjeVYg3UQt4XAoeo0L9
85541 x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4nlv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgz
85542 dWqTHBLmYF5vHX/JHyPLhGGfHoJE+V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6X
85543 U/IyAgkwo1jwDQHVcsaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+Nw
85544 mNtddbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNgKCLjsZWD
85545 zYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeMHVOyToV7BjjHLPj4sHKN
85546 JeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4WSr2Rz0ZiC3oheGe7IUIarFsNMkd7Egr
85547 O3jtZsSOeWmD3n+M
85548 -----END CERTIFICATE-----
85549
85550 QuoVadis Root CA 3 G3
85551 =====================
85552 -----BEGIN CERTIFICATE-----
85553 MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQELBQAwSDELMAkG
85554 A1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAcBgNVBAMTFVF1b1ZhZGlzIFJv
85555 b3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJN
85556 MRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMg
85557 RzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286
85558 IxSR/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNuFoM7pmRL
85559 Mon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXRU7Ox7sWTaYI+FrUoRqHe
85560 6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+cra1AdHkrAj80//ogaX3T7mH1urPnMNA3
85561 I4ZyYUUpSFlob3emLoG+B01vr87ERRORFHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3U
85562 VDmrJqMz6nWB2i3ND0/kA9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f7
85563 5li59wzweyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634RylsSqi
85564 Md5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBpVzgeAVuNVejH38DM
85565 dyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0QA4XN8f+MFrXBsj6IbGB/kE+V9/Yt
85566 rQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
85567 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZI
85568 hvcNAQELBQADggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px
85569 KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnIFUBhynLWcKzS
85570 t/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5WvvoxXqA/4Ti2Tk08HS6IT7SdEQ
85571 TXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFgu/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9Du
85572 DcpmvJRPpq3t/O5jrFc/ZSXPsoaP0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGib
85573 Ih6BJpsQBJFxwAYf3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmD
85574 hPbl8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+DhcI00iX
85575 0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HNPlopNLk9hM6xZdRZkZFW
85576 dSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ywaZWWDYWGWVjUTR939+J399roD1B0y2
85577 PpxxVJkES/1Y+Zj0
85578 -----END CERTIFICATE-----
85579
85580 DigiCert Assured ID Root G2
85581 ===========================
85582 -----BEGIN CERTIFICATE-----
85583 MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQG
85584 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
85585 IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgw
85586 MTE1MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
85587 ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIw
85588 ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSAn61UQbVH
85589 35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4HteccbiJVMWWXvdMX0h5i89vq
85590 bFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9HpEgjAALAcKxHad3A2m67OeYfcgnDmCXRw
85591 VWmvo2ifv922ebPynXApVfSr/5Vh88lAbx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OP
85592 YLfykqGxvYmJHzDNw6YuYjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+Rn
85593 lTGNAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTO
85594 w0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPIQW5pJ6d1Ee88hjZv
85595 0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I0jJmwYrA8y8678Dj1JGG0VDjA9tz
85596 d29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4GnilmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAW
85597 hsI6yLETcDbYz+70CjTVW0z9B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0M
85598 jomZmWzwPDCvON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
85599 IhNzbM8m9Yop5w==
85600 -----END CERTIFICATE-----
85601
85602 DigiCert Assured ID Root G3
85603 ===========================
85604 -----BEGIN CERTIFICATE-----
85605 MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQswCQYDVQQGEwJV
85606 UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYD
85607 VQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
85608 MTIwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
85609 d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQ
85610 BgcqhkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJfZn4f5dwb
85611 RXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17QRSAPWXYQ1qAk8C3eNvJs
85612 KTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgF
85613 UaFNN6KDec6NHSrkhDAKBggqhkjOPQQDAwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5Fy
85614 YZ5eEJJZVrmDxxDnOOlYJjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy
85615 1vUhZscv6pZjamVFkpUBtA==
85616 -----END CERTIFICATE-----
85617
85618 DigiCert Global Root G2
85619 =======================
85620 -----BEGIN CERTIFICATE-----
85621 MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQG
85622 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
85623 HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUx
85624 MjAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
85625 dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkq
85626 hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI2/Ou8jqJ
85627 kTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx1x7e/dfgy5SDN67sH0NO
85628 3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQq2EGnI/yuum06ZIya7XzV+hdG82MHauV
85629 BJVJ8zUtluNJbd134/tJS7SsVQepj5WztCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyM
85630 UNGPHgm+F6HmIcr9g+UQvIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQAB
85631 o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV5uNu
85632 5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY1Yl9PMWLSn/pvtsr
85633 F9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4NeF22d+mQrvHRAiGfzZ0JFrabA0U
85634 WTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NGFdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBH
85635 QRFXGU7Aj64GxJUTFy8bJZ918rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/
85636 iyK5S9kJRaTepLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
85637 MrY=
85638 -----END CERTIFICATE-----
85639
85640 DigiCert Global Root G3
85641 =======================
85642 -----BEGIN CERTIFICATE-----
85643 MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQswCQYDVQQGEwJV
85644 UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAwHgYD
85645 VQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAw
85646 MDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5k
85647 aWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0C
85648 AQYFK4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FGfp4tn+6O
85649 YwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPOZ9wj/wMco+I+o0IwQDAP
85650 BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNp
85651 Yim8S8YwCgYIKoZIzj0EAwMDaAAwZQIxAK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y
85652 3maTD/HMsQmP3Wyr+mt/oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34
85653 VOKa5Vt8sycX
85654 -----END CERTIFICATE-----
85655
85656 DigiCert Trusted Root G4
85657 ========================
85658 -----BEGIN CERTIFICATE-----
85659 MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBiMQswCQYDVQQG
85660 EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEw
85661 HwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1
85662 MTIwMDAwWjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
85663 d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0G
85664 CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3yithZwuEp
85665 pz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1Ifxp4VpX6+n6lXFllVcq9o
85666 k3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDVySAdYyktzuxeTsiT+CFhmzTrBcZe7Fsa
85667 vOvJz82sNEBfsXpm7nfISKhmV1efVFiODCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGY
85668 QJB5w3jHtrHEtWoYOAMQjdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6
85669 MUSaM0C/CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCiEhtm
85670 mnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADMfRyVw4/3IbKyEbe7
85671 f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QYuKZ3AeEPlAwhHbJUKSWJbOUOUlFH
85672 dL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXKchYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8
85673 oR7FwI+isX4KJpn15GkvmB0t9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
85674 DwEB/wQEAwIBhjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
85675 ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2SV1EY+CtnJYY
85676 ZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd+SeuMIW59mdNOj6PWTkiU0Tr
85677 yF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWcfFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy
85678 7zBZLq7gcfJW5GqXb5JQbZaNaHqasjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iah
85679 ixTXTBmyUEFxPT9NcCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN
85680 5r5N0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie4u1Ki7wb
85681 /UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mIr/OSmbaz5mEP0oUA51Aa
85682 5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tK
85683 G48BtieVU+i2iW1bvGjUI+iLUaJW+fCmgKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP
85684 82Z+
85685 -----END CERTIFICATE-----
85686
85687 WoSign
85688 ======
85689 -----BEGIN CERTIFICATE-----
85690 MIIFdjCCA16gAwIBAgIQXmjWEXGUY1BWAGjzPsnFkTANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQG
85691 EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxKjAoBgNVBAMTIUNlcnRpZmljYXRpb24g
85692 QXV0aG9yaXR5IG9mIFdvU2lnbjAeFw0wOTA4MDgwMTAwMDFaFw0zOTA4MDgwMTAwMDFaMFUxCzAJ
85693 BgNVBAYTAkNOMRowGAYDVQQKExFXb1NpZ24gQ0EgTGltaXRlZDEqMCgGA1UEAxMhQ2VydGlmaWNh
85694 dGlvbiBBdXRob3JpdHkgb2YgV29TaWduMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA
85695 vcqNrLiRFVaXe2tcesLea9mhsMMQI/qnobLMMfo+2aYpbxY94Gv4uEBf2zmoAHqLoE1UfcIiePyO
85696 CbiohdfMlZdLdNiefvAA5A6JrkkoRBoQmTIPJYhTpA2zDxIIFgsDcSccf+Hb0v1naMQFXQoOXXDX
85697 2JegvFNBmpGN9J42Znp+VsGQX+axaCA2pIwkLCxHC1l2ZjC1vt7tj/id07sBMOby8w7gLJKA84X5
85698 KIq0VC6a7fd2/BVoFutKbOsuEo/Uz/4Mx1wdC34FMr5esAkqQtXJTpCzWQ27en7N1QhatH/YHGkR
85699 +ScPewavVIMYe+HdVHpRaG53/Ma/UkpmRqGyZxq7o093oL5d//xWC0Nyd5DKnvnyOfUNqfTq1+ez
85700 EC8wQjchzDBwyYaYD8xYTYO7feUapTeNtqwylwA6Y3EkHp43xP901DfA4v6IRmAR3Qg/UDaruHqk
85701 lWJqbrDKaiFaafPz+x1wOZXzp26mgYmhiMU7ccqjUu6Du/2gd/Tkb+dC221KmYo0SLwX3OSACCK2
85702 8jHAPwQ+658geda4BmRkAjHXqc1S+4RFaQkAKtxVi8QGRkvASh0JWzko/amrzgD5LkhLJuYwTKVY
85703 yrREgk/nkR4zw7CT/xH8gdLKH3Ep3XZPkiWvHYG3Dy+MwwbMLyejSuQOmbp8HkUff6oZRZb9/D0C
85704 AwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFOFmzw7R
85705 8bNLtwYgFP6HEtX2/vs+MA0GCSqGSIb3DQEBBQUAA4ICAQCoy3JAsnbBfnv8rWTjMnvMPLZdRtP1
85706 LOJwXcgu2AZ9mNELIaCJWSQBnfmvCX0KI4I01fx8cpm5o9dU9OpScA7F9dY74ToJMuYhOZO9sxXq
85707 T2r09Ys/L3yNWC7F4TmgPsc9SnOeQHrAK2GpZ8nzJLmzbVUsWh2eJXLOC62qx1ViC777Y7NhRCOj
85708 y+EaDveaBk3e1CNOIZZbOVtXHS9dCF4Jef98l7VNg64N1uajeeAz0JmWAjCnPv/So0M/BVoG6kQC
85709 2nz4SNAzqfkHx5Xh9T71XXG68pWpdIhhWeO/yloTunK0jF02h+mmxTwTv97QRCbut+wucPrXnbes
85710 5cVAWubXbHssw1abR80LzvobtCHXt2a49CUwi1wNuepnsvRtrtWhnk/Yn+knArAdBtaP4/tIEp9/
85711 EaEQPkxROpaw0RPxx9gmrjrKkcRpnd8BKWRRb2jaFOwIQZeQjdCygPLPwj2/kWjFgGcexGATVdVh
85712 mVd8upUPYUk6ynW8yQqTP2cOEvIo4jEbwFcW3wh8GcF+Dx+FHgo2fFt+J7x6v+Db9NpSvd4MVHAx
85713 kUOVyLzwPt0JfjBkUO1/AaQzZ01oT74V77D2AhGiGxMlOtzCWfHjXEa7ZywCRuoeSKbmW9m1vFGi
85714 kpbbqsY3Iqb+zCB0oy2pLmvLwIIRIbWTee5Ehr7XHuQe+w==
85715 -----END CERTIFICATE-----
85716
85717 WoSign China
85718 ============
85719 -----BEGIN CERTIFICATE-----
85720 MIIFWDCCA0CgAwIBAgIQUHBrzdgT/BtOOzNy0hFIjTANBgkqhkiG9w0BAQsFADBGMQswCQYDVQQG
85721 EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxGzAZBgNVBAMMEkNBIOayg+mAmuagueiv
85722 geS5pjAeFw0wOTA4MDgwMTAwMDFaFw0zOTA4MDgwMTAwMDFaMEYxCzAJBgNVBAYTAkNOMRowGAYD
85723 VQQKExFXb1NpZ24gQ0EgTGltaXRlZDEbMBkGA1UEAwwSQ0Eg5rKD6YCa5qC56K+B5LmmMIICIjAN
85724 BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0EkhHiX8h8EqwqzbdoYGTufQdDTc7WU1/FDWiD+k
85725 8H/rD195L4mx/bxjWDeTmzj4t1up+thxx7S8gJeNbEvxUNUqKaqoGXqW5pWOdO2XCld19AXbbQs5
85726 uQF/qvbW2mzmBeCkTVL829B0txGMe41P/4eDrv8FAxNXUDf+jJZSEExfv5RxadmWPgxDT74wwJ85
85727 dE8GRV2j1lY5aAfMh09Qd5Nx2UQIsYo06Yms25tO4dnkUkWMLhQfkWsZHWgpLFbE4h4TV2TwYeO5
85728 Ed+w4VegG63XX9Gv2ystP9Bojg/qnw+LNVgbExz03jWhCl3W6t8Sb8D7aQdGctyB9gQjF+BNdeFy
85729 b7Ao65vh4YOhn0pdr8yb+gIgthhid5E7o9Vlrdx8kHccREGkSovrlXLp9glk3Kgtn3R46MGiCWOc
85730 76DbT52VqyBPt7D3h1ymoOQ3OMdc4zUPLK2jgKLsLl3Az+2LBcLmc272idX10kaO6m1jGx6KyX2m
85731 +Jzr5dVjhU1zZmkR/sgO9MHHZklTfuQZa/HpelmjbX7FF+Ynxu8b22/8DU0GAbQOXDBGVWCvOGU6
85732 yke6rCzMRh+yRpY/8+0mBe53oWprfi1tWFxK1I5nuPHa1UaKJ/kR8slC/k7e3x9cxKSGhxYzoacX
85733 GKUN5AXlK8IrC6KVkLn9YDxOiT7nnO4fuwECAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1Ud
85734 EwEB/wQFMAMBAf8wHQYDVR0OBBYEFOBNv9ybQV0T6GTwp+kVpOGBwboxMA0GCSqGSIb3DQEBCwUA
85735 A4ICAQBqinA4WbbaixjIvirTthnVZil6Xc1bL3McJk6jfW+rtylNpumlEYOnOXOvEESS5iVdT2H6
85736 yAa+Tkvv/vMx/sZ8cApBWNromUuWyXi8mHwCKe0JgOYKOoICKuLJL8hWGSbueBwj/feTZU7n85iY
85737 r83d2Z5AiDEoOqsuC7CsDCT6eiaY8xJhEPRdF/d+4niXVOKM6Cm6jBAyvd0zaziGfjk9DgNyp115
85738 j0WKWa5bIW4xRtVZjc8VX90xJc/bYNaBRHIpAlf2ltTW/+op2znFuCyKGo3Oy+dCMYYFaA6eFN0A
85739 kLppRQjbbpCBhqcqBT/mhDn4t/lXX0ykeVoQDF7Va/81XwVRHmyjdanPUIPTfPRm94KNPQx96N97
85740 qA4bLJyuQHCH2u2nFoJavjVsIE4iYdm8UXrNemHcSxH5/mc0zy4EZmFcV5cjjPOGG0jfKq+nwf/Y
85741 jj4Du9gqsPoUJbJRa4ZDhS4HIxaAjUz7tGM7zMN07RujHv41D198HRaG9Q7DlfEvr10lO1Hm13ZB
85742 ONFLAzkopR6RctR9q5czxNM+4Gm2KHmgCY0c0f9BckgG/Jou5yD5m6Leie2uPAmvylezkolwQOQv
85743 T8Jwg0DXJCxr5wkf09XHwQj02w47HAcLQxGEIYbpgNR12KvxAmLBsX5VYc8T1yaw15zLKYs4SgsO
85744 kI26oQ==
85745 -----END CERTIFICATE-----
85746
85747 COMODO RSA Certification Authority
85748 ==================================
85749 -----BEGIN CERTIFICATE-----
85750 MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCBhTELMAkGA1UE
85751 BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
85752 A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlv
85753 biBBdXRob3JpdHkwHhcNMTAwMTE5MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMC
85754 R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
85755 ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBB
85756 dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR6FSS0gpWsawNJN3Fz0Rn
85757 dJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8Xpz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZ
85758 FGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+
85759 5eNu/Nio5JIk2kNrYrhV/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pG
85760 x8cgoLEfZd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z+pUX
85761 2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7wqP/0uK3pN/u6uPQL
85762 OvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZahSL0896+1DSJMwBGB7FY79tOi4lu3
85763 sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVICu9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+C
85764 GCe01a60y1Dma/RMhnEw6abfFobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5
85765 WdYgGq/yapiqcrxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
85766 FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w
85767 DQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvlwFTPoCWOAvn9sKIN9SCYPBMt
85768 rFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+
85769 nq6PK7o9mfjYcwlYRm6mnPTXJ9OV2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSg
85770 tZx8jb8uk2IntznaFxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwW
85771 sRqZCuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiKboHGhfKp
85772 pC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmckejkk9u+UJueBPSZI9FoJA
85773 zMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yLS0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHq
85774 ZJx64SIDqZxubw5lT2yHh17zbqD5daWbQOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk52
85775 7RH89elWsn2/x20Kk4yl0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7I
85776 LaZRfyHBNVOFBkpdn627G190
85777 -----END CERTIFICATE-----
85778
85779 USERTrust RSA Certification Authority
85780 =====================================
85781 -----BEGIN CERTIFICATE-----
85782 MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCBiDELMAkGA1UE
85783 BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
85784 ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
85785 dGlvbiBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UE
85786 BhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQK
85787 ExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNh
85788 dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCAEmUXNg7D2wiz
85789 0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2j
85790 Y0K2dvKpOyuR+OJv0OwWIJAJPuLodMkYtJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFn
85791 RghRy4YUVD+8M/5+bJz/Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O
85792 +T23LLb2VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT79uq
85793 /nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6c0Plfg6lZrEpfDKE
85794 Y1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmTYo61Zs8liM2EuLE/pDkP2QKe6xJM
85795 lXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97lc6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8
85796 yexDJtC/QV9AqURE9JnnV4eeUB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+
85797 eLf8ZxXhyVeEHg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
85798 BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
85799 MAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPFUp/L+M+ZBn8b2kMVn54CVVeW
85800 FPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KOVWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ
85801 7l8wXEskEVX/JJpuXior7gtNn3/3ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQ
85802 Eg9zKC7F4iRO/Fjs8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM
85803 8WcRiQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYzeSf7dNXGi
85804 FSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZXHlKYC6SQK5MNyosycdi
85805 yA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9c
85806 J2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRBVXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGw
85807 sAvgnEzDHNb842m1R0aBL6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gx
85808 Q+6IHdfGjjxDah2nGN59PRbxYvnKkKj9
85809 -----END CERTIFICATE-----
85810
85811 USERTrust ECC Certification Authority
85812 =====================================
85813 -----BEGIN CERTIFICATE-----
85814 MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDELMAkGA1UEBhMC
85815 VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
85816 aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
85817 biBBdXRob3JpdHkwHhcNMTAwMjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMC
85818 VVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
85819 aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlv
85820 biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqfloI+d61SRvU8Za2EurxtW2
85821 0eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinngo4N+LZfQYcTxmdwlkWOrfzCjtHDix6Ez
85822 nPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0GA1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNV
85823 HQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBB
85824 HU6+4WMBzzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbWRNZu
85825 9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
85826 -----END CERTIFICATE-----
85827
85828 GlobalSign ECC Root CA - R4
85829 ===========================
85830 -----BEGIN CERTIFICATE-----
85831 MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEkMCIGA1UECxMb
85832 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
85833 EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
85834 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
85835 EwpHbG9iYWxTaWduMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprl
85836 OQcJFspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAwDgYDVR0P
85837 AQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61FuOJAf/sKbvu+M8k8o4TV
85838 MAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGXkPoUVy0D7O48027KqGx2vKLeuwIgJ6iF
85839 JzWbVsaj8kfSt24bAgAXqmemFZHe+pTsewv4n4Q=
85840 -----END CERTIFICATE-----
85841
85842 GlobalSign ECC Root CA - R5
85843 ===========================
85844 -----BEGIN CERTIFICATE-----
85845 MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEkMCIGA1UECxMb
85846 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
85847 EwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoXDTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMb
85848 R2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQD
85849 EwpHbG9iYWxTaWduMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6
85850 SFkc8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8kehOvRnkmS
85851 h5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAd
85852 BgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYIKoZIzj0EAwMDaAAwZQIxAOVpEslu28Yx
85853 uglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7
85854 yFz9SO8NdCKoCOJuxUnOxwy8p2Fp8fc74SrL+SvzZpA3
85855 -----END CERTIFICATE-----
85856
85857 Staat der Nederlanden Root CA - G3
85858 ==================================
85859 -----BEGIN CERTIFICATE-----
85860 MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
85861 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
85862 Um9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloXDTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMC
85863 TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
85864 ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4y
85865 olQPcPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WWIkYFsO2t
85866 x1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqXxz8ecAgwoNzFs21v0IJy
85867 EavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFyKJLZWyNtZrVtB0LrpjPOktvA9mxjeM3K
85868 Tj215VKb8b475lRgsGYeCasH/lSJEULR9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUur
85869 mkVLoR9BvUhTFXFkC4az5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU5
85870 1nus6+N86U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7Ngzp
85871 07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHPbMk7ccHViLVlvMDo
85872 FxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXtBznaqB16nzaeErAMZRKQFWDZJkBE
85873 41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTtXUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMB
85874 AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleu
85875 yjWcLhL75LpdINyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD
85876 U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwpLiniyMMB8jPq
85877 KqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8Ipf3YF3qKS9Ysr1YvY2WTxB1
85878 v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixpgZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA
85879 8KCWAg8zxXHzniN9lLf9OtMJgwYh/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b
85880 8KKaa8MFSu1BYBQw0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0r
85881 mj1AfsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq4BZ+Extq
85882 1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR1VmiiXTTn74eS9fGbbeI
85883 JG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/QFH1T/U67cjF68IeHRaVesd+QnGTbksV
85884 tzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM94B7IWcnMFk=
85885 -----END CERTIFICATE-----
85886
85887 Staat der Nederlanden EV Root CA
85888 ================================
85889 -----BEGIN CERTIFICATE-----
85890 MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJOTDEeMBwGA1UE
85891 CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
85892 RVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0yMjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5M
85893 MR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRl
85894 cmxhbmRlbiBFViBSb290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkk
85895 SzrSM4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nCUiY4iKTW
85896 O0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3dZ//BYY1jTw+bbRcwJu+r
85897 0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46prfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8
85898 Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13lpJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gV
85899 XJrm0w912fxBmJc+qiXbj5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr
85900 08C+eKxCKFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS/ZbV
85901 0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0XcgOPvZuM5l5Tnrmd
85902 74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH1vI4gnPah1vlPNOePqc7nvQDs/nx
85903 fRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrPpx9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNC
85904 MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwa
85905 ivsnuL8wbqg7MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI
85906 eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u2dfOWBfoqSmu
85907 c0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHSv4ilf0X8rLiltTMMgsT7B/Zq
85908 5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTCwPTxGfARKbalGAKb12NMcIxHowNDXLldRqAN
85909 b/9Zjr7dn3LDWyvfjFvO5QxGbJKyCqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tN
85910 f1zuacpzEPuKqf2evTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi
85911 5Dp6Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIaGl6I6lD4
85912 WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeLeG9QgkRQP2YGiqtDhFZK
85913 DyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGy
85914 eUN51q1veieQA6TqJIc/2b3Z6fJfUEkc7uzXLg==
85915 -----END CERTIFICATE-----
85916
85917 IdenTrust Commercial Root CA 1
85918 ==============================
85919 -----BEGIN CERTIFICATE-----
85920 MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBKMQswCQYDVQQG
85921 EwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBS
85922 b290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQwMTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzES
85923 MBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENB
85924 IDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ld
85925 hNlT3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU+ehcCuz/
85926 mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gpS0l4PJNgiCL8mdo2yMKi
85927 1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1bVoE/c40yiTcdCMbXTMTEl3EASX2MN0C
85928 XZ/g1Ue9tOsbobtJSdifWwLziuQkkORiT0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl
85929 3ZBWzvurpWCdxJ35UrCLvYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzy
85930 NeVJSQjKVsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZKdHzV
85931 WYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHTc+XvvqDtMwt0viAg
85932 xGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hvl7yTmvmcEpB4eoCHFddydJxVdHix
85933 uuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5NiGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
85934 AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZI
85935 hvcNAQELBQADggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH
85936 6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwtLRvM7Kqas6pg
85937 ghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93nAbowacYXVKV7cndJZ5t+qnt
85938 ozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3+wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmV
85939 YjzlVYA211QC//G5Xc7UI2/YRYRKW2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUX
85940 feu+h1sXIFRRk0pTAwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/ro
85941 kTLql1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG4iZZRHUe
85942 2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZmUlO+KWA2yUPHGNiiskz
85943 Z2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7R
85944 cGzM7vRX+Bi6hG6H
85945 -----END CERTIFICATE-----
85946
85947 IdenTrust Public Sector Root CA 1
85948 =================================
85949 -----BEGIN CERTIFICATE-----
85950 MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBNMQswCQYDVQQG
85951 EwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3Rv
85952 ciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcNMzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJV
85953 UzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBS
85954 b290IENBIDEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTy
85955 P4o7ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGyRBb06tD6
85956 Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlSbdsHyo+1W/CD80/HLaXI
85957 rcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF/YTLNiCBWS2ab21ISGHKTN9T0a9SvESf
85958 qy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoS
85959 mJxZZoY+rfGwyj4GD3vwEUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFn
85960 ol57plzy9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9VGxyh
85961 LrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ2fjXctscvG29ZV/v
85962 iDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsVWaFHVCkugyhfHMKiq3IXAAaOReyL
85963 4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gDW/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8B
85964 Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMw
85965 DQYJKoZIhvcNAQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj
85966 t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHVDRDtfULAj+7A
85967 mgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9TaDKQGXSc3z1i9kKlT/YPyNt
85968 GtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8GlwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFt
85969 m6/n6J91eEyrRjuazr8FGF1NFTwWmhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMx
85970 NRF4eKLg6TCMf4DfWN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4
85971 Mhn5+bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJtshquDDI
85972 ajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhAGaQdp/lLQzfcaFpPz+vC
85973 ZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ
85974 3Wl9af0AVqW3rLatt8o+Ae+c
85975 -----END CERTIFICATE-----
85976
85977 Entrust Root Certification Authority - G2
85978 =========================================
85979 -----BEGIN CERTIFICATE-----
85980 MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMCVVMxFjAUBgNV
85981 BAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVy
85982 bXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ug
85983 b25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIw
85984 HhcNMDkwNzA3MTcyNTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoT
85985 DUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMx
85986 OTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25s
85987 eTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwggEi
85988 MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP
85989 /vaCeb9zYQYKpSfYs1/TRU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXz
85990 HHfV1IWNcCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hWwcKU
85991 s/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1U1+cPvQXLOZprE4y
85992 TGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0jaWvYkxN4FisZDQSA/i2jZRjJKRx
85993 AgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ6
85994 0B7vfec7aVHUbI2fkBJmqzANBgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5Z
85995 iXMRrEPR9RP/jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
85996 Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v1fN2D807iDgi
85997 nWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4RnAuknZoh8/CbCzB428Hch0P+
85998 vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmHVHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xO
85999 e4pIb4tF9g==
86000 -----END CERTIFICATE-----
86001
86002 Entrust Root Certification Authority - EC1
86003 ==========================================
86004 -----BEGIN CERTIFICATE-----
86005 MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkGA1UEBhMCVVMx
86006 FjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVn
86007 YWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXpl
86008 ZCB1c2Ugb25seTEzMDEGA1UEAxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
86009 IC0gRUMxMB4XDTEyMTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYw
86010 FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2Fs
86011 LXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQg
86012 dXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt
86013 IEVDMTB2MBAGByqGSM49AgEGBSuBBAAiA2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHy
86014 AsWfoPZb1YsGGYZPUxBtByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef
86015 9eNi1KlHBz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
86016 FLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVCR98crlOZF7ZvHH3h
86017 vxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nXhTcGtXsI/esni0qU+eH6p44mCOh8
86018 kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
86019 -----END CERTIFICATE-----
86020
86021 CFCA EV ROOT
86022 ============
86023 -----BEGIN CERTIFICATE-----
86024 MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJDTjEwMC4GA1UE
86025 CgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNB
86026 IEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkxMjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEw
86027 MC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQD
86028 DAxDRkNBIEVWIFJPT1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnV
86029 BU03sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpLTIpTUnrD
86030 7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5/ZOkVIBMUtRSqy5J35DN
86031 uF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp7hZZLDRJGqgG16iI0gNyejLi6mhNbiyW
86032 ZXvKWfry4t3uMCz7zEasxGPrb382KzRzEpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7
86033 xzbh72fROdOXW3NiGUgthxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9f
86034 py25IGvPa931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqotaK8K
86035 gWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNgTnYGmE69g60dWIol
86036 hdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfVPKPtl8MeNPo4+QgO48BdK4PRVmrJ
86037 tqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hvcWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAf
86038 BgNVHSMEGDAWgBTj/i39KNALtbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB
86039 /wQEAwIBBjAdBgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB
86040 ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObTej/tUxPQ4i9q
86041 ecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdLjOztUmCypAbqTuv0axn96/Ua
86042 4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBSESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sG
86043 E5uPhnEFtC+NiWYzKXZUmhH4J/qyP5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfX
86044 BDrDMlI1Dlb4pd19xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjn
86045 aH9dCi77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN5mydLIhy
86046 PDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe/v5WOaHIz16eGWRGENoX
86047 kbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+ZAAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3C
86048 ekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
86049 -----END CERTIFICATE-----
86050
86051 TÜRKTRUST Elektronik Sertifika Hizmet Sağlayıcısı H5
86052 ====================================================
86053 -----BEGIN CERTIFICATE-----
86054 MIIEJzCCAw+gAwIBAgIHAI4X/iQggTANBgkqhkiG9w0BAQsFADCBsTELMAkGA1UEBhMCVFIxDzAN
86055 BgNVBAcMBkFua2FyYTFNMEsGA1UECgxEVMOcUktUUlVTVCBCaWxnaSDEsGxldGnFn2ltIHZlIEJp
86056 bGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7Fni4xQjBABgNVBAMMOVTDnFJLVFJVU1Qg
86057 RWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSBINTAeFw0xMzA0MzAw
86058 ODA3MDFaFw0yMzA0MjgwODA3MDFaMIGxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMU0w
86059 SwYDVQQKDERUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnE
86060 n2kgSGl6bWV0bGVyaSBBLsWeLjFCMEAGA1UEAww5VMOcUktUUlVTVCBFbGVrdHJvbmlrIFNlcnRp
86061 ZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIEg1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
86062 CgKCAQEApCUZ4WWe60ghUEoI5RHwWrom/4NZzkQqL/7hzmAD/I0Dpe3/a6i6zDQGn1k19uwsu537
86063 jVJp45wnEFPzpALFp/kRGml1bsMdi9GYjZOHp3GXDSHHmflS0yxjXVW86B8BSLlg/kJK9siArs1m
86064 ep5Fimh34khon6La8eHBEJ/rPCmBp+EyCNSgBbGM+42WAA4+Jd9ThiI7/PS98wl+d+yG6w8z5UNP
86065 9FR1bSmZLmZaQ9/LXMrI5Tjxfjs1nQ/0xVqhzPMggCTTV+wVunUlm+hkS7M0hO8EuPbJbKoCPrZV
86066 4jI3X/xml1/N1p7HIL9Nxqw/dV8c7TKcfGkAaZHjIxhT6QIDAQABo0IwQDAdBgNVHQ4EFgQUVpkH
86067 HtOsDGlktAxQR95DLL4gwPswDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
86068 hvcNAQELBQADggEBAJ5FdnsXSDLyOIspve6WSk6BGLFRRyDN0GSxDsnZAdkJzsiZ3GglE9Rc8qPo
86069 BP5yCccLqh0lVX6Wmle3usURehnmp349hQ71+S4pL+f5bFgWV1Al9j4uPqrtd3GqqpmWRgqujuwq
86070 URawXs3qZwQcWDD1YIq9pr1N5Za0/EKJAWv2cMhQOQwt1WbZyNKzMrcbGW3LM/nfpeYVhDfwwvJl
86071 lpKQd/Ct9JDpEXjXk4nAPQu6KfTomZ1yju2dL+6SfaHx/126M2CFYv4HAqGEVka+lgqaE9chTLd8
86072 B59OTj+RdPsnnRHM3eaxynFNExc5JsUpISuTKWqW+qtB4Uu2NQvAmxU=
86073 -----END CERTIFICATE-----
86074
86075 Certinomis - Root CA
86076 ====================
86077 -----BEGIN CERTIFICATE-----
86078 MIIFkjCCA3qgAwIBAgIBATANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJGUjETMBEGA1UEChMK
86079 Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxHTAbBgNVBAMTFENlcnRpbm9taXMg
86080 LSBSb290IENBMB4XDTEzMTAyMTA5MTcxOFoXDTMzMTAyMTA5MTcxOFowWjELMAkGA1UEBhMCRlIx
86081 EzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMR0wGwYDVQQDExRD
86082 ZXJ0aW5vbWlzIC0gUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANTMCQos
86083 P5L2fxSeC5yaah1AMGT9qt8OHgZbn1CF6s2Nq0Nn3rD6foCWnoR4kkjW4znuzuRZWJflLieY6pOo
86084 d5tK8O90gC3rMB+12ceAnGInkYjwSond3IjmFPnVAy//ldu9n+ws+hQVWZUKxkd8aRi5pwP5ynap
86085 z8dvtF4F/u7BUrJ1Mofs7SlmO/NKFoL21prbcpjp3vDFTKWrteoB4owuZH9kb/2jJZOLyKIOSY00
86086 8B/sWEUuNKqEUL3nskoTuLAPrjhdsKkb5nPJWqHZZkCqqU2mNAKthH6yI8H7KsZn9DS2sJVqM09x
86087 RLWtwHkziOC/7aOgFLScCbAK42C++PhmiM1b8XcF4LVzbsF9Ri6OSyemzTUK/eVNfaoqoynHWmgE
86088 6OXWk6RiwsXm9E/G+Z8ajYJJGYrKWUM66A0ywfRMEwNvbqY/kXPLynNvEiCL7sCCeN5LLsJJwx3t
86089 FvYk9CcbXFcx3FXuqB5vbKziRcxXV4p1VxngtViZSTYxPDMBbRZKzbgqg4SGm/lg0h9tkQPTYKbV
86090 PZrdd5A9NaSfD171UkRpucC63M9933zZxKyGIjK8e2uR73r4F2iw4lNVYC2vPsKD2NkJK/DAZNuH
86091 i5HMkesE/Xa0lZrmFAYb1TQdvtj/dBxThZngWVJKYe2InmtJiUZ+IFrZ50rlau7SZRFDAgMBAAGj
86092 YzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTvkUz1pcMw6C8I
86093 6tNxIqSSaHh02TAfBgNVHSMEGDAWgBTvkUz1pcMw6C8I6tNxIqSSaHh02TANBgkqhkiG9w0BAQsF
86094 AAOCAgEAfj1U2iJdGlg+O1QnurrMyOMaauo++RLrVl89UM7g6kgmJs95Vn6RHJk/0KGRHCwPT5iV
86095 WVO90CLYiF2cN/z7ZMF4jIuaYAnq1fohX9B0ZedQxb8uuQsLrbWwF6YSjNRieOpWauwK0kDDPAUw
86096 Pk2Ut59KA9N9J0u2/kTO+hkzGm2kQtHdzMjI1xZSg081lLMSVX3l4kLr5JyTCcBMWwerx20RoFAX
86097 lCOotQqSD7J6wWAsOMwaplv/8gzjqh8c3LigkyfeY+N/IZ865Z764BNqdeuWXGKRlI5nU7aJ+BIJ
86098 y29SWwNyhlCVCNSNh4YVH5Uk2KRvms6knZtt0rJ2BobGVgjF6wnaNsIbW0G+YSrjcOa4pvi2WsS9
86099 Iff/ql+hbHY5ZtbqTFXhADObE5hjyW/QASAJN1LnDE8+zbz1X5YnpyACleAu6AdBBR8Vbtaw5Bng
86100 DwKTACdyxYvRVB9dSsNAl35VpnzBMwQUAR1JIGkLGZOdblgi90AMRgwjY/M50n92Uaf0yKHxDHYi
86101 I0ZSKS3io0EHVmmY0gUJvGnHWmHNj4FgFU2A3ZDifcRQ8ow7bkrHxuaAKzyBvBGAFhAn1/DNP3nM
86102 cyrDflOR1m749fPH0FFNjkulW+YZFzvWgQncItzujrnEj1PhZ7szuIgVRs/taTX/dQ1G885x4cVr
86103 hkIGuUE=
86104 -----END CERTIFICATE-----
86105
86106 OISTE WISeKey Global Root GB CA
86107 ===============================
86108 -----BEGIN CERTIFICATE-----
86109 MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBtMQswCQYDVQQG
86110 EwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl
86111 ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAw
86112 MzJaFw0zOTEyMDExNTEwMzFaMG0xCzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYD
86113 VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEds
86114 b2JhbCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3HEokKtaX
86115 scriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGxWuR51jIjK+FTzJlFXHtP
86116 rby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk
86117 9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNku7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4o
86118 Qnc/nSMbsrY9gBQHTC5P99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvg
86119 GUpuuy9rM2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
86120 /zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZI
86121 hvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrghcViXfa43FK8+5/ea4n32cZiZBKpD
86122 dHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0
86123 VQreUGdNZtGn//3ZwLWoo4rOZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEui
86124 HZeeevJuQHHfaPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic
86125 Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM=
86126 -----END CERTIFICATE-----
86127
86128 Certification Authority of WoSign G2
86129 ====================================
86130 -----BEGIN CERTIFICATE-----
86131 MIIDfDCCAmSgAwIBAgIQayXaioidfLwPBbOxemFFRDANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQG
86132 EwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxLTArBgNVBAMTJENlcnRpZmljYXRpb24g
86133 QXV0aG9yaXR5IG9mIFdvU2lnbiBHMjAeFw0xNDExMDgwMDU4NThaFw00NDExMDgwMDU4NThaMFgx
86134 CzAJBgNVBAYTAkNOMRowGAYDVQQKExFXb1NpZ24gQ0EgTGltaXRlZDEtMCsGA1UEAxMkQ2VydGlm
86135 aWNhdGlvbiBBdXRob3JpdHkgb2YgV29TaWduIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
86136 CgKCAQEAvsXEoCKASU+/2YcRxlPhuw+9YH+v9oIOH9ywjj2X4FA8jzrvZjtFB5sg+OPXJYY1kBai
86137 XW8wGQiHC38Gsp1ij96vkqVg1CuAmlI/9ZqD6TRay9nVYlzmDuDfBpgOgHzKtB0TiGsOqCR3A9Du
86138 W/PKaZE1OVbFbeP3PU9ekzgkyhjpJMuSA93MHD0JcOQg5PGurLtzaaNjOg9FD6FKmsLRY6zLEPg9
86139 5k4ot+vElbGs/V6r+kHLXZ1L3PR8du9nfwB6jdKgGlxNIuG12t12s9R23164i5jIFFTMaxeSt+BK
86140 v0mUYQs4kI9dJGwlezt52eJ+na2fmKEG/HgUYFf47oB3sQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMC
86141 AQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU+mCp62XF3RYUCE4MD42b4Pdkr2cwDQYJKoZI
86142 hvcNAQELBQADggEBAFfDejaCnI2Y4qtAqkePx6db7XznPWZaOzG73/MWM5H8fHulwqZm46qwtyeY
86143 P0nXYGdnPzZPSsvxFPpahygc7Y9BMsaV+X3avXtbwrAh449G3CE4Q3RM+zD4F3LBMvzIkRfEzFg3
86144 TgvMWvchNSiDbGAtROtSjFA9tWwS1/oJu2yySrHFieT801LYYRf+epSEj3m2M1m6D8QL4nCgS3gu
86145 +sif/a+RZQp4OBXllxcU3fngLDT4ONCEIgDAFFEYKwLcMFrw6AF8NTojrwjkr6qOKEJJLvD1mTS+
86146 7Q9LGOHSJDy7XUe3IfKN0QqZjuNuPq1w4I+5ysxugTH2e5x6eeRncRg=
86147 -----END CERTIFICATE-----
86148
86149 CA WoSign ECC Root
86150 ==================
86151 -----BEGIN CERTIFICATE-----
86152 MIICCTCCAY+gAwIBAgIQaEpYcIBr8I8C+vbe6LCQkDAKBggqhkjOPQQDAzBGMQswCQYDVQQGEwJD
86153 TjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxGzAZBgNVBAMTEkNBIFdvU2lnbiBFQ0MgUm9v
86154 dDAeFw0xNDExMDgwMDU4NThaFw00NDExMDgwMDU4NThaMEYxCzAJBgNVBAYTAkNOMRowGAYDVQQK
86155 ExFXb1NpZ24gQ0EgTGltaXRlZDEbMBkGA1UEAxMSQ0EgV29TaWduIEVDQyBSb290MHYwEAYHKoZI
86156 zj0CAQYFK4EEACIDYgAE4f2OuEMkq5Z7hcK6C62N4DrjJLnSsb6IOsq/Srj57ywvr1FQPEd1bPiU
86157 t5v8KB7FVMxjnRZLU8HnIKvNrCXSf4/CwVqCXjCLelTOA7WRf6qU0NGKSMyCBSah1VES1ns2o0Iw
86158 QDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUqv3VWqP2h4syhf3R
86159 MluARZPzA7gwCgYIKoZIzj0EAwMDaAAwZQIxAOSkhLCB1T2wdKyUpOgOPQB0TKGXa/kNUTyh2Tv0
86160 Daupn75OcsqF1NnstTJFGG+rrQIwfcf3aWMvoeGY7xMQ0Xk/0f7qO3/eVvSQsRUR2LIiFdAvwyYu
86161 a/GRspBl9JrmkO5K
86162 -----END CERTIFICATE-----
86163
86164 SZAFIR ROOT CA2
86165 ===============
86166 -----BEGIN CERTIFICATE-----
86167 MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQELBQAwUTELMAkG
86168 A1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6ZW5pb3dhIFMuQS4xGDAWBgNV
86169 BAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkwNzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJ
86170 BgNVBAYTAlBMMSgwJgYDVQQKDB9LcmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYD
86171 VQQDDA9TWkFGSVIgUk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5Q
86172 qEvNQLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT3PSQ1hNK
86173 DJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw3gAeqDRHu5rr/gsUvTaE
86174 2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr63fE9biCloBK0TXC5ztdyO4mTp4CEHCdJ
86175 ckm1/zuVnsHMyAHs6A6KCpbns6aH5db5BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwi
86176 ieDhZNRnvDF5YTy7ykHNXGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
86177 AQH/BAQDAgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsFAAOC
86178 AQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw8PRBEew/R40/cof5
86179 O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOGnXkZ7/e7DDWQw4rtTw/1zBLZpD67
86180 oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCPoky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul
86181 4+vJhaAlIDf7js4MNIThPIGyd05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6
86182 +/NNIxuZMzSgLvWpCz/UXeHPhJ/iGcJfitYgHuNztw==
86183 -----END CERTIFICATE-----
86184
86185 Certum Trusted Network CA 2
86186 ===========================
86187 -----BEGIN CERTIFICATE-----
86188 MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCBgDELMAkGA1UE
86189 BhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMuQS4xJzAlBgNVBAsTHkNlcnR1
86190 bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIGA1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29y
86191 ayBDQSAyMCIYDzIwMTExMDA2MDgzOTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQ
86192 TDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENl
86193 cnRpZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENB
86194 IDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWADGSdhhuWZGc/IjoedQF9
86195 7/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+o
86196 CgCXhVqqndwpyeI1B+twTUrWwbNWuKFBOJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40b
86197 Rr5HMNUuctHFY9rnY3lEfktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2p
86198 uTRZCr+ESv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1mo130
86199 GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02isx7QBlrd9pPPV3WZ
86200 9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOWOZV7bIBaTxNyxtd9KXpEulKkKtVB
86201 Rgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgezTv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pye
86202 hizKV/Ma5ciSixqClnrDvFASadgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vM
86203 BhBgu4M1t15n3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
86204 AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZI
86205 hvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQF/xlhMcQSZDe28cmk4gmb3DW
86206 Al45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTfCVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuA
86207 L55MYIR4PSFk1vtBHxgP58l1cb29XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMo
86208 clm2q8KMZiYcdywmdjWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tM
86209 pkT/WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jbAoJnwTnb
86210 w3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksqP/ujmv5zMnHCnsZy4Ypo
86211 J/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Kob7a6bINDd82Kkhehnlt4Fj1F4jNy3eFm
86212 ypnTycUm/Q1oBEauttmbjL4ZvrHG8hnjXALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLX
86213 is7VmFxWlgPF7ncGNf/P5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7
86214 zAYspsbiDrW5viSP
86215 -----END CERTIFICATE-----
86216
86217 Hellenic Academic and Research Institutions RootCA 2015
86218 =======================================================
86219 -----BEGIN CERTIFICATE-----
86220 MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcT
86221 BkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0
86222 aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNl
86223 YXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAx
86224 MTIxWjCBpjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMg
86225 QWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNV
86226 BAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9vdENBIDIw
86227 MTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDC+Kk/G4n8PDwEXT2QNrCROnk8Zlrv
86228 bTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+eh
86229 iGsxr/CL0BgzuNtFajT0AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+
86230 6PAQZe104S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06CojXd
86231 FPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV9Cz82XBST3i4vTwr
86232 i5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrDgfgXy5I2XdGj2HUb4Ysn6npIQf1F
86233 GQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2
86234 fu/Z8VFRfS0myGlZYeCsargqNhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9mu
86235 iNX6hME6wGkoLfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc
86236 Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
86237 AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVdctA4GGqd83EkVAswDQYJKoZI
86238 hvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0IXtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+
86239 D1hYc2Ryx+hFjtyp8iY/xnmMsVMIM4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrM
86240 d/K4kPFox/la/vot9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+y
86241 d+2VZ5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/eaj8GsGsVn
86242 82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnhX9izjFk0WaSrT2y7Hxjb
86243 davYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQl033DlZdwJVqwjbDG2jJ9SrcR5q+ss7F
86244 Jej6A7na+RZukYT1HCjI/CbM1xyQVqdfbzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVt
86245 J94Cj8rDtSvK6evIIVM4pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGa
86246 JI7ZjnHKe7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0vm9q
86247 p/UsQu0yrbYhnr68
86248 -----END CERTIFICATE-----
86249
86250 Hellenic Academic and Research Institutions ECC RootCA 2015
86251 ===========================================================
86252 -----BEGIN CERTIFICATE-----
86253 MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzANBgNVBAcTBkF0
86254 aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9u
86255 cyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJj
86256 aCBJbnN0aXR1dGlvbnMgRUNDIFJvb3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEw
86257 MzcxMlowgaoxCzAJBgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmlj
86258 IEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUQwQgYD
86259 VQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIEVDQyBSb290
86260 Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKgQehLgoRc4vgxEZmGZE4JJS+dQS8KrjVP
86261 dJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJajq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoK
86262 Vlp8aQuqgAkkbH7BRqNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
86263 BBYEFLQiC4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaeplSTA
86264 GiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7SofTUwJCA3sS61kFyjn
86265 dc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR
86266 -----END CERTIFICATE-----
86267
86268 Certplus Root CA G1
86269 ===================
86270 -----BEGIN CERTIFICATE-----
86271 MIIFazCCA1OgAwIBAgISESBVg+QtPlRWhS2DN7cs3EYRMA0GCSqGSIb3DQEBDQUAMD4xCzAJBgNV
86272 BAYTAkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMTAe
86273 Fw0xNDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhD
86274 ZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMTCCAiIwDQYJKoZIhvcNAQEBBQAD
86275 ggIPADCCAgoCggIBANpQh7bauKk+nWT6VjOaVj0W5QOVsjQcmm1iBdTYj+eJZJ+622SLZOZ5KmHN
86276 r49aiZFluVj8tANfkT8tEBXgfs+8/H9DZ6itXjYj2JizTfNDnjl8KvzsiNWI7nC9hRYt6kuJPKNx
86277 Qv4c/dMcLRC4hlTqQ7jbxofaqK6AJc96Jh2qkbBIb6613p7Y1/oA/caP0FG7Yn2ksYyy/yARujVj
86278 BYZHYEMzkPZHogNPlk2dT8Hq6pyi/jQu3rfKG3akt62f6ajUeD94/vI4CTYd0hYCyOwqaK/1jpTv
86279 LRN6HkJKHRUxrgwEV/xhc/MxVoYxgKDEEW4wduOU8F8ExKyHcomYxZ3MVwia9Az8fXoFOvpHgDm2
86280 z4QTd28n6v+WZxcIbekN1iNQMLAVdBM+5S//Ds3EC0pd8NgAM0lm66EYfFkuPSi5YXHLtaW6uOrc
86281 4nBvCGrch2c0798wct3zyT8j/zXhviEpIDCB5BmlIOklynMxdCm+4kLV87ImZsdo/Rmz5yCTmehd
86282 4F6H50boJZwKKSTUzViGUkAksnsPmBIgJPaQbEfIDbsYIC7Z/fyL8inqh3SV4EJQeIQEQWGw9CEj
86283 jy3LKCHyamz0GqbFFLQ3ZU+V/YDI+HLlJWvEYLF7bY5KinPOWftwenMGE9nTdDckQQoRb5fc5+R+
86284 ob0V8rqHDz1oihYHAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0G
86285 A1UdDgQWBBSowcCbkahDFXxdBie0KlHYlwuBsTAfBgNVHSMEGDAWgBSowcCbkahDFXxdBie0KlHY
86286 lwuBsTANBgkqhkiG9w0BAQ0FAAOCAgEAnFZvAX7RvUz1isbwJh/k4DgYzDLDKTudQSk0YcbX8ACh
86287 66Ryj5QXvBMsdbRX7gp8CXrc1cqh0DQT+Hern+X+2B50ioUHj3/MeXrKls3N/U/7/SMNkPX0XtPG
86288 YX2eEeAC7gkE2Qfdpoq3DIMku4NQkv5gdRE+2J2winq14J2by5BSS7CTKtQ+FjPlnsZlFT5kOwQ/
86289 2wyPX1wdaR+v8+khjPPvl/aatxm2hHSco1S1cE5j2FddUyGbQJJD+tZ3VTNPZNX70Cxqjm0lpu+F
86290 6ALEUz65noe8zDUa3qHpimOHZR4RKttjd5cUvpoUmRGywO6wT/gUITJDT5+rosuoD6o7BlXGEilX
86291 CNQ314cnrUlZp5GrRHpejXDbl85IULFzk/bwg2D5zfHhMf1bfHEhYxQUqq/F3pN+aLHsIqKqkHWe
86292 tUNy6mSjhEv9DKgma3GX7lZjZuhCVPnHHd/Qj1vfyDBviP4NxDMcU6ij/UgQ8uQKTuEVV/xuZDDC
86293 VRHc6qnNSlSsKWNEz0pAoNZoWRsz+e86i9sgktxChL8Bq4fA1SCC28a5g4VCXA9DO2pJNdWY9BW/
86294 +mGBDAkgGNLQFwzLSABQ6XaCjGTXOqAHVcweMcDvOrRl++O/QmueD6i9a5jc2NvLi6Td11n0bt3+
86295 qsOR0C5CB8AMTVPNJLFMWx5R9N/pkvo=
86296 -----END CERTIFICATE-----
86297
86298 Certplus Root CA G2
86299 ===================
86300 -----BEGIN CERTIFICATE-----
86301 MIICHDCCAaKgAwIBAgISESDZkc6uo+jF5//pAq/Pc7xVMAoGCCqGSM49BAMDMD4xCzAJBgNVBAYT
86302 AkZSMREwDwYDVQQKDAhDZXJ0cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMjAeFw0x
86303 NDA1MjYwMDAwMDBaFw0zODAxMTUwMDAwMDBaMD4xCzAJBgNVBAYTAkZSMREwDwYDVQQKDAhDZXJ0
86304 cGx1czEcMBoGA1UEAwwTQ2VydHBsdXMgUm9vdCBDQSBHMjB2MBAGByqGSM49AgEGBSuBBAAiA2IA
86305 BM0PW1aC3/BFGtat93nwHcmsltaeTpwftEIRyoa/bfuFo8XlGVzX7qY/aWfYeOKmycTbLXku54uN
86306 Am8xIk0G42ByRZ0OQneezs/lf4WbGOT8zC5y0xaTTsqZY1yhBSpsBqNjMGEwDgYDVR0PAQH/BAQD
86307 AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMB8GA1Ud
86308 IwQYMBaAFNqDYwJ5jtpMxjwjFNiPwyCrKGBZMAoGCCqGSM49BAMDA2gAMGUCMHD+sAvZ94OX7PNV
86309 HdTcswYO/jOYnYs5kGuUIe22113WTNchp+e/IQ8rzfcq3IUHnQIxAIYUFuXcsGXCwI4Un78kFmjl
86310 vPl5adytRSv3tjFzzAalU5ORGpOucGpnutee5WEaXw==
86311 -----END CERTIFICATE-----
86312
86313 OpenTrust Root CA G1
86314 ====================
86315 -----BEGIN CERTIFICATE-----
86316 MIIFbzCCA1egAwIBAgISESCzkFU5fX82bWTCp59rY45nMA0GCSqGSIb3DQEBCwUAMEAxCzAJBgNV
86317 BAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcx
86318 MB4XDTE0MDUyNjA4NDU1MFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoM
86319 CU9wZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzEwggIiMA0GCSqGSIb3DQEB
86320 AQUAA4ICDwAwggIKAoICAQD4eUbalsUwXopxAy1wpLuwxQjczeY1wICkES3d5oeuXT2R0odsN7fa
86321 Yp6bwiTXj/HbpqbfRm9RpnHLPhsxZ2L3EVs0J9V5ToybWL0iEA1cJwzdMOWo010hOHQX/uMftk87
86322 ay3bfWAfjH1MBcLrARYVmBSO0ZB3Ij/swjm4eTrwSSTilZHcYTSSjFR077F9jAHiOH3BX2pfJLKO
86323 YheteSCtqx234LSWSE9mQxAGFiQD4eCcjsZGT44ameGPuY4zbGneWK2gDqdkVBFpRGZPTBKnjix9
86324 xNRbxQA0MMHZmf4yzgeEtE7NCv82TWLxp2NX5Ntqp66/K7nJ5rInieV+mhxNaMbBGN4zK1FGSxyO
86325 9z0M+Yo0FMT7MzUj8czxKselu7Cizv5Ta01BG2Yospb6p64KTrk5M0ScdMGTHPjgniQlQ/GbI4Kq
86326 3ywgsNw2TgOzfALU5nsaqocTvz6hdLubDuHAk5/XpGbKuxs74zD0M1mKB3IDVedzagMxbm+WG+Oi
86327 n6+Sx+31QrclTDsTBM8clq8cIqPQqwWyTBIjUtz9GVsnnB47ev1CI9sjgBPwvFEVVJSmdz7QdFG9
86328 URQIOTfLHzSpMJ1ShC5VkLG631UAC9hWLbFJSXKAqWLXwPYYEQRVzXR7z2FwefR7LFxckvzluFqr
86329 TJOVoSfupb7PcSNCupt2LQIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
86330 /zAdBgNVHQ4EFgQUl0YhVyE12jZVx/PxN3DlCPaTKbYwHwYDVR0jBBgwFoAUl0YhVyE12jZVx/Px
86331 N3DlCPaTKbYwDQYJKoZIhvcNAQELBQADggIBAB3dAmB84DWn5ph76kTOZ0BP8pNuZtQ5iSas000E
86332 PLuHIT839HEl2ku6q5aCgZG27dmxpGWX4m9kWaSW7mDKHyP7Rbr/jyTwyqkxf3kfgLMtMrpkZ2Cv
86333 uVnN35pJ06iCsfmYlIrM4LvgBBuZYLFGZdwIorJGnkSI6pN+VxbSFXJfLkur1J1juONI5f6ELlgK
86334 n0Md/rcYkoZDSw6cMoYsYPXpSOqV7XAp8dUv/TW0V8/bhUiZucJvbI/NeJWsZCj9VrDDb8O+WVLh
86335 X4SPgPL0DTatdrOjteFkdjpY3H1PXlZs5VVZV6Xf8YpmMIzUUmI4d7S+KNfKNsSbBfD4Fdvb8e80
86336 nR14SohWZ25g/4/Ii+GOvUKpMwpZQhISKvqxnUOOBZuZ2mKtVzazHbYNeS2WuOvyDEsMpZTGMKcm
86337 GS3tTAZQMPH9WD25SxdfGbRqhFS0OE85og2WaMMolP3tLR9Ka0OWLpABEPs4poEL0L9109S5zvE/
86338 bw4cHjdx5RiHdRk/ULlepEU0rbDK5uUTdg8xFKmOLZTW1YVNcxVPS/KyPu1svf0OnWZzsD2097+o
86339 4BGkxK51CUpjAEggpsadCwmKtODmzj7HPiY46SvepghJAwSQiumPv+i2tCqjI40cHLI5kqiPAlxA
86340 OXXUc0ECd97N4EOH1uS6SsNsEn/+KuYj1oxx
86341 -----END CERTIFICATE-----
86342
86343 OpenTrust Root CA G2
86344 ====================
86345 -----BEGIN CERTIFICATE-----
86346 MIIFbzCCA1egAwIBAgISESChaRu/vbm9UpaPI+hIvyYRMA0GCSqGSIb3DQEBDQUAMEAxCzAJBgNV
86347 BAYTAkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEcy
86348 MB4XDTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoM
86349 CU9wZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzIwggIiMA0GCSqGSIb3DQEB
86350 AQUAA4ICDwAwggIKAoICAQDMtlelM5QQgTJT32F+D3Y5z1zCU3UdSXqWON2ic2rxb95eolq5cSG+
86351 Ntmh/LzubKh8NBpxGuga2F8ORAbtp+Dz0mEL4DKiltE48MLaARf85KxP6O6JHnSrT78eCbY2albz
86352 4e6WiWYkBuTNQjpK3eCasMSCRbP+yatcfD7J6xcvDH1urqWPyKwlCm/61UWY0jUJ9gNDlP7ZvyCV
86353 eYCYitmJNbtRG6Q3ffyZO6v/v6wNj0OxmXsWEH4db0fEFY8ElggGQgT4hNYdvJGmQr5J1WqIP7wt
86354 UdGejeBSzFfdNTVY27SPJIjki9/ca1TSgSuyzpJLHB9G+h3Ykst2Z7UJmQnlrBcUVXDGPKBWCgOz
86355 3GIZ38i1MH/1PCZ1Eb3XG7OHngevZXHloM8apwkQHZOJZlvoPGIytbU6bumFAYueQ4xncyhZW+vj
86356 3CzMpSZyYhK05pyDRPZRpOLAeiRXyg6lPzq1O4vldu5w5pLeFlwoW5cZJ5L+epJUzpM5ChaHvGOz
86357 9bGTXOBut9Dq+WIyiET7vycotjCVXRIouZW+j1MY5aIYFuJWpLIsEPUdN6b4t/bQWVyJ98LVtZR0
86358 0dX+G7bw5tYee9I8y6jj9RjzIR9u701oBnstXW5DiabA+aC/gh7PU3+06yzbXfZqfUAkBXKJOAGT
86359 y3HCOV0GEfZvePg3DTmEJwIDAQABo2MwYTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
86360 /zAdBgNVHQ4EFgQUajn6QiL35okATV59M4PLuG53hq8wHwYDVR0jBBgwFoAUajn6QiL35okATV59
86361 M4PLuG53hq8wDQYJKoZIhvcNAQENBQADggIBAJjLq0A85TMCl38th6aP1F5Kr7ge57tx+4BkJamz
86362 Gj5oXScmp7oq4fBXgwpkTx4idBvpkF/wrM//T2h6OKQQbA2xx6R3gBi2oihEdqc0nXGEL8pZ0keI
86363 mUEiyTCYYW49qKgFbdEfwFFEVn8nNQLdXpgKQuswv42hm1GqO+qTRmTFAHneIWv2V6CG1wZy7HBG
86364 S4tz3aAhdT7cHcCP009zHIXZ/n9iyJVvttN7jLpTwm+bREx50B1ws9efAvSyB7DH5fitIw6mVskp
86365 EndI2S9G/Tvw/HRwkqWOOAgfZDC2t0v7NqwQjqBSM2OdAzVWxWm9xiNaJ5T2pBL4LTM8oValX9YZ
86366 6e18CL13zSdkzJTaTkZQh+D5wVOAHrut+0dSixv9ovneDiK3PTNZbNTe9ZUGMg1RGUFcPk8G97kr
86367 gCf2o6p6fAbhQ8MTOWIaNr3gKC6UAuQpLmBVrkA9sHSSXvAgZJY/X0VdiLWK2gKgW0VU3jg9CcCo
86368 SmVGFvyqv1ROTVu+OEO3KMqLM6oaJbolXCkvW0pujOotnCr2BXbgd5eAiN1nE28daCSLT7d0geX0
86369 YJ96Vdc+N9oWaz53rK4YcJUIeSkDiv7BO7M/Gg+kO14fWKGVyasvc0rQLW6aWQ9VGHgtPFGml4vm
86370 u7JwqkwR3v98KzfUetF3NI/n+UL3PIEMS1IK
86371 -----END CERTIFICATE-----
86372
86373 OpenTrust Root CA G3
86374 ====================
86375 -----BEGIN CERTIFICATE-----
86376 MIICITCCAaagAwIBAgISESDm+Ez8JLC+BUCs2oMbNGA/MAoGCCqGSM49BAMDMEAxCzAJBgNVBAYT
86377 AkZSMRIwEAYDVQQKDAlPcGVuVHJ1c3QxHTAbBgNVBAMMFE9wZW5UcnVzdCBSb290IENBIEczMB4X
86378 DTE0MDUyNjAwMDAwMFoXDTM4MDExNTAwMDAwMFowQDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCU9w
86379 ZW5UcnVzdDEdMBsGA1UEAwwUT3BlblRydXN0IFJvb3QgQ0EgRzMwdjAQBgcqhkjOPQIBBgUrgQQA
86380 IgNiAARK7liuTcpm3gY6oxH84Bjwbhy6LTAMidnW7ptzg6kjFYwvWYpa3RTqnVkrQ7cG7DK2uu5B
86381 ta1doYXM6h0UZqNnfkbilPPntlahFVmhTzeXuSIevRHr9LIfXsMUmuXZl5mjYzBhMA4GA1UdDwEB
86382 /wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAf
86383 BgNVHSMEGDAWgBRHd8MUi2I5DMlv4VBN0BBY3JWIbTAKBggqhkjOPQQDAwNpADBmAjEAj6jcnboM
86384 BBf6Fek9LykBl7+BFjNAk2z8+e2AcG+qj9uEwov1NcoG3GRvaBbhj5G5AjEA2Euly8LQCGzpGPta
86385 3U1fJAuwACEl74+nBCZx4nxp5V2a+EEfOzmTk51V6s2N8fvB
86386 -----END CERTIFICATE-----
86387
86388 ISRG Root X1
86389 ============
86390 -----BEGIN CERTIFICATE-----
86391 MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAwTzELMAkGA1UE
86392 BhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2VhcmNoIEdyb3VwMRUwEwYDVQQD
86393 EwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQG
86394 EwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMT
86395 DElTUkcgUm9vdCBYMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54r
86396 Vygch77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+0TM8ukj1
86397 3Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6UA5/TR5d8mUgjU+g4rk8K
86398 b4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sWT8KOEUt+zwvo/7V3LvSye0rgTBIlDHCN
86399 Aymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyHB5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ
86400 4Q7e2RCOFvu396j3x+UCB5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf
86401 1b0SHzUvKBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWnOlFu
86402 hjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTnjh8BCNAw1FtxNrQH
86403 usEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbwqHyGO0aoSCqI3Haadr8faqU9GY/r
86404 OPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CIrU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4G
86405 A1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY
86406 9umbbjANBgkqhkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
86407 ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ3BebYhtF8GaV
86408 0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KKNFtY2PwByVS5uCbMiogziUwt
86409 hDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJw
86410 TdwJx4nLCgdNbOhdjsnvzqvHu7UrTkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nx
86411 e5AW0wdeRlN8NwdCjNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZA
86412 JzVcoyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq4RgqsahD
86413 YVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPAmRGunUHBcnWEvgJBQl9n
86414 JEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57demyPxgcYxn/eR44/KJ4EBs+lVDR3veyJ
86415 m+kXQ99b21/+jh5Xos1AnX5iItreGCc=
86416 -----END CERTIFICATE-----
86417
86418 AC RAIZ FNMT-RCM
86419 ================
86420 -----BEGIN CERTIFICATE-----
86421 MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsxCzAJBgNVBAYT
86422 AkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTAeFw0wODEw
86423 MjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJD
86424 TTEZMBcGA1UECwwQQUMgUkFJWiBGTk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
86425 ggIBALpxgHpMhm5/yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcf
86426 qQgfBBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAzWHFctPVr
86427 btQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxFtBDXaEAUwED653cXeuYL
86428 j2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z374jNUUeAlz+taibmSXaXvMiwzn15Cou
86429 08YfxGyqxRxqAQVKL9LFwag0Jl1mpdICIfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mw
86430 WsXmo8RZZUc1g16p6DULmbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnT
86431 tOmlcYF7wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peSMKGJ
86432 47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2ZSysV4999AeU14EC
86433 ll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMetUqIJ5G+GR4of6ygnXYMgrwTJbFaa
86434 i0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
86435 FPd9xf3E6Jobd2Sn9R2gzL+HYJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1o
86436 dHRwOi8vd3d3LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD
86437 nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1RXxlDPiyN8+s
86438 D8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYMLVN0V2Ue1bLdI4E7pWYjJ2cJ
86439 j+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrT
86440 Qfv6MooqtyuGC2mDOL7Nii4LcK2NJpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW
86441 +YJF1DngoABd15jmfZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7
86442 Ixjp6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp1txyM/1d
86443 8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B9kiABdcPUXmsEKvU7ANm
86444 5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wokRqEIr9baRRmW1FMdW4R58MD3R++Lj8UG
86445 rp1MYp3/RgT408m2ECVAdf4WqslKYIYvuu8wd+RU4riEmViAqhOLUTpPSPaLtrM=
86446 -----END CERTIFICATE-----
86447
86448 Amazon Root CA 1
86449 ================
86450 -----BEGIN CERTIFICATE-----
86451 MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsFADA5MQswCQYD
86452 VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAxMB4XDTE1
86453 MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
86454 bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
86455 ggEBALJ4gHHKeNXjca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgH
86456 FzZM9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qwIFAGbHrQ
86457 gLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6VOujw5H5SNz/0egwLX0t
86458 dHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L93FcXmn/6pUCyziKrlA4b9v7LWIbxcce
86459 VOF34GfID5yHI9Y/QCB/IIDEgEw+OyQmjgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB
86460 /zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3
86461 DQEBCwUAA4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDIU5PM
86462 CCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUsN+gDS63pYaACbvXy
86463 8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vvo/ufQJVtMVT8QtPHRh8jrdkPSHCa
86464 2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2
86465 xJNDd2ZhwLnoQdeXeGADbkpyrqXRfboQnoZsG4q5WTP468SQvvG5
86466 -----END CERTIFICATE-----
86467
86468 Amazon Root CA 2
86469 ================
86470 -----BEGIN CERTIFICATE-----
86471 MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwFADA5MQswCQYD
86472 VQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAyMB4XDTE1
86473 MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpv
86474 bjEZMBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoC
86475 ggIBAK2Wny2cSkxKgXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4
86476 kHbZW0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg1dKmSYXp
86477 N+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K8nu+NQWpEjTj82R0Yiw9
86478 AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvd
86479 fLC6HM783k81ds8P+HgfajZRRidhW+mez/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAEx
86480 kv8LV/SasrlX6avvDXbR8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSS
86481 btqDT6ZjmUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz7Mt0
86482 Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6+XUyo05f7O0oYtlN
86483 c/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI0u1ufm8/0i2BWSlmy5A5lREedCf+
86484 3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSw
86485 DPBMMPQFWAJI/TPlUq9LhONmUjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oA
86486 A7CXDpO8Wqj2LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
86487 +gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kSk5Nrp+gvU5LE
86488 YFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl7uxMMne0nxrpS10gxdr9HIcW
86489 xkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygmbtmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQ
86490 gj9sAq+uEjonljYE1x2igGOpm/HlurR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbW
86491 aQbLU8uz/mtBzUF+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoV
86492 Yh63n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE76KlXIx3
86493 KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H9jVlpNMKVv/1F2Rs76gi
86494 JUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT4PsJYGw=
86495 -----END CERTIFICATE-----
86496
86497 Amazon Root CA 3
86498 ================
86499 -----BEGIN CERTIFICATE-----
86500 MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5MQswCQYDVQQG
86501 EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSAzMB4XDTE1MDUy
86502 NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
86503 MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZB
86504 f8ANm+gBG1bG8lKlui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjr
86505 Zt6jQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSrttvXBp43
86506 rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkrBqWTrBqYaGFy+uGh0Psc
86507 eGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteMYyRIHN8wfdVoOw==
86508 -----END CERTIFICATE-----
86509
86510 Amazon Root CA 4
86511 ================
86512 -----BEGIN CERTIFICATE-----
86513 MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5MQswCQYDVQQG
86514 EwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24gUm9vdCBDQSA0MB4XDTE1MDUy
86515 NjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZ
86516 MBcGA1UEAxMQQW1hem9uIFJvb3QgQ0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN
86517 /sGKe0uoe0ZLY7Bi9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri
86518 83BkM6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
86519 HQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WBMAoGCCqGSM49BAMDA2gA
86520 MGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlwCkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1
86521 AE47xDqUEpHJWEadIRNyp4iciuRMStuW1KyLa2tJElMzrdfkviT8tQp21KW8EA==
86522 -----END CERTIFICATE-----
86523
86524 LuxTrust Global Root 2
86525 ======================
86526 -----BEGIN CERTIFICATE-----
86527 MIIFwzCCA6ugAwIBAgIUCn6m30tEntpqJIWe5rgV0xZ/u7EwDQYJKoZIhvcNAQELBQAwRjELMAkG
86528 A1UEBhMCTFUxFjAUBgNVBAoMDUx1eFRydXN0IFMuQS4xHzAdBgNVBAMMFkx1eFRydXN0IEdsb2Jh
86529 bCBSb290IDIwHhcNMTUwMzA1MTMyMTU3WhcNMzUwMzA1MTMyMTU3WjBGMQswCQYDVQQGEwJMVTEW
86530 MBQGA1UECgwNTHV4VHJ1c3QgUy5BLjEfMB0GA1UEAwwWTHV4VHJ1c3QgR2xvYmFsIFJvb3QgMjCC
86531 AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANeFl78RmOnwYoNMPIf5U2o3C/IPPIfOb9wm
86532 Kb3FibrJgz337spbxm1Jc7TJRqMbNBM/wYlFV/TZsfs2ZUv7COJIcRHIbjuend+JZTemhfY7RBi2
86533 xjcwYkSSl2l9QjAk5A0MiWtj3sXh306pFGxT4GHO9hcvHTy95iJMHZP1EMShduxq3sVs35a0VkBC
86534 wGKSMKEtFZSg0iAGCW5qbeXrt77U8PEVfIvmTroTzEsnXpk8F12PgX8zPU/TPxvsXD/wPEx1bvKm
86535 1Z3aLQdjAsZy6ZS8TEmVT4hSyNvoaYL4zDRbIvCGp4m9SAptZoFtyMhk+wHh9OHe2Z7d21vUKpkm
86536 FRseTJIpgp7VkoGSQXAZ96Tlk0u8d2cx3Rz9MXANF5kM+Qw5GSoXtTBxVdUPrljhPS80m8+f9niF
86537 wpN6cj5mj5wWEWCPnolvZ77gR1o7DJpni89Gxq44o/KnvObWhWszJHAiS8sIm7vI+AIpHb4gDEa/
86538 a4ebsypmQjVGbKq6rfmYe+lQVRQxv7HaLe2ArWgk+2mr2HETMOZns4dA/Yl+8kPREd8vZS9kzl8U
86539 ubG/Mb2HeFpZZYiq/FkySIbWTLkpS5XTdvN3JW1CHDiDTf2jX5t/Lax5Gw5CMZdjpPuKadUiDTSQ
86540 MC6otOBttpSsvItO13D8xTiOZCXhTTmQzsmHhFhxAgMBAAGjgagwgaUwDwYDVR0TAQH/BAUwAwEB
86541 /zBCBgNVHSAEOzA5MDcGByuBKwEBAQowLDAqBggrBgEFBQcCARYeaHR0cHM6Ly9yZXBvc2l0b3J5
86542 Lmx1eHRydXN0Lmx1MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBT/GCh2+UgFLKGu8SsbK7JT
86543 +Et8szAdBgNVHQ4EFgQU/xgodvlIBSyhrvErGyuyU/hLfLMwDQYJKoZIhvcNAQELBQADggIBAGoZ
86544 FO1uecEsh9QNcH7X9njJCwROxLHOk3D+sFTAMs2ZMGQXvw/l4jP9BzZAcg4atmpZ1gDlaCDdLnIN
86545 H2pkMSCEfUmmWjfrRcmF9dTHF5kH5ptV5AzoqbTOjFu1EVzPig4N1qx3gf4ynCSecs5U89BvolbW
86546 7MM3LGVYvlcAGvI1+ut7MV3CwRI9loGIlonBWVx65n9wNOeD4rHh4bhY79SV5GCc8JaXcozrhAIu
86547 ZY+kt9J/Z93I055cqqmkoCUUBpvsT34tC38ddfEz2O3OuHVtPlu5mB0xDVbYQw8wkbIEa91WvpWA
86548 VWe+2M2D2RjuLg+GLZKecBPs3lHJQ3gCpU3I+V/EkVhGFndadKpAvAefMLmx9xIX3eP/JEAdemrR
86549 TxgKqpAd60Ae36EeRJIQmvKN4dFLRp7oRUKX6kWZ8+xm1QL68qZKJKrezrnK+T+Tb/mjuuqlPpmt
86550 /f97mfVl7vBZKGfXkJWkE4SphMHozs51k2MavDzq1WQfLSoSOcbDWjLtR5EWDrw4wVDej8oqkDQc
86551 7kGUnF4ZLvhFSZl0kbAEb+MEWrGrKqv+x9CWttrhSmQGbmBNvUJO/3jaJMobtNeWOWyu8Q6qp31I
86552 iyBMz2TWuJdGsE7RKlY6oJO9r4Ak4Ap+58rVyuiFVdw2KuGUaJPHZnJED4AhMmwlxyOAgwrr
86553 -----END CERTIFICATE-----
86554
86555 TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
86556 =============================================
86557 -----BEGIN CERTIFICATE-----
86558 MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIxGDAWBgNVBAcT
86559 D0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxpbXNlbCB2ZSBUZWtub2xvamlr
86560 IEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0wKwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24g
86561 TWVya2V6aSAtIEthbXUgU00xNjA0BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRp
86562 ZmlrYXNpIC0gU3VydW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYD
86563 VQQGEwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXllIEJpbGlt
86564 c2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklUQUsxLTArBgNVBAsTJEth
86565 bXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBTTTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11
86566 IFNNIFNTTCBLb2sgU2VydGlmaWthc2kgLSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
86567 MIIBCgKCAQEAr3UwM6q7a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y8
86568 6Ij5iySrLqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INrN3wc
86569 wv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2XYacQuFWQfw4tJzh0
86570 3+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/iSIzL+aFCr2lqBs23tPcLG07xxO9
86571 WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4fAJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQU
86572 ZT/HiobGPN08VFw1+DrtUgxHV8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
86573 KoZIhvcNAQELBQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh
86574 AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPfIPP54+M638yc
86575 lNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4lzwDGrpDxpa5RXI4s6ehlj2R
86576 e37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0j
86577 q5Rm+K37DwhuJi1/FwcJsoz7UMCflo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM=
86578 -----END CERTIFICATE-----
86579 <?php
86580
86581 if (PHP_SAPI !== 'cli') {
86582     echo 'Warning: Composer should be invoked via the CLI version of PHP, not the '.PHP_SAPI.' SAPI'.PHP_EOL;
86583 }
86584
86585 require __DIR__.'/../src/bootstrap.php';
86586
86587 use Composer\Factory;
86588 use Composer\XdebugHandler;
86589 use Composer\Console\Application;
86590
86591 error_reporting(-1);
86592
86593 // Create output for XdebugHandler and Application
86594 $output = Factory::createOutput();
86595
86596 $xdebug = new XdebugHandler($output);
86597 $xdebug->check();
86598 unset($xdebug);
86599
86600 if (function_exists('ini_set')) {
86601     @ini_set('display_errors', 1);
86602
86603     $memoryInBytes = function ($value) {
86604         $unit = strtolower(substr($value, -1, 1));
86605         $value = (int) $value;
86606         switch($unit) {
86607             case 'g':
86608                 $value *= 1024;
86609                 // no break (cumulative multiplier)
86610             case 'm':
86611                 $value *= 1024;
86612                 // no break (cumulative multiplier)
86613             case 'k':
86614                 $value *= 1024;
86615         }
86616
86617         return $value;
86618     };
86619
86620     $memoryLimit = trim(ini_get('memory_limit'));
86621     // Increase memory_limit if it is lower than 1.5GB
86622     if ($memoryLimit != -1 && $memoryInBytes($memoryLimit) < 1024 * 1024 * 1536) {
86623         @ini_set('memory_limit', '1536M');
86624     }
86625     unset($memoryInBytes, $memoryLimit);
86626 }
86627
86628 putenv('COMPOSER_BINARY='.realpath($_SERVER['argv'][0]));
86629
86630 // run the command application
86631 $application = new Application();
86632 $application->run(null, $output);
86633
86634 Copyright (c) Nils Adermann, Jordi Boggiano
86635
86636 Permission is hereby granted, free of charge, to any person obtaining a copy
86637 of this software and associated documentation files (the "Software"), to deal
86638 in the Software without restriction, including without limitation the rights
86639 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
86640 copies of the Software, and to permit persons to whom the Software is furnished
86641 to do so, subject to the following conditions:
86642
86643 The above copyright notice and this permission notice shall be included in all
86644 copies or substantial portions of the Software.
86645
86646 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
86647 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
86648 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
86649 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
86650 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
86651 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
86652 THE SOFTWARE.
86653
86654 fL¸Ú¬\9b\10â×·t\16\94<þÓ«Ê\ 2\0\0\0GBMB